diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..412eeda78dc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..fa8446d1109 --- /dev/null +++ b/.gitignore @@ -0,0 +1,82 @@ +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover +*.ldf + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + +############ +## DNN +############ + +[Dd]esktop[Mm]odules\DNNCorp +[Dd]esktop[Mm]odules\DNNCorp\HTML +[Dd]esktop[Mm]odules\DNNCorp\RazorModules +[Dd]esktop[Mm]odules\DNNCorp + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini diff --git a/DNN Platform/Components/ClientDependency/Source/BaseLoader.cs b/DNN Platform/Components/ClientDependency/Source/BaseLoader.cs new file mode 100644 index 00000000000..12634e0e792 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/BaseLoader.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using ClientDependency.Core.Controls; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.Config; +using System.Configuration.Provider; +using System.Runtime.CompilerServices; + +//Make a 'friend' to mvc app +[assembly: InternalsVisibleTo("ClientDependency.Core.Mvc")] + +namespace ClientDependency.Core +{ + + public class BaseLoader + { + + public BaseLoader(HttpContextBase http) + { + CurrentContext = http; + } + + protected HttpContextBase CurrentContext { get; private set; } + + public BaseFileRegistrationProvider Provider { get; set; } + + /// + /// Tracks all dependencies and maintains a deduplicated list + /// + internal List Dependencies = new List(); + /// + /// Tracks all paths and maintains a deduplicated list + /// + internal HashSet Paths = new HashSet(); + + /// + /// Adds a path to the current loader + /// + /// + /// + /// Returns the current loader instance so you can chain calls together + public BaseLoader AddPath(string pathNameAlias, string path) + { + AddPath(new BasicPath() { Name = pathNameAlias, Path = path }); + return this; + } + + /// + /// Adds a path to the current loader + /// + /// + /// Returns the current loader instance so you can chain calls together + public BaseLoader AddPath(IClientDependencyPath path) + { + Paths.Add(path); + return this; + } + + /// + /// Registers dependencies with the specified provider. + /// + /// + /// + /// + /// + /// + /// This is the top most overloaded method + /// + public void RegisterClientDependencies(BaseFileRegistrationProvider provider, IEnumerable dependencies, IEnumerable paths, ProviderCollection currProviders) + { + //find or create the ProviderDependencyList for the provider + ProviderDependencyList currList = Dependencies + .Where(x => x.ProviderIs(provider)) + .DefaultIfEmpty(new ProviderDependencyList(provider)) + .SingleOrDefault(); + + //add the dependencies that don't have a provider specified + currList.AddDependencies(dependencies + .Where(x => string.IsNullOrEmpty(x.ForceProvider))); + + //add the list if it is new + if (!Dependencies.Contains(currList) && currList.Dependencies.Count > 0) + Dependencies.Add(currList); + + //we need to look up all of the dependencies that have forced providers, + //check if we've got a provider list for it, create one if not and add the dependencies + //to it. + var allProviderNamesInList = dependencies + .Select(x => x.ForceProvider) + .Where(x => !string.IsNullOrEmpty(x)) + .Distinct(); + var forceProviders = (from provName in allProviderNamesInList + where currProviders[provName] != null + select (BaseFileRegistrationProvider) currProviders[provName]).ToList(); + foreach (var prov in forceProviders) + { + //find or create the ProviderDependencyList for the prov + var p = prov; + var forceList = Dependencies + .Where(x => x.ProviderIs(prov)) + .DefaultIfEmpty(new ProviderDependencyList(prov)) + .SingleOrDefault(); + //add the dependencies that don't have a force provider specified + forceList.AddDependencies(dependencies + .Where(x => x.ForceProvider == p.Name)); + //add the list if it is new + if (!Dependencies.Contains(forceList)) + Dependencies.Add(forceList); + } + + //add the paths, ensure no dups + Paths.UnionWith(paths); + } + + public void RegisterClientDependencies(List dependencies, params IClientDependencyPath[] paths) + { + RegisterClientDependencies(Provider, dependencies, paths, ClientDependencySettings.Instance.MvcRendererCollection); + } + + public void RegisterClientDependencies(List dependencies, IEnumerable paths) + { + RegisterClientDependencies(Provider, dependencies, paths, ClientDependencySettings.Instance.MvcRendererCollection); + } + + + + #region RegisterDependency overloads + + public void RegisterDependency(string filePath, ClientDependencyType type) + { + RegisterDependency(filePath, "", type); + } + + public void RegisterDependency(string filePath, ClientDependencyType type, object htmlAttributes) + { + RegisterDependency(filePath, "", type, htmlAttributes); + } + + public void RegisterDependency(int priority, string filePath, ClientDependencyType type) + { + RegisterDependency(priority, filePath, "", type); + } + + public void RegisterDependency(int priority, string filePath, ClientDependencyType type, object htmlAttributes) + { + RegisterDependency(priority, filePath, "", type, htmlAttributes); + } + + public void RegisterDependency(string filePath, string pathNameAlias, ClientDependencyType type) + { + RegisterDependency(Constants.DefaultPriority, filePath, pathNameAlias, type); + } + + public void RegisterDependency(string filePath, string pathNameAlias, ClientDependencyType type, object htmlAttributes) + { + RegisterDependency(Constants.DefaultPriority, filePath, pathNameAlias, type, htmlAttributes); + } + + /// + /// Dynamically registers a dependency into the loader at runtime. + /// This is similar to ScriptManager.RegisterClientScriptInclude. + /// Registers a file dependency with the default provider. + /// + /// + /// + /// + /// + public void RegisterDependency(int priority, string filePath, string pathNameAlias, ClientDependencyType type) + { + RegisterDependency(Constants.DefaultGroup, priority, filePath, pathNameAlias, type); + } + + public void RegisterDependency(int priority, string filePath, string pathNameAlias, ClientDependencyType type, object htmlAttributes) + { + RegisterDependency(Constants.DefaultGroup, priority, filePath, pathNameAlias, type, htmlAttributes); + } + + public void RegisterDependency(int group, int priority, string filePath, string pathNameAlias, ClientDependencyType type) + { + IClientDependencyFile file = new BasicFile(type) { Group = group, Priority = priority, FilePath = filePath, PathNameAlias = pathNameAlias }; + RegisterClientDependencies(new List { file }, new List()); //send an empty paths collection + } + + public void RegisterDependency(int group, int priority, string filePath, string pathNameAlias, ClientDependencyType type, object htmlAttributes) + { + var file = new BasicFile(type) { Group = group, Priority = priority, FilePath = filePath, PathNameAlias = pathNameAlias }; + + //now add the attributes to the list + foreach(var d in htmlAttributes.ToDictionary()) + { + file.HtmlAttributes.Add(d.Key, d.Value.ToString()); + } + + RegisterClientDependencies(new List { file }, new List()); //send an empty paths collection + } + + #endregion + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/BasicFile.cs b/DNN Platform/Components/ClientDependency/Source/BasicFile.cs new file mode 100644 index 00000000000..de58c3d9636 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/BasicFile.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core +{ + public class BasicFile : IClientDependencyFile, IHaveHtmlAttributes + { + public BasicFile(ClientDependencyType type) + { + DependencyType = type; + HtmlAttributes = new Dictionary(); + } + + #region IClientDependencyFile Members + + public string FilePath { get; set; } + public ClientDependencyType DependencyType { get; private set; } + public int Priority { get; set; } + public int Group { get; set; } + public string PathNameAlias { get; set; } + /// + /// This can be empty and will use default provider + /// + public string ForceProvider { get; set; } + public bool ForceBundle { get; set; } + + /// + /// Used to store additional attributes in the HTML markup for the item + /// + /// + /// Mostly used for CSS Media, but could be for anything + /// + public IDictionary HtmlAttributes { get; private set; } + + #endregion + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/BasicPath.cs b/DNN Platform/Components/ClientDependency/Source/BasicPath.cs new file mode 100644 index 00000000000..e81410bae42 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/BasicPath.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; + +namespace ClientDependency.Core +{ + public class BasicPath : IClientDependencyPath + { + public BasicPath() { } + public BasicPath(string name, string path) + { + Name = name; + Path = path; + } + + public string Name { get; set; } + public string Path { get; set; } + public bool ForceBundle { get; set; } + } +} + diff --git a/DNN Platform/Components/ClientDependency/Source/ClientDependency.Core.csproj b/DNN Platform/Components/ClientDependency/Source/ClientDependency.Core.csproj new file mode 100644 index 00000000000..ce281d23658 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ClientDependency.Core.csproj @@ -0,0 +1,166 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {3B64E72E-63CC-4A90-ADFF-4B919EF17239} + Library + Properties + ClientDependency.Core + ClientDependency.Core + v4.0 + 512 + SAK + SAK + SAK + SAK + + + 3.5 + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\ + TRACE;MVC + prompt + 4 + AllRules.ruleset + + + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/ClientDependencyAttribute.cs b/DNN Platform/Components/ClientDependency/Source/ClientDependencyAttribute.cs new file mode 100644 index 00000000000..ab383282548 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ClientDependencyAttribute.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClientDependency.Core +{ + /// + /// This attribute is used for data types that uses client assets like Javascript and CSS for liveediting. + /// The Live Editing feature in umbraco will look for this attribute and preload all dependencies to the page + /// to ensure that all client events and assets gets loaded + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class ClientDependencyAttribute : Attribute, IClientDependencyFile, IRequiresHtmlAttributesParsing + { + public ClientDependencyAttribute() + { + Priority = Constants.DefaultPriority; + Group = Constants.DefaultGroup; + PathNameAlias = ""; + HtmlAttributes = new Dictionary(); + } + + public ClientDependencyAttribute(ClientDependencyType dependencyType, string fullFilePath) + : this(Constants.DefaultPriority, dependencyType, fullFilePath, string.Empty) + { } + + public ClientDependencyAttribute(ClientDependencyType dependencyType, string fileName, string pathNameAlias) + : this(Constants.DefaultPriority, dependencyType, fileName, pathNameAlias) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// The file path to the dependency. + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string fullFilePath) + : this(priority, dependencyType, fullFilePath, string.Empty) + { } + + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// + /// + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string fileName, string pathNameAlias) + : this(Constants.DefaultGroup, priority, dependencyType, fileName, pathNameAlias, false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The priority. + /// Type of the dependency. + /// + /// + public ClientDependencyAttribute(int group, int priority, ClientDependencyType dependencyType, string fileName, string pathNameAlias, bool forceBundle) + { + if (String.IsNullOrEmpty(fileName)) + throw new ArgumentNullException("fileName"); + + Priority = priority; + + Group = group; + + FilePath = fileName; + PathNameAlias = pathNameAlias; + + DependencyType = dependencyType; + ForceBundle = forceBundle; + + HtmlAttributes = new Dictionary(); + } + + + /// + /// Gets or sets the priority. + /// + /// The priority. + public int Priority { get; set; } + + /// + /// Gets or sets the group. + /// + /// The group. + public int Group { get; set; } + + /// + /// This can be empty and will use default provider + /// + public string ForceProvider { get; set; } + + public bool ForceBundle { get; set; } + + /// + /// Gets or sets the file path. + /// + /// The file path. + public string FilePath { get; set; } + + /// + /// The path alias to be pre-pended to the file path if specified. + /// The alias is specified in in the ClientDependencyHelper constructor. + /// If the alias specified does not exist in the ClientDependencyHelper + /// path collection, an exception is thrown. + /// + public string PathNameAlias { get; set; } + + /// + /// Used to set the HtmlAttributes on this class via a string which is parsed + /// + /// + /// The syntax for the string must be: key1:value1,key2:value2 etc... + /// + public string HtmlAttributesAsString { get; set; } + + /// + /// Used to store additional attributes in the HTML markup for the item + /// + /// + /// Mostly used for CSS Media, but could be for anything + /// + public IDictionary HtmlAttributes { get; private set; } + + /// + /// Gets or sets the type of the dependency. + /// + /// The type of the dependency. + public ClientDependencyType DependencyType { get; set; } + } + + +} diff --git a/DNN Platform/Components/ClientDependency/Source/ClientDependencyType.cs b/DNN Platform/Components/ClientDependency/Source/ClientDependencyType.cs new file mode 100644 index 00000000000..47fa3b63357 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ClientDependencyType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClientDependency.Core +{ + /// + /// The type of client file + /// + public enum ClientDependencyType + { + Javascript, Css + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CSSMin.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CSSMin.cs new file mode 100644 index 00000000000..b7462372317 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CSSMin.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace ClientDependency.Core.CompositeFiles +{ + public class CssMin + { + + public static string CompressCSS(string body) + { + body = Regex.Replace(body, @"[\n\r]+\s*", string.Empty); + body = Regex.Replace(body, @"\s+", " "); + body = Regex.Replace(body, @"\s?([:,;{}])\s?", "$1"); + body = Regex.Replace(body, @"([\s:]0)(px|pt|%|em)", "$1"); + body = Regex.Replace(body, @"/\*[\d\D]*?\*/", string.Empty); + return body; + + } + + } + +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeDependencyHandler.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeDependencyHandler.cs new file mode 100644 index 00000000000..4b1fc73e780 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeDependencyHandler.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.Web; +using System.Reflection; +using System.IO; +using System.Linq; +using ClientDependency.Core.CompositeFiles.Providers; +using ClientDependency.Core.Config; +using System.Text; +using System.Web.Security; + +namespace ClientDependency.Core.CompositeFiles +{ + public class CompositeDependencyHandler : IHttpHandler + { + private readonly static object Lock = new object(); + + /// + /// When building composite includes, it creates a Base64 encoded string of all of the combined dependency file paths + /// for a given composite group. If this group contains too many files, then the file path with the query string will be very long. + /// This is the maximum allowed number of characters that there is allowed, otherwise an exception is thrown. + /// + /// + /// If this handler path needs to change, it can be changed by setting it in the global.asax on application start + /// + public static int MaxHandlerUrlLength = 2048; + + bool IHttpHandler.IsReusable + { + get + { + return true; + } + } + + void IHttpHandler.ProcessRequest(HttpContext context) + { + var contextBase = new HttpContextWrapper(context); + + ClientDependencyType type; + string fileset; + int version = 0; + + if (string.IsNullOrEmpty(context.Request.PathInfo)) + { + // querystring format + fileset = context.Request["s"]; + if (!string.IsNullOrEmpty(context.Request["cdv"]) && !Int32.TryParse(context.Request["cdv"], out version)) + throw new ArgumentException("Could not parse the version in the request"); + try + { + type = (ClientDependencyType)Enum.Parse(typeof(ClientDependencyType), context.Request["t"], true); + } + catch + { + throw new ArgumentException("Could not parse the type set in the request"); + } + } + else + { + + // path format + var segs = context.Request.PathInfo.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + fileset = ""; + int i = 0; + while (i < segs.Length - 1) + fileset += segs[i++]; + int pos; + pos = segs[i].IndexOf('.'); + if (pos < 0) + throw new ArgumentException("Could not parse the type set in the request"); + fileset += segs[i].Substring(0, pos); + string ext = segs[i].Substring(pos + 1); + pos = ext.IndexOf('.'); + if (pos > 0) + { + if (!Int32.TryParse(ext.Substring(0, pos), out version)) + throw new ArgumentException("Could not parse the version in the request"); + ext = ext.Substring(pos + 1); + } + ext = ext.ToLower(); + if (ext == "js") + type = ClientDependencyType.Javascript; + else if (ext == "css") + type = ClientDependencyType.Css; + else + throw new ArgumentException("Could not parse the type set in the request"); + + } + + fileset = context.Server.UrlDecode(fileset); + + if (string.IsNullOrEmpty(fileset)) + throw new ArgumentException("Must specify a fileset in the request"); + + byte[] outputBytes = null; + + //retry up to 5 times... this is only here due to a bug found in another website that was returning a blank + //result. To date, it can't be replicated in VS, but we'll leave it here for error handling support... can't hurt + for (int i = 0; i < 5; i++) + { + outputBytes = ProcessRequestInternal(contextBase, fileset, type, version, outputBytes); + if (outputBytes != null && outputBytes.Length > 0) + break; + + ClientDependencySettings.Instance.Logger.Error(string.Format("No bytes were returned, this is attempt {0}. Fileset: {1}, Type: {2}, Version: {3}", i, fileset, type, version), null); + } + + if (outputBytes == null || outputBytes.Length == 0) + { + ClientDependencySettings.Instance.Logger.Fatal(string.Format("No bytes were returned after 5 attempts. Fileset: {0}, Type: {1}, Version: {2}", fileset, type, version), null); + List fDefs; + outputBytes = GetCombinedFiles(contextBase, fileset, type, out fDefs); + } + + context.Response.ContentType = type == ClientDependencyType.Javascript ? "application/x-javascript" : "text/css"; + context.Response.OutputStream.Write(outputBytes, 0, outputBytes.Length); + } + + internal byte[] ProcessRequestInternal(HttpContextBase context, string fileset, ClientDependencyType type, int version, byte[] outputBytes) + { + //get the compression type supported + var clientCompression = context.GetClientCompression(); + + //get the map to the composite file for this file set, if it exists. + var map = ClientDependencySettings.Instance.DefaultFileMapProvider.GetCompositeFile(fileset, version, clientCompression.ToString()); + + string compositeFileName = ""; + if (map != null && map.HasFileBytes) + { + ProcessFromFile(context, map, out compositeFileName, out outputBytes); + } + else + { + lock (Lock) + { + //check again... + if (map != null && map.HasFileBytes) + { + //there's files there now, so process them + ProcessFromFile(context, map, out compositeFileName, out outputBytes); + } + else + { + List fileDefinitions; + byte[] fileBytes; + + if (ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.UrlType == CompositeUrlType.MappedId) + { + //need to try to find the map by it's id/version (not compression) + var filePaths = ClientDependencySettings.Instance.DefaultFileMapProvider.GetDependentFiles(fileset, version); + + if (filePaths == null) + { + throw new KeyNotFoundException("no map was found for the dependency key: " + fileset + + " ,CompositeUrlType.MappedId requires that a map is found"); + } + + //combine files and get the definition types of them (internal vs external resources) + fileBytes = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider + .CombineFiles(filePaths.ToArray(), context, type, out fileDefinitions); + } + else + { + //need to do the combining, etc... and save the file map + fileBytes = GetCombinedFiles(context, fileset, type, out fileDefinitions); + } + + //compress data + outputBytes = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.CompressBytes(clientCompression, fileBytes); + context.AddCompressionResponseHeader(clientCompression); + + //save combined file + var compositeFile = ClientDependencySettings.Instance + .DefaultCompositeFileProcessingProvider + .SaveCompositeFile(outputBytes, type, context.Server, version); + + if (compositeFile != null) + { + compositeFileName = compositeFile.FullName; + if (!string.IsNullOrEmpty(compositeFileName)) + { + //Update the XML file map + ClientDependencySettings.Instance.DefaultFileMapProvider.CreateUpdateMap(fileset, clientCompression.ToString(), + fileDefinitions.Select(x => new BasicFile(type) { FilePath = x.Uri }).Cast(), + compositeFileName, + version); + } + } + } + } + } + + SetCaching(context, compositeFileName, fileset, clientCompression); + return outputBytes; + } + + private byte[] GetCombinedFiles(HttpContextBase context, string fileset, ClientDependencyType type, out List fDefs) + { + //get the file list + string[] filePaths = fileset.DecodeFrom64Url().Split(';'); + //combine files and get the definition types of them (internal vs external resources) + return ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.CombineFiles(filePaths, context, type, out fDefs); + } + + private void ProcessFromFile(HttpContextBase context, CompositeFileMap map, out string compositeFileName, out byte[] outputBytes) + { + //the saved file's bytes are already compressed. + outputBytes = map.GetCompositeFileBytes(); + compositeFileName = map.CompositeFileName; + CompressionType cType = (CompressionType)Enum.Parse(typeof(CompressionType), map.CompressionType); + context.AddCompressionResponseHeader(cType); + } + + /// + /// Sets the output cache parameters and also the client side caching parameters + /// + /// + /// The name of the file that has been saved to disk + /// The Base64 encoded string supplied in the query string for the handler + /// + private void SetCaching(HttpContextBase context, string fileName, string fileset, CompressionType compressionType) + { + if (string.IsNullOrEmpty(fileName)) + { + ClientDependencySettings.Instance.Logger.Error("ClientDependency handler path is null", new Exception()); + return; + } + + //This ensures OutputCaching is set for this handler and also controls + //client side caching on the browser side. Default is 10 days. + var duration = TimeSpan.FromDays(10); + var cache = context.Response.Cache; + cache.SetCacheability(HttpCacheability.Public); + + cache.SetExpires(DateTime.Now.Add(duration)); + cache.SetMaxAge(duration); + cache.SetValidUntilExpires(true); + cache.SetLastModified(DateTime.Now); + + cache.SetETag("\"" + FormsAuthentication.HashPasswordForStoringInConfigFile(fileset + compressionType.ToString(), "MD5") + "\""); + + //set server OutputCache to vary by our params + + /* // proper way to do it is to have + * cache.SetVaryByCustom("cdparms"); + * + * // then have this in global.asax + * public override string GetVaryByCustomString(HttpContext context, string arg) + * { + * if (arg == "cdparms") + * { + * if (string.IsNullOrEmpty(context.Request.PathInfo)) + * { + * // querystring format + * return context.Request["s"] + "+" + context.Request["t"] + "+" + (context.Request["v"] ?? "0"); + * } + * else + * { + * // path format + * return context.Request.PathInfo.Replace('/', ''); + * } + * } + * } + * + * // that way, there would be one cache entry for both querystring and path formats. + * // but, it requires a global.asax and I can't find a way to do without it. + */ + + // in any case, cache already varies by pathInfo (build-in) so for path formats, we do not need anything + // just add params for querystring format, just in case... + cache.VaryByParams["t"] = true; + cache.VaryByParams["s"] = true; + cache.VaryByParams["cdv"] = true; + + //ensure the cache is different based on the encoding specified per browser + cache.VaryByContentEncodings["gzip"] = true; + cache.VaryByContentEncodings["deflate"] = true; + + //don't allow varying by wildcard + cache.SetOmitVaryStar(true); + //ensure client browser maintains strict caching rules + cache.AppendCacheExtension("must-revalidate, proxy-revalidate"); + + //This is the only way to set the max-age cachability header in ASP.Net! + //FieldInfo maxAgeField = cache.GetType().GetField("_maxAge", BindingFlags.Instance | BindingFlags.NonPublic); + //maxAgeField.SetValue(cache, duration); + + //make this output cache dependent on the file if there is one. + if (!string.IsNullOrEmpty(fileName)) + context.Response.AddFileDependency(fileName); + } + + } +} + diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileDefinition.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileDefinition.cs new file mode 100644 index 00000000000..9504fd56afa --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileDefinition.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.Config; +using System.IO; +using System.Web; +using System.Net; +using System.IO.Compression; + +namespace ClientDependency.Core.CompositeFiles +{ + /// + /// A simple class defining a Uri string and whether or not it is a local application file + /// + public class CompositeFileDefinition + { + public CompositeFileDefinition(string uri, bool isLocalFile) + { + IsLocalFile = isLocalFile; + Uri = uri; + } + public bool IsLocalFile { get; set; } + public string Uri { get; set; } + + public override bool Equals(object obj) + { + return (obj.GetType().Equals(this.GetType()) + && ((CompositeFileDefinition)obj).IsLocalFile.Equals(IsLocalFile) + && ((CompositeFileDefinition)obj).Uri.Equals(Uri)); + } + + /// + /// overrides hash code to ensure that it is unique per machine + /// + /// + public override int GetHashCode() + { + string machineName; + //catch usecase where user is running with EnvironmentPermission + try + { + machineName=Environment.MachineName; + } + catch (Exception) + { + machineName = HttpContext.Current.Server.MachineName; + } + return (machineName.ToString() + Uri).GetHashCode(); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileMap.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileMap.cs new file mode 100644 index 00000000000..7a38d2c0b82 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/CompositeFileMap.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using System.IO; + +namespace ClientDependency.Core.CompositeFiles +{ + /// + /// Deserialized structure of the XML stored in the map file + /// + public class CompositeFileMap + { + + internal CompositeFileMap(string key, string compressionType, string file, IEnumerable filePaths, int version) + { + DependentFiles = filePaths; + FileKey = key; + CompositeFileName = file; + CompressionType = compressionType; + Version = version; + } + + public string FileKey { get; private set; } + public string CompositeFileName { get; private set; } + public string CompressionType { get; private set; } + public int Version { get; private set; } + public IEnumerable DependentFiles { get; private set; } + + private byte[] m_FileBytes; + + /// + /// If for some reason the file doesn't exist any more or we cannot read the file, this will return false. + /// + public bool HasFileBytes + { + get + { + GetCompositeFileBytes(); + return m_FileBytes != null; + } + } + + /// + /// Returns the file's bytes + /// + public byte[] GetCompositeFileBytes() + { + if (m_FileBytes == null) + { + if (string.IsNullOrEmpty(CompositeFileName)) + { + return null; + } + + try + { + FileInfo fi = new FileInfo(CompositeFileName); + FileStream fs = fi.OpenRead(); + byte[] fileBytes = new byte[fs.Length]; + fs.Read(fileBytes, 0, fileBytes.Length); + fs.Close(); + m_FileBytes = fileBytes; + } + catch + { + m_FileBytes = null; + } + } + return m_FileBytes; + } + + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/JSMin.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/JSMin.cs new file mode 100644 index 00000000000..e500c645060 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/JSMin.cs @@ -0,0 +1,345 @@ +using System; +using System.IO; +using System.Text; + +/* Originally written in 'C', this code has been converted to the C# language. + * The author's copyright message is reproduced below. + * All modifications from the original to C# are placed in the public domain. + */ + +/* jsmin.c + 2007-05-22 + +Copyright (c) 2002 Douglas Crockford (www.crockford.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +namespace ClientDependency.Core.CompositeFiles +{ + public class JSMin + { + const int EOF = -1; + + StringReader sr; + StringWriter sw; + int theA; + int theB; + int theLookahead = EOF; + + public static string CompressJS(string body) + { + return new JSMin().Minify(body); + } + + public string Minify(string src) + { + StringBuilder sb = new StringBuilder(); + using (sr = new StringReader(src)) + { + using (sw = new StringWriter(sb)) + { + jsmin(); + } + } + return sb.ToString(); + } + + /* jsmin -- Copy the input to the output, deleting the characters which are + insignificant to JavaScript. Comments will be removed. Tabs will be + replaced with spaces. Carriage returns will be replaced with linefeeds. + Most spaces and linefeeds will be removed. + */ + void jsmin() + { + theA = '\n'; + action(3); + while (theA != EOF) + { + switch (theA) + { + case ' ': + { + if (isAlphanum(theB)) + { + action(1); + } + else + { + action(2); + } + break; + } + case '\n': + { + switch (theB) + { + case '{': + case '[': + case '(': + case '+': + case '-': + { + action(1); + break; + } + case ' ': + { + action(3); + break; + } + default: + { + if (isAlphanum(theB)) + { + action(1); + } + else + { + action(2); + } + break; + } + } + break; + } + default: + { + switch (theB) + { + case ' ': + { + if (isAlphanum(theA)) + { + action(1); + break; + } + action(3); + break; + } + case '\n': + { + switch (theA) + { + case '}': + case ']': + case ')': + case '+': + case '-': + case '"': + case '\'': + { + action(1); + break; + } + default: + { + if (isAlphanum(theA)) + { + action(1); + } + else + { + action(3); + } + break; + } + } + break; + } + default: + { + action(1); + break; + } + } + break; + } + } + } + } + /* action -- do something! What you do is determined by the argument: + 1 Output A. Copy B to A. Get the next B. + 2 Copy B to A. Get the next B. (Delete A). + 3 Get the next B. (Delete B). + action treats a string as a single character. Wow! + action recognizes a regular expression if it is preceded by ( or , or =. + */ + void action(int d) + { + if (d <= 1) + { + put(theA); + } + if (d <= 2) + { + theA = theB; + if (theA == '\'' || theA == '"') + { + for (; ; ) + { + put(theA); + theA = get(); + if (theA == theB) + { + break; + } + if (theA <= '\n') + { + throw new Exception(string.Format("Error: JSMIN unterminated string literal: {0}\n", theA)); + } + if (theA == '\\') + { + put(theA); + theA = get(); + } + } + } + } + if (d <= 3) + { + theB = next(); + if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' || + theA == '[' || theA == '!' || theA == ':' || + theA == '&' || theA == '|' || theA == '?' || + theA == '{' || theA == '}' || theA == ';' || + theA == '\n')) + { + put(theA); + put(theB); + for (; ; ) + { + theA = get(); + if (theA == '/') + { + break; + } + else if (theA == '\\') + { + put(theA); + theA = get(); + } + else if (theA <= '\n') + { + throw new Exception(string.Format("Error: JSMIN unterminated Regular Expression literal : {0}.\n", theA)); + } + put(theA); + } + theB = next(); + } + } + } + /* next -- get the next character, excluding comments. peek() is used to see + if a '/' is followed by a '/' or '*'. + */ + int next() + { + int c = get(); + if (c == '/') + { + switch (peek()) + { + case '/': + { + for (; ; ) + { + c = get(); + if (c <= '\n') + { + return c; + } + } + } + case '*': + { + get(); + for (; ; ) + { + switch (get()) + { + case '*': + { + if (peek() == '/') + { + get(); + return ' '; + } + break; + } + case EOF: + { + throw new Exception("Error: JSMIN Unterminated comment.\n"); + } + } + } + } + default: + { + return c; + } + } + } + return c; + } + /* peek -- get the next character without getting it. + */ + int peek() + { + theLookahead = get(); + return theLookahead; + } + /* get -- return the next character from stdin. Watch out for lookahead. If + the character is a control character, translate it to a space or + linefeed. + */ + int get() + { + int c = theLookahead; + theLookahead = EOF; + if (c == EOF) + { + c = sr.Read(); + } + if (c >= ' ' || c == '\n' || c == EOF) + { + return c; + } + if (c == '\r') + { + return '\n'; + } + return ' '; + } + void put(int c) + { + sw.Write((char)c); + } + /* isAlphanum -- return true if the character is a letter, digit, underscore, + dollar sign, or non-ASCII character. + */ + bool isAlphanum(int c) + { + return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' || c == '+' || + c > 126); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseCompositeFileProcessingProvider.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseCompositeFileProcessingProvider.cs new file mode 100644 index 00000000000..2daefc54a4a --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseCompositeFileProcessingProvider.cs @@ -0,0 +1,450 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.Config; +using System.IO; +using System.Web; +using System.Net; +using System.Configuration.Provider; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + public abstract class BaseCompositeFileProcessingProvider : ProviderBase, IHttpProvider + { + + private const string DefaultDependencyPath = "~/App_Data/ClientDependency"; + private readonly string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()); + + /// + /// The path specified in the config + /// + private string _compositeFilePath; + + /// + /// constructor sets defaults + /// + protected BaseCompositeFileProcessingProvider() + { + PersistCompositeFiles = true; + EnableCssMinify = true; + EnableJsMinify = true; + UrlType = CompositeUrlType.MappedId; + + _compositeFilePath = DefaultDependencyPath; + } + + #region Public Properties + + /// + /// Flags whether or not to enable composite file script creation/persistence. + /// Composite file persistence will increase performance in the case of cache turnover or application + /// startup since the files are already combined and compressed. + /// This also allows for the ability to easily clear the cache so the files are refreshed. + /// + public bool PersistCompositeFiles { get; set; } + public bool EnableCssMinify { get; set; } + public bool EnableJsMinify { get; set; } + + /// + /// The Url type to use for the dependency handler + /// + public CompositeUrlType UrlType { get; protected set; } + + /// + /// Returns the CompositeFilePath + /// + /// + public DirectoryInfo CompositeFilePath { get; protected set; } + + /// + /// Returns the set of white listed domains + /// + public IList BundleDomains { get; protected set; } + + #endregion + + #region IHttpProvider Members + + public void Initialize(HttpContextBase http) + { + CompositeFilePath = new DirectoryInfo(http.Server.MapPath(_compositeFilePath)); + } + + #endregion + + public abstract FileInfo SaveCompositeFile(byte[] fileContents, ClientDependencyType type, HttpServerUtilityBase server, int version); + public abstract byte[] CombineFiles(string[] filePaths, HttpContextBase context, ClientDependencyType type, out List fileDefs); + public abstract byte[] CompressBytes(CompressionType type, byte[] fileBytes); + + /// + /// Returns a URL used to return a compbined/compressed/optimized version of all dependencies. + /// + /// The full url with the encoded query strings for the handler which will process the composite list + /// of dependencies. The handler will compbine, compress, minify, and output cache the results + /// on the base64 encoded string. + /// + /// + /// + /// + /// + /// An array containing the list of composite file URLs. This will generally only contain 1 value unless + /// the number of files registered exceeds the maximum length, then it will return more than one file. + public virtual string[] ProcessCompositeList( + IEnumerable dependencies, + ClientDependencyType type, + HttpContextBase http) + { + if (!dependencies.Any()) + return new string[] { }; + + switch (UrlType) + { + case CompositeUrlType.MappedId: + + //use the file mapper to create us a file key/id for the file set + var fileKey = ClientDependencySettings.Instance.DefaultFileMapProvider.CreateNewMap(http, dependencies, GetVersion()); + + //create the url + return new[] { GetCompositeFileUrl(fileKey, type, http, CompositeUrlType.MappedId) }; + + default: + + //build the combined composite list urls + + var files = new List(); + var currBuilder = new StringBuilder(); + var base64Builder = new StringBuilder(); + var builderCount = 1; + var stringType = type.ToString(); + foreach (var a in dependencies) + { + //update the base64 output to get the length + base64Builder.Append(a.FilePath.EncodeTo64()); + + //test if the current base64 string exceeds the max length, if so we need to split + if ((base64Builder.Length + ClientDependencySettings.Instance.CompositeFileHandlerPath.Length + stringType.Length + 10) + >= (CompositeDependencyHandler.MaxHandlerUrlLength)) + { + //add the current output to the array + files.Add(currBuilder.ToString()); + //create some new output + currBuilder = new StringBuilder(); + base64Builder = new StringBuilder(); + builderCount++; + } + + //update the normal builder + currBuilder.Append(a.FilePath + ";"); + } + + if (builderCount > files.Count) + { + files.Add(currBuilder.ToString()); + } + + //now, compress each url + for (var i = 0; i < files.Count; i++) + { + //append our version to the combined url + var encodedFile = files[i].EncodeTo64Url(); + files[i] = GetCompositeFileUrl(encodedFile, type, http, UrlType); + } + + return files.ToArray(); + } + } + + public virtual int GetVersion() + { + return ClientDependencySettings.Instance.Version; + } + + /// + /// Returns the url for the composite file handler for the filePath specified. + /// + /// The Base64 encoded file paths or the file map key used to lookup the required dependencies + /// + /// + /// + /// + public virtual string GetCompositeFileUrl( + string fileKey, + ClientDependencyType type, + HttpContextBase http, + CompositeUrlType urlType) + { + var url = new StringBuilder(); + int version = GetVersion(); + switch (urlType) + { + case CompositeUrlType.Base64QueryStrings: + + //Create a URL with a base64 query string + + const string handler = "{0}?s={1}&t={2}"; + url.Append(string.Format(handler, + ClientDependencySettings.Instance.CompositeFileHandlerPath, + http.Server.UrlEncode(fileKey), type)); + url.Append("&cdv="); + url.Append(version.ToString()); + break; + default: + + //Create a URL based on base64 paths instead of a query string + + + //this used to be a "." but this causes problems with mvc and ignore routes for + //some very strange reason, so we'll just use normal paths. + var versionDelimiter = "."; + + url.Append(ClientDependencySettings.Instance.CompositeFileHandlerPath); + int pos = 0; + while (fileKey.Length > pos) + { + url.Append("/"); + int len = Math.Min(fileKey.Length - pos, 240); + url.Append(fileKey.Substring(pos, len)); + pos += 240; + } + url.Append(versionDelimiter); + url.Append(version.ToString()); + switch (type) + { + case ClientDependencyType.Css: + url.Append(versionDelimiter); + url.Append("css"); + break; + case ClientDependencyType.Javascript: + url.Append(versionDelimiter); + url.Append("js"); + break; + } + break; + } + + return url.ToString(); + } + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + base.Initialize(name, config); + + if (config == null) + return; + + if (config["enableCssMinify"] != null) + { + bool enableCssMinify; + if (bool.TryParse(config["enableCssMinify"], out enableCssMinify)) + EnableCssMinify = enableCssMinify; + } + if (config["enableJsMinify"] != null) + { + bool enableJsMinify; + if (bool.TryParse(config["enableJsMinify"], out enableJsMinify)) + EnableJsMinify = enableJsMinify; + } + + if (config["persistFiles"] != null) + { + bool persistFiles; + if (bool.TryParse(config["persistFiles"], out persistFiles)) + PersistCompositeFiles = persistFiles; + } + + if (config["urlType"] != null) + { + try + { + UrlType = (CompositeUrlType)Enum.Parse(typeof(CompositeUrlType), config["urlType"]); + } + catch (ArgumentException) + { + //swallow exception, we've set the default + } + } + + _compositeFilePath = config["compositeFilePath"] ?? DefaultDependencyPath; + + string bundleDomains = config["bundleDomains"]; + if (bundleDomains != null) + bundleDomains = bundleDomains.Trim(); + if (string.IsNullOrEmpty(bundleDomains)) + { + BundleDomains = new List(); + } + else + { + string[] domains = bundleDomains.Split(new char[] { ',' }); + for (int i = 0; i < domains.Length; i++) + { + // make sure we have a starting dot and a trailing port + // ie 'maps.google.com' will be stored as '.maps.google.com:80' + if (domains[i].IndexOf(':') < 0) + domains[i] = domains[i] + ":80"; + if (!domains[i].StartsWith(".")) + domains[i] = "." + domains[i]; + } + BundleDomains = new List(domains); + } + } + + /// + /// Minifies the file + /// + /// + /// + /// + protected virtual string MinifyFile(string fileContents, ClientDependencyType type) + { + switch (type) + { + case ClientDependencyType.Css: + return EnableCssMinify ? CssMin.CompressCSS(fileContents) : fileContents; + case ClientDependencyType.Javascript: + return EnableJsMinify ? JSMin.CompressJS(fileContents) : fileContents; + default: + return fileContents; + } + } + + /// + /// This ensures that all paths (i.e. images) in a CSS file have their paths change to absolute paths. + /// + /// + /// + /// + /// + /// + protected virtual string ParseCssFilePaths(string fileContents, ClientDependencyType type, string url, HttpContextBase http) + { + //if it is a CSS file we need to parse the URLs + if (type == ClientDependencyType.Css) + { + var uri = new Uri(url, UriKind.RelativeOrAbsolute); + fileContents = CssFileUrlFormatter.TransformCssFile(fileContents, uri.MakeAbsoluteUri(http)); + } + return fileContents; + } + + /// + /// Tries to convert the url to a uri, then read the request into a string and return it. + /// This takes into account relative vs absolute URI's + /// + /// + /// + /// + /// true if successful, false if not successful + /// + /// if the path is a relative local path, the we use Server.Execute to get the request output, otherwise + /// if it is an absolute path, a WebClient request is made to fetch the contents. + /// + protected bool TryReadUri(string url, out string requestContents, HttpContextBase http) + { + Uri uri; + if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri)) + { + //flag of whether or not to make a request to get the external resource (used below) + bool bundleExternalUri = false; + + //if its a relative path, then check if we should execute/retreive contents, + //otherwise change it to an absolute path and try to request it. + if (!uri.IsAbsoluteUri) + { + //if this is an ASPX page, we should execute it instead of http getting it. + if (uri.ToString().EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase)) + { + var sw = new StringWriter(); + try + { + http.Server.Execute(url, sw); + requestContents = sw.ToString(); + sw.Close(); + return true; + } + catch (Exception ex) + { + ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", url, ex.Message), ex); + requestContents = ""; + return false; + } + } + + //if this is a call for a web resource, we should http get it + if (url.StartsWith(http.Request.ApplicationPath.TrimEnd('/') + "/webresource.axd", StringComparison.InvariantCultureIgnoreCase)) + { + bundleExternalUri = true; + } + } + + try + { + //we've gotten this far, make the URI absolute and try to load it + uri = uri.MakeAbsoluteUri(http); + + //if this isn't a web resource, we need to check if its approved + if (!bundleExternalUri) + { + // get the domain to test, with starting dot and trailing port, then compare with + // declared (authorized) domains. the starting dot is here to allow for subdomain + // approval, eg '.maps.google.com:80' will be approved by rule '.google.com:80', yet + // '.roguegoogle.com:80' will not. + var domain = string.Format(".{0}:{1}", uri.Host, uri.Port); + + foreach (string bundleDomain in BundleDomains) + { + if (domain.EndsWith(bundleDomain)) + { + bundleExternalUri = true; + break; + } + } + } + + if (bundleExternalUri) + { + requestContents = GetXmlResponse(uri); + return true; + } + else + { + ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. Domain is not white-listed.", url), null); + } + } + catch (Exception ex) + { + ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", url, ex.Message), ex); + } + + + } + requestContents = ""; + return false; + } + + /// + /// Gets the web response and ensures that the BOM is not present not matter what encoding is specified. + /// + /// + /// + private string GetXmlResponse(Uri resource) + { + string xml; + + using (var client = new WebClient()) + { + client.Credentials = CredentialCache.DefaultNetworkCredentials; + client.Encoding = Encoding.UTF8; + xml = client.DownloadString(resource); + } + + if (xml.StartsWith(_byteOrderMarkUtf8)) + { + xml = xml.Remove(0, _byteOrderMarkUtf8.Length - 1); + } + + return xml; + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseFileMapProvider.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseFileMapProvider.cs new file mode 100644 index 00000000000..75d342b6410 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/BaseFileMapProvider.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Configuration.Provider; +using System.IO; +using System.Web; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + public abstract class BaseFileMapProvider : ProviderBase, IHttpProvider + { + + /// + /// Retreives the file map for the key/version/compression type specified + /// + /// + /// + /// + /// + public abstract CompositeFileMap GetCompositeFile(string fileKey, + int version, + string compression); + + /// + /// Retreives the dependent file paths for the filekey/version (regardless of compression) + /// + /// + /// + /// + public abstract IEnumerable GetDependentFiles(string fileKey, int version); + + /// + /// Creates a map for the version/compression type/dependent file listing + /// + /// + /// + /// + /// + /// + public abstract void CreateUpdateMap(string fileKey, + string compressionType, + IEnumerable dependentFiles, + string compositeFile, + int version); + + /// + /// Creates a new file map and file key for the dependent file list, this is used to create URLs with CompositeUrlType.MappedId + /// + public abstract string CreateNewMap(HttpContextBase http, + IEnumerable dependentFiles, + int version); + + /// + /// Runs initialization with an Http context, this occurs after the initial provider config initialization + /// + /// + public abstract void Initialize(System.Web.HttpContextBase http); + + + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProvider.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProvider.cs new file mode 100644 index 00000000000..75ccb918b02 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProvider.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Web.Hosting; +using ClientDependency.Core.Config; +using System.IO; +using System.Web; +using System.Net; +using System.IO.Compression; +using System.Configuration.Provider; +using ClientDependency.Core.CompositeFiles; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + + /// + /// A provider for combining, minifying, compressing and saving composite scripts/css files + /// + public class CompositeFileProcessingProvider : BaseCompositeFileProcessingProvider + { + + public const string DefaultName = "CompositeFileProcessor"; + private static Regex _importCssRegex = new Regex("@import url\\((.+?)\\);?", RegexOptions.Compiled); + + /// + /// Saves the file's bytes to disk with a hash of the byte array + /// + /// + /// + /// + /// The new file path + /// + /// the extension will be: .cdj for JavaScript and .cdc for CSS + /// + public override FileInfo SaveCompositeFile(byte[] fileContents, ClientDependencyType type, HttpServerUtilityBase server, int version) + { + //don't save the file if composite files are disabled. + if (!PersistCompositeFiles) + return null; + + if (!CompositeFilePath.Exists) + CompositeFilePath.Create(); + + var fi = new FileInfo( + Path.Combine(CompositeFilePath.FullName, + version + "_" + Guid.NewGuid().ToString("N") + ".cd" + type.ToString().Substring(0, 1).ToUpper())); + + if (fi.Exists) + fi.Delete(); + + var fs = fi.Create(); + fs.Write(fileContents, 0, fileContents.Length); + fs.Close(); + return fi; + } + + /// + /// combines all files to a byte array + /// + /// + /// + /// + /// + /// + public override byte[] CombineFiles(string[] filePaths, HttpContextBase context, ClientDependencyType type, out List fileDefs) + { + + var fDefs = new List(); + + var ms = new MemoryStream(5000); + var sw = new StreamWriter(ms, Encoding.UTF8); + + foreach (string s in filePaths) + { + if (!string.IsNullOrEmpty(s)) + { + try + { + var fi = new FileInfo(context.Server.MapPath(s)); + if (ClientDependencySettings.Instance.FileBasedDependencyExtensionList.Contains(fi.Extension.ToUpper())) + { + //if the file doesn't exist, then we'll assume it is a URI external request + if (!fi.Exists) + { + WriteFileToStream(ref sw, s, type, ref fDefs, context); + } + else + { + WriteFileToStream(ref sw, fi, type, s, ref fDefs, context); + } + } + else + { + //if it's not a file based dependency, try to get the request output. + WriteFileToStream(ref sw, s, type, ref fDefs, context); + } + } + catch (Exception ex) + { + Type exType = ex.GetType(); + if (exType.Equals(typeof(NotSupportedException)) + || exType.Equals(typeof(ArgumentException)) + || exType.Equals(typeof(HttpException))) + { + //could not parse the string into a fileinfo or couldn't mappath, so we assume it is a URI + WriteFileToStream(ref sw, s, type, ref fDefs, context); + } + else + { + //if this fails, log the exception in trace, but continue + ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", s, ex.Message), ex); + } + } + } + + if (type == ClientDependencyType.Javascript) + { + sw.Write(";;;"); //write semicolons in case the js isn't formatted correctly. This also helps for debugging. + } + + } + sw.Flush(); + byte[] outputBytes = ms.ToArray(); + sw.Close(); + ms.Close(); + fileDefs = fDefs; + return outputBytes; + } + + /// + /// Compresses the bytes if the browser supports it + /// + public override byte[] CompressBytes(CompressionType type, byte[] fileBytes) + { + return SimpleCompressor.CompressBytes(type, fileBytes); + } + + /// + /// Writes the output of an external request to the stream. Returns true/false if succesful or not. + /// + /// + /// + /// + /// + /// + /// + protected virtual void WriteFileToStream(ref StreamWriter sw, string url, ClientDependencyType type, ref List fileDefs, HttpContextBase http) + { + string requestOutput; + var rVal = TryReadUri(url, out requestOutput, http); + if (rVal) + { + //write the contents of the external request. + WriteContentToStream(ref sw, MinifyFile(ParseCssFilePaths(requestOutput, type, url, http), type), type, http); + fileDefs.Add(new CompositeFileDefinition(url, false)); + } + return; + } + + protected virtual void WriteFileToStream(ref StreamWriter sw, FileInfo fi, ClientDependencyType type, string origUrl, ref List fileDefs, HttpContextBase http) + { + try + { + //if it is a file based dependency then read it + var fileContents = File.ReadAllText(fi.FullName, Encoding.UTF8); //read as utf 8 + + WriteContentToStream(ref sw, MinifyFile(ParseCssFilePaths(fileContents, type, origUrl, http), type), type, http); + fileDefs.Add(new CompositeFileDefinition(origUrl, true)); + return; + } + catch (Exception ex) + { + ClientDependencySettings.Instance.Logger.Error(string.Format("Could not write file {0} contents to stream. EXCEPTION: {1}", fi.FullName, ex.Message), ex); + return; + } + } + + private void WriteContentToStream(ref StreamWriter sw, string content, ClientDependencyType type, HttpContextBase context) + { + //need to parse + if (type == ClientDependencyType.Css && ClientDependencySettings.Instance.DefaultFileRegistrationProvider.EnableCompositeFiles) + { + while(_importCssRegex.IsMatch(content)) + { + var match = _importCssRegex.Match(content); + //write the previous content + sw.WriteLine(content.Substring(0, match.Index)); + //write import css content + var filePath = match.Groups[1].Value.Trim('\'', '"'); + try + { + var importContent = string.Empty; + if(filePath.StartsWith("http")) + { + importContent = ParseCssFilePaths(DownloadString(filePath), ClientDependencyType.Css, filePath, context); + } + else + { + importContent = ParseCssFilePaths(File.ReadAllText(context.Server.MapPath(filePath)), ClientDependencyType.Css, filePath, context); + } + + sw.WriteLine(importContent); + } + catch + { + sw.WriteLine(string.Format("/*Invalid CSS: {0}*/", filePath)); + } + + content = content.Substring(match.Index + match.Length); + } + sw.WriteLine(content); + } + else + { + sw.WriteLine(MinifyFile(content, type)); + } + } + + private string DownloadString(string url) + { + var content = string.Empty; + try + { + var webRequest = (HttpWebRequest)HttpWebRequest.Create(url); + webRequest.UserAgent = "ClientDependency Css Parser"; + var response = webRequest.GetResponse(); + using (var reader = new StreamReader(response.GetResponseStream())) + { + content = reader.ReadToEnd(); + } + response.Close(); + } + catch + { + content = string.Format("/*Invalid CSS: {0}*/", url); + } + + return content; + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProviderCollection.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProviderCollection.cs new file mode 100644 index 00000000000..3859f25842d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeFileProcessingProviderCollection.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Configuration.Provider; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + public class CompositeFileProcessingProviderCollection : ProviderCollection + { + public new BaseCompositeFileProcessingProvider this[string name] + { + get { return (BaseCompositeFileProcessingProvider)base[name]; } + } + + public override void Add(ProviderBase provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + + if (!(provider is BaseCompositeFileProcessingProvider)) + throw new ArgumentException("Invalid provider type", "provider"); + + base.Add(provider); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeUrlType.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeUrlType.cs new file mode 100644 index 00000000000..a36fcbff967 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/CompositeUrlType.cs @@ -0,0 +1,22 @@ +namespace ClientDependency.Core.CompositeFiles.Providers +{ + public enum CompositeUrlType + { + /// + /// The original URL type in which full dependency paths are base64 encoded as query strings + /// + Base64QueryStrings, + + /// + /// Creates a URL in which the full dependency paths are base64 encoded as URL paths, however because + /// paths can get quite large, this requires that .Net 4 is running and that you increase the maxUrlLength + /// configuration property in the httpRuntime section in your web.config + /// + Base64Paths, + + /// + /// Uses the file map provider to store and map the dependency paths with a reference to an ID it generates + /// + MappedId + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/FileMapProviderCollection.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/FileMapProviderCollection.cs new file mode 100644 index 00000000000..ac189daf8df --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/FileMapProviderCollection.cs @@ -0,0 +1,24 @@ +using System; +using System.Configuration.Provider; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + public class FileMapProviderCollection : ProviderCollection + { + public new BaseFileMapProvider this[string name] + { + get { return (BaseFileMapProvider)base[name]; } + } + + public override void Add(ProviderBase provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + + if (!(provider is BaseFileMapProvider)) + throw new ArgumentException("Invalid provider type", "provider"); + + base.Add(provider); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/XmlFileMapper.cs b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/XmlFileMapper.cs new file mode 100644 index 00000000000..cedf26c16d8 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompositeFiles/Providers/XmlFileMapper.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Xml.Linq; +using System.Xml; +using System.IO; +using ClientDependency.Core.Config; +using System.Security.Cryptography; + +namespace ClientDependency.Core.CompositeFiles.Providers +{ + + /// + /// Creates an XML file to map a saved composite file to the URL requested for the + /// dependency handler. + /// This is used in order to determine which individual files are dependant on what composite file so + /// a user can remove it to clear the cache, and also if the cache expires but the file still exists + /// this allows the system to simply read the one file again instead of compiling all of the other files + /// into one again. + /// + public class XmlFileMapper : BaseFileMapProvider + { + + public const string DefaultName = "XmlFileMap"; + + private const string MapFileName = "map.xml"; + + private XDocument _doc; + private FileInfo _xmlFile; + private DirectoryInfo _xmlMapFolder; + private string _fileMapVirtualFolder = "~/App_Data/ClientDependency"; + private static readonly object Locker = new object(); + + public override void Initialize(HttpContextBase http) + { + if (http == null) throw new ArgumentNullException("http"); + + _xmlMapFolder = new DirectoryInfo(http.Server.MapPath(_fileMapVirtualFolder)); + + //Name the map file according to the machine name + _xmlFile = new FileInfo(GetXmlMapPath()); + + EnsureXmlFile(); + + lock (Locker) + { + try + { + _doc = XDocument.Load(_xmlFile.FullName); + } + catch (XmlException) + { + //if it's an xml exception, create a new one and try one more time... should always work. + CreateNewXmlFile(); + _doc = XDocument.Load(_xmlFile.FullName); + } + } + } + + /// + /// Initializes the provider, loads in the existing file contents. If the file doesn't exist, it creates one. + /// + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + base.Initialize(name, config); + + if (config == null) + return; + + if (config["mapPath"] != null) + { + _fileMapVirtualFolder = config["mapPath"]; + } + + } + + /// + /// Returns the composite file map associated with the file key, the version and the compression type + /// + /// + /// + /// + /// + public override CompositeFileMap GetCompositeFile(string fileKey, int version, string compression) + { + if (string.IsNullOrEmpty(fileKey)) throw new ArgumentNullException("fileKey"); + + EnsureXmlFile(); + + var x = FindItem(fileKey, version, compression); + try + { + return (x == null ? null : new CompositeFileMap(fileKey, + (string)x.Attribute("compression"), + (string)x.Attribute("file"), + x.Descendants("file") + .Select(f => ((string)f.Attribute("name"))).ToArray(), + int.Parse((string)x.Attribute("version")))); + } + catch + { + return null; + } + } + + /// + /// Retreives the dependent file paths for the filekey/version (regardless of compression) + /// + /// + /// + /// + public override IEnumerable GetDependentFiles(string fileKey, int version) + { + if (string.IsNullOrEmpty(fileKey)) throw new ArgumentNullException("fileKey"); + + var x = FindItem(fileKey, version); + try + { + if (x != null) + { + var file = new CompositeFileMap(fileKey, + (string) x.Attribute("compression"), + (string) x.Attribute("file"), + x.Descendants("file") + .Select(f => ((string) f.Attribute("name"))).ToArray(), + int.Parse((string) x.Attribute("version"))); + return file.DependentFiles; + } + } + catch + { + return null; + } + return null; + } + + /// + /// Creates a new file map and file key for the dependent file list, this is used to create URLs with CompositeUrlType.MappedId + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// ]]> + /// + public override string CreateNewMap(HttpContextBase http, + IEnumerable dependentFiles, + int version) + { + if (http == null) throw new ArgumentNullException("http"); + + var builder = new StringBuilder(); + foreach (var d in dependentFiles) + { + builder.Append(d.FilePath); + builder.Append(";"); + } + var combinedFiles = builder.ToString(); + combinedFiles = combinedFiles.TrimEnd(new[] { ';' }); + + var fileKey = (combinedFiles + version).GenerateMd5(); + + var x = FindItem(fileKey, version); + + //if no map exists, create one + if (x == null) + { + //now, create a map with the file key so that it can be filled out later with the actual composite file that is created by the handler + CreateUpdateMap(fileKey, + string.Empty, + dependentFiles, + string.Empty, + version); + } + + return fileKey; + } + + /// + /// Adds/Updates an entry to the file map with the key specified, the version and dependent files listed with a map + /// to the composite file created for the files. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// ]]> + /// + public override void CreateUpdateMap(string fileKey, + string compressionType, + IEnumerable dependentFiles, + string compositeFile, + int version) + { + if (string.IsNullOrEmpty(fileKey)) throw new ArgumentNullException("fileKey"); + + lock (Locker) + { + //see if we can find an item with the key/version/compression that exists + var x = FindItem(fileKey, version, compressionType); + + if (x != null) + { + x.Attribute("file").Value = compositeFile; + //remove all of the files so we can re-add them. + x.Element("files").Remove(); + + x.Add(CreateFileNode(dependentFiles)); + } + else + { + //if it doesn't exist, create it + _doc.Root.Add(new XElement("item", + new XAttribute("key", fileKey), + new XAttribute("file", compositeFile), + new XAttribute("compression", compressionType), + new XAttribute("version", version), + CreateFileNode(dependentFiles))); + } + + _doc.Save(_xmlFile.FullName); + } + } + + /// + /// Finds an element in the map matching the key and version/compression + /// + /// + /// + /// + /// + private XElement FindItem(string key, int version, string compression) + { + if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key"); + + var items = _doc.Root.Elements("item") + .Where(e => (string) e.Attribute("key") == key + && (string) e.Attribute("version") == version.ToString()); + return items.Where(e => (string)e.Attribute("compression") == compression).SingleOrDefault(); + } + + /// + /// Finds a element in the map matching key/version + /// + /// + /// + /// + private XElement FindItem(string key, int version) + { + if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key"); + + var items = _doc.Root.Elements("item") + .Where(e => (string)e.Attribute("key") == key + && (string)e.Attribute("version") == version.ToString()); + return items.FirstOrDefault(); + } + + private XElement CreateFileNode(IEnumerable dependentFiles) + { + var x = new XElement("files"); + + //add all of the files + foreach (var d in dependentFiles) + { + x.Add(new XElement("file", new XAttribute("name", d.FilePath))); + } + + return x; + } + + /// + /// Returns the full path the map xml file for the current machine and install folder. + /// + /// + /// We need to create the map based on the combination of both machine name and install folder because + /// this deals with issues for load balanced environments and file locking and also + /// deals with issues when the ClientDependency folder is deployed between environments + /// since you would want your staging ClientDependencies in your live and vice versa. + /// This is however based on the theory that each website you have will have a unique combination + /// of folder path and machine name. + /// + /// + private string GetXmlMapPath() + { + var folder = _xmlMapFolder.FullName; + var folderMd5 = folder.GenerateMd5(); + string machineName; + //catch usecase where user is running with EnvironmentPermission + try + { + machineName = Environment.MachineName; + } + catch (Exception) + { + machineName = HttpContext.Current.Server.MachineName; + } + return Path.Combine(folder, machineName.ToString() + "-" + folderMd5 + "-" + MapFileName); + } + + private void CreateNewXmlFile() + { + if (File.Exists(_xmlFile.FullName)) + { + File.Delete(_xmlFile.FullName); + } + + if (_doc == null) + { + _doc = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), + new XElement("map")); + _doc.Save(_xmlFile.FullName); + } + else + { + //if there's xml in memory, then the file has been deleted so write out the file + _doc.Save(_xmlFile.FullName); + } + + } + + private void EnsureXmlFile() + { + if (!File.Exists(_xmlFile.FullName)) + { + lock (Locker) + { + //double check + if (!File.Exists(_xmlFile.FullName)) + { + if (!_xmlMapFolder.Exists) + _xmlMapFolder.Create(); + CreateNewXmlFile(); + } + } + } + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CompressionType.cs b/DNN Platform/Components/ClientDependency/Source/CompressionType.cs new file mode 100644 index 00000000000..feb42f2456d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CompressionType.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.Config; +using System.IO; +using System.Web; +using System.Net; +using System.IO.Compression; + +namespace ClientDependency.Core +{ + public enum CompressionType + { + deflate, gzip, none + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySection.cs b/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySection.cs new file mode 100644 index 00000000000..8d6a91dffb7 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySection.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Configuration; +using System.Linq; +using ClientDependency.Core.Logging; + +namespace ClientDependency.Core.Config +{ + public class ClientDependencySection : ConfigurationSection + { + /// + /// Set the version for the files, this will reset all composite file caching, and if + /// composite files are disabled will add a query string to each request so that + /// any client side cached files will be re-downloaded. + /// + [ConfigurationProperty("version", DefaultValue = 0)] + public int Version + { + get { return (int)base["version"]; } + set { base["version"] = value; } + } + + [ConfigurationProperty("compositeFiles")] + public CompositeFileSection CompositeFileElement + { + get + { + return (CompositeFileSection)this["compositeFiles"]; + } + } + + [ConfigurationProperty("fileRegistration")] + public FileRegistrationSection FileRegistrationElement + { + get + { + return (FileRegistrationSection)this["fileRegistration"]; + } + } + + [ConfigurationProperty("mvc")] + public MvcSection MvcElement + { + get + { + return (MvcSection)this["mvc"]; + } + } + + [ConfigurationProperty("loggerType")] + public string LoggerType + { + get + { + return (string)this["loggerType"]; + } + } + + /// + /// Not really supposed to be used by public, but can implement at your own risk! + /// This by default assigns the MvcFilter and RogueFileFilter. + /// + [ConfigurationProperty("filters", IsRequired = false)] + public ProviderSettingsCollection Filters + { + get + { + var obj = base["filters"]; + + if (obj == null || ((obj is ConfigurationElementCollection) && ((ConfigurationElementCollection)obj).Count == 0)) + { + var col = new ProviderSettingsCollection(); + col.Add(new ProviderSettings("MvcFilter", "ClientDependency.Core.Mvc.MvcFilter, ClientDependency.Core.Mvc")); + col.Add(new ProviderSettings("RogueFileFilter", "ClientDependency.Core.Module.RogueFileFilter, ClientDependency.Core")); + return col; + } + else + { + return (ProviderSettingsCollection)obj; + } + } + } + + /// + /// The configuration section to set the FileBasedDependencyExtensionList. This is a comma separated list. + /// + /// + /// If this is not explicitly set, then the extensions 'js' and 'css' are the defaults. + /// + [ConfigurationProperty("fileDependencyExtensions", DefaultValue = ".js,.css")] + protected string FileBasedDepdendenyExtensions + { + get { return (string)base["fileDependencyExtensions"]; } + set { base["fileDependencyExtensions"] = value; } + } + + /// + /// The file extensions of Client Dependencies that are file based as opposed to request based. + /// Any file that doesn't have the extensions listed here will be request based, request based is + /// more overhead for the server to process. + /// + /// + /// A request based JavaScript file may be a .ashx that dynamically creates JavaScript server side. + /// Or an asmx/js request based on the proxied javascript created by web services. + /// + /// + /// If this is not explicitly set, then the extensions 'js' and 'css' are the defaults. + /// + public IEnumerable FileBasedDependencyExtensionList + { + get + { + return FileBasedDepdendenyExtensions.Split(',') + .Select(x => x.Trim().ToUpper()); + } + } + } + +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySettings.cs b/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySettings.cs new file mode 100644 index 00000000000..92b11c1a363 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/ClientDependencySettings.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Configuration; +using System.Configuration.Provider; +using System.Web; +using System.Configuration; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.CompositeFiles.Providers; +using ClientDependency.Core.Logging; +using System.IO; + +namespace ClientDependency.Core.Config +{ + public class ClientDependencySettings + { + /// + /// used for singleton + /// + private static ClientDependencySettings _settings; + private static readonly object Lock = new object(); + + /// + /// Default constructor, for use with a web context app + /// + internal ClientDependencySettings() + { + if (HttpContext.Current == null) + { + throw new InvalidOperationException( + "HttpContext.Current must exist when using the empty constructor for ClientDependencySettings, otherwise use the alternative constructor"); + } + + LoadProviders((ClientDependencySection)ConfigurationManager.GetSection("clientDependency"), new HttpContextWrapper(HttpContext.Current)); + + } + + internal ClientDependencySettings(FileInfo configFile, HttpContextBase ctx) + { + var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile.FullName }; + var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + LoadProviders((ClientDependencySection)configuration.GetSection("clientDependency"), ctx); + } + + /// + /// Singleton, used for web apps + /// + public static ClientDependencySettings Instance + { + get + { + if (_settings == null) + { + lock(Lock) + { + //double check + if (_settings == null) + { + _settings = new ClientDependencySettings(); + } + } + } + return _settings; + } + } + + /// + /// The file extensions of Client Dependencies that are file based as opposed to request based. + /// Any file that doesn't have the extensions listed here will be request based, request based is + /// more overhead for the server to process. + /// + /// + /// A request based JavaScript file may be a .ashx that dynamically creates JavaScript server side. + /// + /// + /// If this is not explicitly set, then the extensions 'js' and 'css' are the defaults. + /// + public List FileBasedDependencyExtensionList { get; set; } + + public int Version { get; set; } + + public ILogger Logger { get; private set; } + + /// + /// Returns the default MVC renderer + /// + public BaseRenderer DefaultMvcRenderer { get; private set; } + + /// + /// Returns the MVC renderer provider collection + /// + public RendererCollection MvcRendererCollection { get; private set; } + + /// + /// Returns the default file registration provider + /// + public WebFormsFileRegistrationProvider DefaultFileRegistrationProvider { get; private set; } + + /// + /// Returns the file registration provider collection + /// + public FileRegistrationProviderCollection FileRegistrationProviderCollection { get; private set; } + + /// + /// Returns the default composite file processing provider + /// + public BaseCompositeFileProcessingProvider DefaultCompositeFileProcessingProvider { get; private set; } + + /// + /// Returns the composite file processing provider collection + /// + public CompositeFileProcessingProviderCollection CompositeFileProcessingProviderCollection { get; private set; } + + /// + /// Returns the default file map provider + /// + public BaseFileMapProvider DefaultFileMapProvider { get; private set; } + + /// + /// Returns the collection of file map providers + /// + public FileMapProviderCollection FileMapProviderCollection { get; private set; } + + public ClientDependencySection ConfigSection { get; private set; } + + public string CompositeFileHandlerPath { get; set; } + + internal void LoadProviders(ClientDependencySection section, HttpContextBase http) + { + + ConfigSection = section; + + FileRegistrationProviderCollection = new FileRegistrationProviderCollection(); + CompositeFileProcessingProviderCollection = new CompositeFileProcessingProviderCollection(); + MvcRendererCollection = new RendererCollection(); + FileMapProviderCollection = new FileMapProviderCollection(); + + // if there is no section found, then create one + if (ConfigSection == null) + { + //create a new section with the default settings + ConfigSection = new ClientDependencySection(); + } + + //need to check if it's an http path or a lambda path + var path = ConfigSection.CompositeFileElement.CompositeFileHandlerPath; + CompositeFileHandlerPath = path.StartsWith("~/") + ? VirtualPathUtility.ToAbsolute(ConfigSection.CompositeFileElement.CompositeFileHandlerPath, http.Request.ApplicationPath) + : ConfigSection.CompositeFileElement.CompositeFileHandlerPath; + Version = ConfigSection.Version; + FileBasedDependencyExtensionList = ConfigSection.FileBasedDependencyExtensionList.ToList(); + + //load the providers from the config, if there isn't config sections then add default providers + // and then load the defaults. + + LoadDefaultCompositeFileConfig(ConfigSection, http); + + DefaultCompositeFileProcessingProvider = CompositeFileProcessingProviderCollection[ConfigSection.CompositeFileElement.DefaultFileProcessingProvider]; + if (DefaultCompositeFileProcessingProvider == null) + throw new ProviderException("Unable to load default composite file provider"); + + LoadDefaultFileMapConfig(ConfigSection, http); + + DefaultFileMapProvider = FileMapProviderCollection[ConfigSection.CompositeFileElement.DefaultFileMapProvider]; + if (DefaultFileMapProvider == null) + throw new ProviderException("Unable to load default file map provider"); + + LoadDefaultMvcFileConfig(ConfigSection); + + DefaultMvcRenderer = MvcRendererCollection[ConfigSection.MvcElement.DefaultRenderer]; + if (DefaultMvcRenderer == null) + throw new ProviderException("Unable to load default mvc renderer"); + + LoadDefaultFileRegConfig(ConfigSection); + + DefaultFileRegistrationProvider = FileRegistrationProviderCollection[ConfigSection.FileRegistrationElement.DefaultProvider]; + if (DefaultFileRegistrationProvider == null) + throw new ProviderException("Unable to load default file registration provider"); + + if (string.IsNullOrEmpty(ConfigSection.LoggerType)) + { + Logger = new NullLogger(); + } + else + { + var t = Type.GetType(ConfigSection.LoggerType); + if (!typeof(ILogger).IsAssignableFrom(t)) + { + throw new ArgumentException("The loggerType '" + ConfigSection.LoggerType + "' does not inherit from ClientDependency.Core.Logging.ILogger"); + } + + Logger = (ILogger)Activator.CreateInstance(t); + } + + } + + private void LoadDefaultFileRegConfig(ClientDependencySection section) + { + if (section.FileRegistrationElement.Providers.Count == 0) + { + //create new providers + var php = new PageHeaderProvider(); + php.Initialize(PageHeaderProvider.DefaultName, null); + FileRegistrationProviderCollection.Add(php); + + var csrp = new LazyLoadProvider(); + csrp.Initialize(LazyLoadProvider.DefaultName, null); + FileRegistrationProviderCollection.Add(csrp); + + var lcp = new LoaderControlProvider(); + lcp.Initialize(LoaderControlProvider.DefaultName, null); + FileRegistrationProviderCollection.Add(lcp); + } + else + { + ProvidersHelper.InstantiateProviders(section.FileRegistrationElement.Providers, FileRegistrationProviderCollection, typeof(BaseFileRegistrationProvider)); + } + + } + + private void LoadDefaultFileMapConfig(ClientDependencySection section, HttpContextBase http) + { + if (section.CompositeFileElement.FileMapProviders.Count == 0) + { + //if not specified, create default + var fmp = new XmlFileMapper(); + fmp.Initialize(XmlFileMapper.DefaultName, null); + fmp.Initialize(http); + FileMapProviderCollection.Add(fmp); + } + else + { + ProvidersHelper.InstantiateProviders(section.CompositeFileElement.FileMapProviders, FileMapProviderCollection, typeof(BaseFileMapProvider)); + //since the BaseFileMapProvider is an IHttpProvider, we need to do the http init + foreach (var p in FileMapProviderCollection.Cast()) + { + p.Initialize(http); + } + } + + } + + private void LoadDefaultCompositeFileConfig(ClientDependencySection section, HttpContextBase http) + { + if (section.CompositeFileElement.FileProcessingProviders.Count == 0) + { + var cfpp = new CompositeFileProcessingProvider(); + cfpp.Initialize(CompositeFileProcessingProvider.DefaultName, null); + cfpp.Initialize(http); + CompositeFileProcessingProviderCollection.Add(cfpp); + } + else + { + ProvidersHelper.InstantiateProviders(section.CompositeFileElement.FileProcessingProviders, CompositeFileProcessingProviderCollection, typeof(BaseCompositeFileProcessingProvider)); + //since the BaseCompositeFileProcessingProvider is an IHttpProvider, we need to do the http init + foreach(var p in CompositeFileProcessingProviderCollection.Cast()) + { + p.Initialize(http); + } + } + + } + + private void LoadDefaultMvcFileConfig(ClientDependencySection section) + { + if (section.MvcElement.Renderers.Count == 0) + { + var mvc = new StandardRenderer(); + mvc.Initialize(StandardRenderer.DefaultName, null); + MvcRendererCollection.Add(mvc); + } + else + { + ProvidersHelper.InstantiateProviders(section.MvcElement.Renderers, MvcRendererCollection, typeof(BaseRenderer)); + } + + } + } +} + diff --git a/DNN Platform/Components/ClientDependency/Source/Config/CompositeFileSection.cs b/DNN Platform/Components/ClientDependency/Source/Config/CompositeFileSection.cs new file mode 100644 index 00000000000..19c248a8e5d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/CompositeFileSection.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class CompositeFileSection : ConfigurationElement + { + + /// + /// All of the file processing providers registered + /// + [ConfigurationProperty("fileProcessingProviders")] + public ProviderSettingsCollection FileProcessingProviders + { + get { return (ProviderSettingsCollection)base["fileProcessingProviders"]; } + } + + /// + /// All of the File map providers registered + /// + [ConfigurationProperty("fileMapProviders")] + public ProviderSettingsCollection FileMapProviders + { + get { return (ProviderSettingsCollection)base["fileMapProviders"]; } + } + + /// + /// The default File processing provider + /// + [StringValidator(MinLength = 1)] + [ConfigurationProperty("defaultFileProcessingProvider", DefaultValue = "CompositeFileProcessor")] + public string DefaultFileProcessingProvider + { + get { return (string)base["defaultFileProcessingProvider"]; } + set { base["defaultFileProcessingProvider"] = value; } + } + + /// + /// The default file map provider + /// + [StringValidator(MinLength = 1)] + [ConfigurationProperty("defaultFileMapProvider", DefaultValue = "XmlFileMap")] + public string DefaultFileMapProvider + { + get { return (string)base["defaultFileMapProvider"]; } + set { base["defaultFileMapProvider"] = value; } + } + + [ConfigurationProperty("compositeFileHandlerPath", DefaultValue = "DependencyHandler.axd")] + public string CompositeFileHandlerPath + { + get { return (string)base["compositeFileHandlerPath"]; } + set { base["compositeFileHandlerPath"] = value; } + } + + [ConfigurationProperty("mimeTypeCompression")] + public MimeTypeCompressionCollection MimeTypeCompression + { + get + { + return (MimeTypeCompressionCollection)base["mimeTypeCompression"]; + } + } + + [ConfigurationProperty("rogueFileCompression")] + public RogueFileCompressionCollection RogueFileCompression + { + get + { + return (RogueFileCompressionCollection)base["rogueFileCompression"]; + } + } + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/FileRegistrationSection.cs b/DNN Platform/Components/ClientDependency/Source/Config/FileRegistrationSection.cs new file mode 100644 index 00000000000..84ef31a0f70 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/FileRegistrationSection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class FileRegistrationSection : ConfigurationElement + { + + [ConfigurationProperty("providers")] + public ProviderSettingsCollection Providers + { + get { return (ProviderSettingsCollection)base["providers"]; } + } + + [StringValidator(MinLength = 1)] + [ConfigurationProperty("defaultProvider", DefaultValue = "LoaderControlProvider")] + public string DefaultProvider + { + get { return (string)base["defaultProvider"]; } + set { base["defaultProvider"] = value; } + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionCollection.cs b/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionCollection.cs new file mode 100644 index 00000000000..af20f59d9d4 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionCollection.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + + + public class MimeTypeCompressionCollection : ConfigurationElementCollection + { + protected override bool ThrowOnDuplicate + { + get + { + return true; + } + } + + protected override ConfigurationElement CreateNewElement() + { + var e = new MimeTypeCompressionElement(); + return e; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((MimeTypeCompressionElement)element); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionElement.cs b/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionElement.cs new file mode 100644 index 00000000000..dbe39cf8634 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/MimeTypeCompressionElement.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class MimeTypeCompressionElement : ConfigurationElement + { + [ConfigurationProperty("type", IsRequired = true)] + public string MimeType + { + get + { + return (string)this["type"]; + } + } + + [ConfigurationProperty("path", DefaultValue = "*")] + public string FilePath + { + get + { + return (string)this["path"]; + } + } + + public override int GetHashCode() + { + return (this.MimeType + this.FilePath).GetHashCode(); + } + + public override bool Equals(object compareTo) + { + var e = compareTo as MimeTypeCompressionElement; + if (e != null) + { + return (e.GetHashCode().Equals(this.GetHashCode())); + } + return false; + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/MvcSection.cs b/DNN Platform/Components/ClientDependency/Source/Config/MvcSection.cs new file mode 100644 index 00000000000..1585009d16e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/MvcSection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class MvcSection : ConfigurationElement + { + + [ConfigurationProperty("renderers")] + public ProviderSettingsCollection Renderers + { + get { return (ProviderSettingsCollection)base["renderers"]; } + } + + [StringValidator(MinLength = 1)] + [ConfigurationProperty("defaultRenderer", DefaultValue = "StandardRenderer")] + public string DefaultRenderer + { + get { return (string)base["defaultRenderer"]; } + set { base["defaultRenderer"] = value; } + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionCollection.cs b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionCollection.cs new file mode 100644 index 00000000000..522f974bb8c --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionCollection.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class RogueFileCompressionCollection : ConfigurationElementCollection + { + protected override bool ThrowOnDuplicate + { + get + { + return true; + } + } + + protected override ConfigurationElement CreateNewElement() + { + var e = new RogueFileCompressionElement(); + return e; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((RogueFileCompressionElement)element); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionElement.cs b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionElement.cs new file mode 100644 index 00000000000..3496edbe909 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionElement.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + class RogueFileCompressionElement : ConfigurationElement + { + [ConfigurationProperty("compressJs", DefaultValue = true)] + public bool CompressJs + { + get + { + return (bool)this["compressJs"]; + } + } + + [ConfigurationProperty("compressCss", DefaultValue = true)] + public bool CompressCss + { + get + { + return (bool)this["compressCss"]; + } + } + + [ConfigurationProperty("path", DefaultValue = "*")] + public string FilePath + { + get + { + return (string)this["path"]; + } + } + + /// + /// a collection of file extensions that must match on the rogue file for it to + /// be replaced with the composite handler + /// + [ConfigurationProperty("jsExt", DefaultValue = ".js")] + public string JsRequestExtension + { + get + { + return (string)this["jsExt"]; + } + } + + /// + /// a collection of file extensions that must match on the rogue file for it to + /// be replaced with the composite handler + /// + [ConfigurationProperty("cssExt", DefaultValue = ".css")] + public string CssRequestExtension + { + get + { + return (string)this["cssExt"]; + } + } + + [ConfigurationProperty("exclusions")] + public RogueFileCompressionExcludeCollection ExcludePaths + { + get + { + return (RogueFileCompressionExcludeCollection)base["exclusions"]; + } + } + + public override int GetHashCode() + { + return this.FilePath.GetHashCode(); + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeCollection.cs b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeCollection.cs new file mode 100644 index 00000000000..45d31b80713 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeCollection.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + public class RogueFileCompressionExcludeCollection : ConfigurationElementCollection + { + protected override bool ThrowOnDuplicate + { + get + { + return true; + } + } + + protected override ConfigurationElement CreateNewElement() + { + var e = new RogueFileCompressionExcludeElement(); + return e; + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((RogueFileCompressionExcludeElement)element); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeElement.cs b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeElement.cs new file mode 100644 index 00000000000..13374bf43dc --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Config/RogueFileCompressionExcludeElement.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration; + +namespace ClientDependency.Core.Config +{ + + public class RogueFileCompressionExcludeElement : ConfigurationElement + { + [ConfigurationProperty("path", IsRequired = true)] + public string FilePath + { + get + { + return (string)this["path"]; + } + } + + public override int GetHashCode() + { + return this.FilePath.GetHashCode(); + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Constants.cs b/DNN Platform/Components/ClientDependency/Source/Constants.cs new file mode 100644 index 00000000000..c377c9b9189 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Constants.cs @@ -0,0 +1,22 @@ +namespace ClientDependency.Core +{ + public static class Constants + { + /// + /// If a priority is not set, the default will be 100. + /// + /// + /// This will generally mean that if a developer doesn't specify a priority it will come after all other dependencies that + /// have unless the priority is explicitly set above 100. + /// + public const int DefaultPriority = 100; + + /// + /// If a group is not set, the default will be 100. + /// + /// + /// Unless a group is specified, all dependencies will go into the same, default, group. + /// + public const int DefaultGroup = 100; + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/ControlExtensions.cs b/DNN Platform/Components/ClientDependency/Source/ControlExtensions.cs new file mode 100644 index 00000000000..900a3550034 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ControlExtensions.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.UI; +using ClientDependency.Core.Controls; +using System.Web; + +namespace ClientDependency.Core +{ + public static class ControlExtensions + { + + + + public static IEnumerable FlattenChildren(this Control control) + { + var children = control.Controls.Cast(); + return children.SelectMany(c => FlattenChildren(c)).Concat(children); + } + + public static IEnumerable FlattenChildren(this Control control) + { + var children = control.Controls + .Cast() + .Where(x => x is T); + return children.SelectMany(c => FlattenChildren(c)).Concat(children); + } + + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyInclude.cs b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyInclude.cs new file mode 100644 index 00000000000..eb0335d5305 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyInclude.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; + +namespace ClientDependency.Core.Controls +{ + public abstract class ClientDependencyInclude : Control, IClientDependencyFile, IRequiresHtmlAttributesParsing + { + protected ClientDependencyInclude() + { + Priority = Constants.DefaultPriority; + Group = Constants.DefaultGroup; + PathNameAlias = ""; + HtmlAttributes = new Dictionary(); + AddTag = true; + } + + protected ClientDependencyInclude(IClientDependencyFile file) + { + Priority = file.Priority; + PathNameAlias = file.PathNameAlias; + FilePath = file.FilePath; + DependencyType = file.DependencyType; + Group = file.Group; + AddTag = true; + HtmlAttributes = new Dictionary(); + } + + public ClientDependencyType DependencyType { get; internal set; } + + public string FilePath { get; set; } + public string PathNameAlias { get; set; } + public int Priority { get; set; } + public int Group { get; set; } + public bool AddTag { get; set; } + + /// + /// This can be empty and will use default provider + /// + public string ForceProvider { get; set; } + + public bool ForceBundle { get; set; } + + /// + /// Used to store additional attributes in the HTML markup for the item + /// + /// + /// Mostly used for CSS Media, but could be for anything + /// + public IDictionary HtmlAttributes { get; private set; } + + /// + /// Used to set the HtmlAttributes on this class via a string which is parsed + /// + /// + /// The syntax for the string must be: key1:value1,key2:value2 etc... + /// + public string HtmlAttributesAsString { get; set; } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + if (string.IsNullOrEmpty(FilePath)) + throw new NullReferenceException("Both File and Type properties must be set"); + } + + protected override void Render(HtmlTextWriter writer) + { + if (AddTag) + { + writer.Write("", DependencyType, FilePath); + } + + base.Render(writer); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyLoader.cs b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyLoader.cs new file mode 100644 index 00000000000..e5d70457788 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyLoader.cs @@ -0,0 +1,316 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web; +using System.Linq; +using ClientDependency.Core.Config; +using ClientDependency.Core.FileRegistration.Providers; + +namespace ClientDependency.Core.Controls +{ + [ParseChildren(typeof(ClientDependencyPath), ChildrenAsProperties = true)] + public class ClientDependencyLoader : Control + { + + /// + /// Constructor sets the defaults. + /// + public ClientDependencyLoader() + { + Paths = new ClientDependencyPathCollection(); + + _base = new BaseLoader(new HttpContextWrapper(Context)) + { + //by default the provider is the default provider + Provider = ClientDependencySettings.Instance.DefaultFileRegistrationProvider + }; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + //add this object to the context and validate the context type + if (Context != null) + { + if (!Context.Items.Contains(ContextKey)) + { + lock (Locker) + { + if (!Context.Items.Contains(ContextKey)) + { + //The context needs to be a page + var page = Context.Handler as Page; + if (page == null) + throw new InvalidOperationException("ClientDependencyLoader only works with Page based handlers."); + Context.Items[ContextKey] = this; + } + } + } + else + { + if (Context.Items[ContextKey] != this) + { + throw new InvalidOperationException("Only one ClientDependencyLoader may exist on a page"); + } + } + } + else + throw new InvalidOperationException("ClientDependencyLoader requires an HttpContext"); + } + + public const string ContextKey = "ClientDependencyLoader"; + + private static readonly object Locker = new object(); + + public string ProviderName + { + get + { + return _base.Provider.Name; + } + set + { + _base.Provider = ClientDependencySettings.Instance.FileRegistrationProviderCollection[value]; + } + } + + [Obsolete("Use the GetInstance() method instead to pass in an HttpContext object")] + public static ClientDependencyLoader Instance + { + get { return GetInstance(new HttpContextWrapper(HttpContext.Current)); } + } + + /// + /// Singleton per request instance. + /// + /// + /// If no ClientDependencyLoader control exists on the current page, an exception is thrown. + /// + public static ClientDependencyLoader GetInstance(HttpContextBase ctx) + { + if (!ctx.Items.Contains(ContextKey)) + return null; + return ctx.Items[ContextKey] as ClientDependencyLoader; + } + + private readonly BaseLoader _base; + + /// + /// Need to set the container for each of the paths to support databinding. + /// + protected override void CreateChildControls() + { + base.CreateChildControls(); + foreach (var path in Paths) + { + path.Parent = this; + } + } + + /// + /// Need to bind all children paths. + /// + /// + protected override void OnDataBinding(EventArgs e) + { + base.OnDataBinding(e); + foreach (var path in Paths) + { + path.DataBind(); + } + } + + /// + /// Finds all dependencies on the page and renders them + /// + /// + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + _base.Paths.UnionWith(Paths.Cast()); + RegisterClientDependencies((WebFormsFileRegistrationProvider)_base.Provider, Page, _base.Paths); + RenderDependencies(); + } + + private void RenderDependencies() + { + _base.Dependencies.ForEach(x => ((WebFormsFileRegistrationProvider)x.Provider) + .RegisterDependencies(Page, x.Dependencies, _base.Paths, new HttpContextWrapper(Context))); + } + + [PersistenceMode(PersistenceMode.InnerProperty)] + public ClientDependencyPathCollection Paths { get; private set; } + + #region Static Helper methods + + /// + /// Checks if a loader already exists, if it does, it returns it, otherwise it will + /// create a new one in the control specified. + /// isNew will be true if a loader was created, otherwise false if it already existed. + /// + /// + /// + /// + /// + public static ClientDependencyLoader TryCreate(Control parent, HttpContextBase http, out bool isNew) + { + if (GetInstance(http) == null) + { + var loader = new ClientDependencyLoader(); + parent.Controls.Add(loader); + isNew = true; + return loader; + } + isNew = false; + return GetInstance(http); + } + + #endregion + + /// + /// Registers a file dependency + /// + /// + /// + public ClientDependencyLoader RegisterDependency(string filePath, ClientDependencyType type) + { + _base.RegisterDependency(filePath, type); + return this; + } + + /// + /// Registers a file dependency + /// + public ClientDependencyLoader RegisterDependency(int priority, string filePath, ClientDependencyType type) + { + _base.RegisterDependency(priority, filePath, type); + return this; + } + + /// + /// Registers a file dependency + /// + public ClientDependencyLoader RegisterDependency(int priority, string filePath, string pathNameAlias, ClientDependencyType type) + { + _base.RegisterDependency(priority, filePath, pathNameAlias, type); + return this; + } + + /// + /// Registers a file dependency + /// + /// + /// + /// + public ClientDependencyLoader RegisterDependency(string filePath, string pathNameAlias, ClientDependencyType type) + { + _base.RegisterDependency(Constants.DefaultGroup, Constants.DefaultPriority, filePath, pathNameAlias, type); + return this; + } + + /// + /// Adds a path to the current loader + /// + /// + /// + public ClientDependencyLoader AddPath(string pathNameAlias, string path) + { + _base.AddPath(pathNameAlias, path); + return this; + } + + /// + /// Adds a path to the current loader + /// + /// + public ClientDependencyLoader AddPath(IClientDependencyPath path) + { + _base.AddPath(path); + return this; + } + + /// + /// Registers dependencies + /// + /// + /// + public void RegisterClientDependencies(Control control, ClientDependencyPathCollection paths) + { + RegisterClientDependencies((WebFormsFileRegistrationProvider)_base.Provider, control, paths.Cast()); + } + + /// + /// Registers dependencies with the provider name specified + /// + /// + /// + /// + public void RegisterClientDependencies(string providerName, Control control, IEnumerable paths) + { + RegisterClientDependencies(ClientDependencySettings.Instance.FileRegistrationProviderCollection[providerName], control, paths); + } + + /// + /// Registers dependencies with the provider specified by T + /// + public void RegisterClientDependencies(Control control, List paths) + where T : WebFormsFileRegistrationProvider + { + //need to find the provider with the type + var found = ClientDependencySettings.Instance.FileRegistrationProviderCollection + .Cast() + .FirstOrDefault(p => p.GetType().Equals(typeof (T))); + if (found == null) + throw new ArgumentException("Could not find the ClientDependencyProvider specified by T"); + + RegisterClientDependencies(found, control, paths); + } + + public void RegisterClientDependencies(WebFormsFileRegistrationProvider provider, Control control, IEnumerable paths) + { + var dependencies = FindDependencies(control); + _base.RegisterClientDependencies(provider, dependencies, paths, ClientDependencySettings.Instance.FileRegistrationProviderCollection); + } + + /// + /// Find all dependencies of this control and it's entire child control hierarchy. + /// + /// + /// + private static IEnumerable FindDependencies(Control control) + { + var ctls = new List(control.FlattenChildren()) { control }; + + var dependencies = new List(); + + // add child dependencies + var iClientDependency = typeof(IClientDependencyFile); + foreach (var ctl in ctls) + { + // find dependencies + var controlType = ctl.GetType(); + + //dependencies.AddRange(Attribute.GetCustomAttributes(controlType) + // .OfType() + // .Cast()); + + if (iClientDependency.IsAssignableFrom(ctl.GetType())) + { + var include = (IClientDependencyFile)ctl; + dependencies.Add(include); + } + + } + + return dependencies; + } + + } + + + + +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPath.cs b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPath.cs new file mode 100644 index 00000000000..203ab3f35d3 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPath.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; + +namespace ClientDependency.Core.Controls +{ + + /// + /// A path object for the client dependency loader. Used to specify all of the base paths (name and path) to + /// be used with the client dependencies. + /// Databinding support has been enabled. + /// + [ParseChildren(true)] + public class ClientDependencyPath : IClientDependencyPath + { + string _name = ""; + string _path = ""; + + public string Name { get { return _name; } set { _name = value; } } + public string Path { get { return _path; } set { _path = value; } } + + public bool ForceBundle { get; set; } + + #region Logic to allow for databinding non-UI ASP.Net control + public event EventHandler DataBinding; + public void DataBind() + { + OnDataBinding(new EventArgs()); + } + protected void OnDataBinding(EventArgs e) + { + if (DataBinding != null) + DataBinding(this, e); + } + public Control BindingContainer + { + get + { + return Parent; + } + } + #endregion + + /// + /// This is set at runtime to set the load for this path object. this is required for databinding. + /// + public ClientDependencyLoader Parent { get; internal set; } + + public string ResolvedPath + { + get + { + if (string.IsNullOrEmpty(Path)) + throw new ArgumentNullException("Path has not been set"); + return Parent.ResolveUrl(Path); + } + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPathCollection.cs b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPathCollection.cs new file mode 100644 index 00000000000..f94f1b3046d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/ClientDependencyPathCollection.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClientDependency.Core.Controls +{ + public class ClientDependencyPathCollection : List + { + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/CssInclude.cs b/DNN Platform/Components/ClientDependency/Source/Controls/CssInclude.cs new file mode 100644 index 00000000000..19b638b4225 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/CssInclude.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core.Controls +{ + public class CssInclude : ClientDependencyInclude + { + internal bool EncodeImages { get; set; } + + public CssInclude() + { + DependencyType = ClientDependencyType.Css; + CssMedia = CssMediaType.All; + } + public CssInclude(IClientDependencyFile file) + : base(file) + { + DependencyType = ClientDependencyType.Css; + CssMedia = CssMediaType.All; + } + public CssInclude(IClientDependencyFile file, CssMediaType mediaType) + : base(file) + { + DependencyType = ClientDependencyType.Css; + CssMedia = mediaType; + } + + public CssMediaType CssMedia { get; set; } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/HtmlInclude.cs b/DNN Platform/Components/ClientDependency/Source/Controls/HtmlInclude.cs new file mode 100644 index 00000000000..49ee11788a1 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/HtmlInclude.cs @@ -0,0 +1,95 @@ +using System; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Text.RegularExpressions; + +namespace ClientDependency.Core.Controls +{ + [ToolboxData("<{0}:HtmlInclude runat=\"server\">")] + public class HtmlInclude : Literal + { + public const string TagPattern = @"<{0}((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>"; + public const string AttributePattern = @"{0}(\s*=\s*(?:""(?.*?)""|'(?.*?)'|(?[^'"">\s]+)))"; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + var isNew = false; + var loader = ClientDependencyLoader.TryCreate(Page, new HttpContextWrapper(Context), out isNew); + + RegisterIncludes(Text, loader); + + Text = string.Empty; + } + + private static void RegisterIncludes(string innerHtml, ClientDependencyLoader loader) + { + RegisterCssIncludes(innerHtml, loader); + RegisterJsIncludes(innerHtml, loader); + } + + private static void RegisterCssIncludes(string innerHtml, ClientDependencyLoader loader) + { + var tagPattern = string.Format(TagPattern, "link"); + var typeAttributePattern = string.Format(AttributePattern, "type"); + var srcAttributePattern = string.Format(AttributePattern, "href"); + + var count = 0; + foreach (Match match in Regex.Matches(innerHtml, tagPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + var typeMatch = Regex.Match(match.Value, typeAttributePattern, + RegexOptions.Compiled | RegexOptions.IgnoreCase | + RegexOptions.CultureInvariant); + + if (typeMatch.Success && typeMatch.Groups["val"].Value == "text/css") + { + var srcMatch = Regex.Match(match.Value, srcAttributePattern, + RegexOptions.Compiled | RegexOptions.IgnoreCase | + RegexOptions.CultureInvariant); + + if (srcMatch.Success) + { + loader.RegisterDependency(Constants.DefaultPriority + count, + srcMatch.Groups["val"].Value, + ClientDependencyType.Css); + + count++; + } + } + } + } + + private static void RegisterJsIncludes(string innerHtml, ClientDependencyLoader loader) + { + var tagPattern = string.Format(TagPattern, "script"); + var typeAttributePattern = string.Format(AttributePattern, "type"); + var srcAttributePattern = string.Format(AttributePattern, "src"); + + var count = 0; + foreach (Match match in Regex.Matches(innerHtml, tagPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + var typeMatch = Regex.Match(match.Value, typeAttributePattern, + RegexOptions.Compiled | RegexOptions.IgnoreCase | + RegexOptions.CultureInvariant); + + if (typeMatch.Success && typeMatch.Groups["val"].Value == "text/javascript") + { + var srcMatch = Regex.Match(match.Value, srcAttributePattern, + RegexOptions.Compiled | RegexOptions.IgnoreCase | + RegexOptions.CultureInvariant); + + if (srcMatch.Success) + { + loader.RegisterDependency(Constants.DefaultPriority + count, + srcMatch.Groups["val"].Value, + ClientDependencyType.Javascript); + + count++; + } + } + } + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Controls/JsInclude.cs b/DNN Platform/Components/ClientDependency/Source/Controls/JsInclude.cs new file mode 100644 index 00000000000..1aec4b9fb30 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Controls/JsInclude.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core.Controls +{ + public class JsInclude : ClientDependencyInclude + { + + public JsInclude() + { + DependencyType = ClientDependencyType.Javascript; + } + public JsInclude(IClientDependencyFile file) + : base(file) + { + DependencyType = ClientDependencyType.Javascript; + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CssFileUrlFormatter.cs b/DNN Platform/Components/ClientDependency/Source/CssFileUrlFormatter.cs new file mode 100644 index 00000000000..d1b1214ca1e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CssFileUrlFormatter.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace ClientDependency.Core +{ + public class CssFileUrlFormatter + { + + /// + /// Returns the CSS file with all of the url's formatted to be absolute locations + /// + /// content of the css file + /// the uri location of the css file + /// + public static string TransformCssFile(string fileContent, Uri cssLocation) + { + string str = Regex.Replace( + fileContent, + @"url\(((?!data:).+?)\)", + new MatchEvaluator( + delegate(Match m) + { + if (m.Groups.Count == 2) + { + var match = m.Groups[1].Value.Trim('\'', '"'); + var hashSplit = match.Split(new[] {'#'}, StringSplitOptions.RemoveEmptyEntries); + + return string.Format(@"url(""{0}{1}"")", + match.StartsWith("http") ? match : new Uri(cssLocation, match).PathAndQuery, + hashSplit.Length > 1 ? ("#" + hashSplit[1]) : ""); + } + return m.Value; + }) + ); + + return str; + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/CssMediaType.cs b/DNN Platform/Components/ClientDependency/Source/CssMediaType.cs new file mode 100644 index 00000000000..5aa2cb1937c --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/CssMediaType.cs @@ -0,0 +1,7 @@ +namespace ClientDependency.Core +{ + public enum CssMediaType + { + All, Screen, Print + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/DependencyHtmlElement.cs b/DNN Platform/Components/ClientDependency/Source/DependencyHtmlElement.cs new file mode 100644 index 00000000000..1ef46edf03c --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/DependencyHtmlElement.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace ClientDependency.Core +{ + /// + /// A simple model defining the source of the dependency and the Html Elements that need to be rendered as part of the html tag + /// + public class DependencyHtmlElement + { + public string Source { get; set; } + public IDictionary HtmlAttributes { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/DictionaryExtensions.cs b/DNN Platform/Components/ClientDependency/Source/DictionaryExtensions.cs new file mode 100644 index 00000000000..de31de434fe --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/DictionaryExtensions.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ClientDependency.Core +{ + public static class DictionaryExtensions + { + + /// + /// Returns the dictionary as formatted html attributes for use in an html tag + /// + /// + /// + public static string ToHtmlAttributes(this IDictionary d) + { + return string.Join(" ", d.Select(x => x.Key + "=\"" + x.Value + "\"").ToArray()); + } + + /// + /// Determines if 2 dictionaries contain the exact same keys/values + /// + /// + /// + /// + public static bool IsEqualTo(this IDictionary d, IDictionary compareTo) + { + if (d.Count != compareTo.Count) + return false; + + foreach(var i in d) + { + if (!compareTo.ContainsKey(i.Key)) + return false; + if (!compareTo[i.Key].Equals(i.Value, StringComparison.InvariantCultureIgnoreCase)) + return false; + } + + return true; + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseFileRegistrationProvider.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseFileRegistrationProvider.cs new file mode 100644 index 00000000000..5703276a052 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseFileRegistrationProvider.cs @@ -0,0 +1,358 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Text; +using System.Web.UI; +using System.Configuration.Provider; +using System.Web; +using System.Linq; +using ClientDependency.Core.CompositeFiles.Providers; +using ClientDependency.Core.Controls; +using ClientDependency.Core.Config; +using ClientDependency.Core; +using ClientDependency.Core.CompositeFiles; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public abstract class BaseFileRegistrationProvider : ProviderBase + { + /// + /// Constructor sets defaults + /// + protected BaseFileRegistrationProvider() + { + EnableCompositeFiles = true; + } + + //protected HashSet FolderPaths { get; set; } + //protected List AllDependencies { get; set; } + + /// + /// By default this is true but can be overriden (in either config or code). + /// Composite files are never enabled with compilation debug="true" however. + /// + public virtual bool EnableCompositeFiles { get; set; } + + ///// + ///// By default this is empty, but if you want to explicity define a base url for dependencies you can + ///// + //public string WebsiteBaseUrl { get; set; } + + #region Abstract methods/properties + + protected abstract string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes); + protected abstract string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes); + + protected abstract string RenderSingleJsFile(string js, IDictionary htmlAttributes); + protected abstract string RenderSingleCssFile(string css, IDictionary htmlAttributes); + + #endregion + + #region Provider Initialization + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + base.Initialize(name, config); + + if (config != null && config["enableCompositeFiles"] != null && !string.IsNullOrEmpty(config["enableCompositeFiles"])) + { + EnableCompositeFiles = bool.Parse(config["enableCompositeFiles"]); + } + + //if (config != null && config["websiteBaseUrl"] != null && !string.IsNullOrEmpty(config["websiteBaseUrl"])) + //{ + // WebsiteBaseUrl = config["website"]; + // if (!string.IsNullOrEmpty(WebsiteBaseUrl)) + // WebsiteBaseUrl = WebsiteBaseUrl.TrimEnd('/'); + //} + } + + #endregion + + #region Protected Methods + + /// + /// Because we can have both internal and external dependencies rendered, we need to stagger the script tag output... if they are external, we need to stop the compressing/combining + /// and write out the external dependency, then resume the compressing/combining handler. + /// + /// + /// + /// + /// + /// + protected void WriteStaggeredDependencies( + IEnumerable dependencies, + HttpContextBase http, + StringBuilder builder, + Func, HttpContextBase, IDictionary, string> renderCompositeFiles, + Func, string> renderSingle) + { + + + //This action will stagger the output based on whether or not the html attribute declarations are the same for each dependency + Action> staggerOnDifferentAttributes = (list) => + { + var sameAttributes = new List(); + var currHtmlAttr = GetHtmlAttributes(list.ElementAt(0)); + foreach (var c in list) + { + if (!currHtmlAttr.IsEqualTo(GetHtmlAttributes(c))) + { + //if the attributes are different we need to stagger + if (sameAttributes.Any()) + { + //render the current buffer + builder.Append(renderCompositeFiles(sameAttributes, http, currHtmlAttr)); + //clear the buffer + sameAttributes.Clear(); + } + } + + //add the item to the buffer and set the current html attributes + sameAttributes.Add(c); + currHtmlAttr = GetHtmlAttributes(c); + } + + //if there's anything in the buffer then write the remaining + if (sameAttributes.Any()) + builder.Append(renderCompositeFiles(sameAttributes, http, currHtmlAttr)); + }; + + var currNonRemoteFiles = new List(); + foreach (var f in dependencies) + { + //if it is an external resource, then we need to break the sequence + // unless it has been explicitely required that the dependency be bundled + if (http.IsAbsolutePath(f.FilePath) + //remote dependencies aren't local + && !new Uri(f.FilePath, UriKind.RelativeOrAbsolute).IsLocalUri(http) + // not required to be bundled + && !f.ForceBundle) + { + //we've encountered an external dependency, so we need to break the sequence and restart it after + //we output the raw script tag + if (currNonRemoteFiles.Count > 0) + { + //render the current buffer + staggerOnDifferentAttributes(currNonRemoteFiles); + //clear the buffer + currNonRemoteFiles.Clear(); + } + //write out the single script tag + builder.Append(renderSingle(f.FilePath, GetHtmlAttributes(f))); + } + else + { + //its a normal registration, add to the buffer + currNonRemoteFiles.Add(f); + } + } + //now check if there's anything in the buffer to render + if (currNonRemoteFiles.Count > 0) + { + //render the current buffer + staggerOnDifferentAttributes(currNonRemoteFiles); + } + } + + /// + /// Ensures the correctly resolved file path is set for each dependency (i.e. so that ~ are taken care of) and also + /// prefixes the file path with the correct base path specified for the PathNameAlias if specified. + /// + /// The dependencies list for which file paths will be updated + /// + /// + protected virtual void UpdateFilePaths(IEnumerable dependencies, + HashSet folderPaths, HttpContextBase http) + { + foreach (var dependency in dependencies) + { + if (!string.IsNullOrEmpty(dependency.PathNameAlias)) + { + var paths = folderPaths.ToList(); + var d = dependency; + var path = paths.Find( + (p) => p.Name == d.PathNameAlias); + if (path == null) + { + throw new NullReferenceException("The PathNameAlias specified for dependency " + dependency.FilePath + " does not exist in the ClientDependencyPathCollection"); + } + var resolvedPath = path.ResolvePath(http); + var basePath = resolvedPath.EndsWith("/") ? resolvedPath : resolvedPath + "/"; + dependency.FilePath = basePath + dependency.FilePath; + dependency.ForceBundle = (dependency.ForceBundle | path.ForceBundle); + } + else + { + dependency.FilePath = dependency.ResolveFilePath(http); + } + + //append query strings to each file if we are in debug mode + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + dependency.FilePath = AppendVersion(dependency.FilePath, http); + } + } + } + + + /// + /// This will ensure that no duplicates have made it into the collection. + /// Duplicates WILL occur if the same dependency is registered in 2 different ways: + /// one with a global path and one with a full path. This is because paths may not be defined + /// until we render so we cannot de-duplicate at the time of registration. + /// De-duplication will remove the dependency with a lower priority or later in the list. + /// This also must be called after UpdatePaths are called since we need to full path filled in. + /// + /// The dependencies list for which duplicates will be removed + /// + protected virtual void EnsureNoDuplicates(List dependencies, HashSet folderPaths) + { + var toKeep = new HashSet(); + + foreach (var d in dependencies) + { + //check if it is a duplicate + if (dependencies + .Where(x => x.FilePath.ToUpper().Trim().Equals(d.FilePath.ToUpper().Trim())) + .Any()) + { + //find the dups and return an object with the associated index + var dups = dependencies + .Where(x => x.FilePath.ToUpper().Trim().Equals(d.FilePath.ToUpper().Trim())) + .Select((x, index) => new { Index = index, File = x }) + .ToList(); + + var priorities = dups.Select(x => x.File.Priority).Distinct().ToList(); + + //if there's more than 1 priority defined, we know we need to remove by priority + //instead of by index + if (priorities.Count() > 1) + { + toKeep.Add(dups + .Where(x => x.File.Priority == priorities.Min()) + .First().File); + } + else + { + //if not by priority, we just need to keep the first on in the list + toKeep.Add(dups + .Where(x => x.Index == dups + .Select(p => p.Index) + .Min()) + .First().File); + } + } + else + { + //if there's only one found, then just add it to our output + toKeep.Add(d); + } + + + } + + dependencies.Clear(); + dependencies.AddRange(toKeep); + + + } + + private string AppendVersion(string url, HttpContextBase http) + { + var version = this.GetVersion(); + if (version == 0) + return url; + if ((http.IsDebuggingEnabled || !EnableCompositeFiles) + || ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.UrlType == CompositeUrlType.Base64QueryStrings) + { + //ensure there's not duplicated query string syntax + url += url.Contains('?') ? "&" : "?"; + //append a version + url += "cdv=" + version; + } + else + { + //the URL should end with a '0' + url = url.TrimEnd('0') + version; + } + return url; + } + + public virtual int GetVersion() + { + return ClientDependencySettings.Instance.Version; + } + + #endregion + + ///// + ///// Checks if the "website" config param has been passed in, if so this formats the url + ///// to be an absolute URL with the pre-pended domain + ///// + ///// + ///// + //protected string MapToWebsiteBaseUrl(string url) + //{ + // if (!string.IsNullOrEmpty(WebsiteBaseUrl)) + // { + // if (url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) + // || url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) + // return url; + + // // make sure the url begins with a / + // string slashedUrl = (url[0] != '/' ? "/" : string.Empty) + url; + + // return WebsiteBaseUrl + slashedUrl; + // } + // return url; + //} + + + /// + /// Checks if the current file implements the html attribute interfaces and returns the appropriate html attributes + /// + /// + /// + private static IDictionary GetHtmlAttributes(IClientDependencyFile file) + { + IDictionary attributes = new Dictionary(); + + if (file is IHaveHtmlAttributes) + { + var fileWithAttributes = (IHaveHtmlAttributes)file; + attributes = fileWithAttributes.HtmlAttributes; + + if (file is IRequiresHtmlAttributesParsing) + { + //we need to parse the attributes into the dictionary + HtmlAttributesStringParser.ParseIntoDictionary(((IRequiresHtmlAttributesParsing)file).HtmlAttributesAsString, attributes); + } + } + + //now we must ensure that the correct js/css attribute exist! + switch(file.DependencyType) + { + case ClientDependencyType.Javascript: + if (!attributes.ContainsKey("type")) + attributes.Add("type", "text/javascript"); + if (attributes.ContainsKey("src")) + attributes.Remove("src"); + break; + case ClientDependencyType.Css: + if (!attributes.ContainsKey("type")) + attributes.Add("type", "text/css"); + if (!attributes.ContainsKey("rel")) + attributes.Add("rel", "stylesheet"); + if (attributes.ContainsKey("href")) + attributes.Remove("href"); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + //just return an empty dictionary + return attributes; + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseRenderer.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseRenderer.cs new file mode 100644 index 00000000000..5b0a30e81dc --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/BaseRenderer.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration.Provider; +using ClientDependency.Core.Config; +using ClientDependency.Core.FileRegistration.Providers; +using System.IO; +using System.Web; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public abstract class BaseRenderer : BaseFileRegistrationProvider + { + + + public virtual void RegisterDependencies(List allDependencies, + HashSet paths, + out string jsOutput, + out string cssOutput, + HttpContextBase http) + { + var folderPaths = paths; + + UpdateFilePaths(allDependencies, folderPaths, http); + EnsureNoDuplicates(allDependencies, folderPaths); + + var cssBuilder = new StringBuilder(); + var jsBuilder = new StringBuilder(); + + // find the groups + var groups = allDependencies + .Select(x => x.Group) + .Distinct() + .ToList(); + + // sort them + groups.Sort((a, b) => a.CompareTo(b)); + + foreach (var group in groups) + { + var g = group; + var jsDependencies = allDependencies + .Where(x => x.Group == g && x.DependencyType == ClientDependencyType.Javascript) + .ToList(); + + var cssDependencies = allDependencies + .Where(x => x.Group == g && x.DependencyType == ClientDependencyType.Css) + .ToList(); + + // sort by priority + jsDependencies.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + cssDependencies.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + + //render + WriteStaggeredDependencies(cssDependencies, http, cssBuilder, RenderCssDependencies, RenderSingleCssFile); + WriteStaggeredDependencies(jsDependencies, http, jsBuilder, RenderJsDependencies, RenderSingleJsFile); + + } + cssOutput = cssBuilder.ToString(); + jsOutput = jsBuilder.ToString(); + } + } +} + diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/FileRegistrationProviderCollection.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/FileRegistrationProviderCollection.cs new file mode 100644 index 00000000000..5e43e0f9e5e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/FileRegistrationProviderCollection.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Configuration.Provider; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class FileRegistrationProviderCollection : ProviderCollection + { + public new WebFormsFileRegistrationProvider this[string name] + { + get { return (WebFormsFileRegistrationProvider)base[name]; } + } + + public override void Add(ProviderBase provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + + if (!(provider is WebFormsFileRegistrationProvider)) + throw new ArgumentException("Invalid provider type", "provider"); + + base.Add(provider); + } + + } + +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/HtmlEmbedContants.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/HtmlEmbedContants.cs new file mode 100644 index 00000000000..037775fc65d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/HtmlEmbedContants.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class HtmlEmbedContants + { + public const string ScriptEmbedWithSource = ""; + public const string CssEmbedWithSource = ""; + + public const string ScriptEmbedWithCode = ""; + //public const string CssEmbed = ""; + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadProvider.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadProvider.cs new file mode 100644 index 00000000000..5a5c5f4c2c2 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadProvider.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; +using ClientDependency.Core.Config; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class LazyLoadProvider : WebFormsFileRegistrationProvider + { + + public const string DefaultName = "LazyLoadProvider"; + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + // Assign the provider a default name if it doesn't have one + if (string.IsNullOrEmpty(name)) + name = DefaultName; + + base.Initialize(name, config); + } + + /// Path to the dependency loader we need for adding control dependencies. + protected const string DependencyLoaderResourceName = "ClientDependency.Core.Resources.LazyLoader.js"; + + protected override string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!jsDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in jsDependencies) + { + sb.Append(RenderSingleJsFile(string.Format("'{0}','{1}'", dependency.FilePath, string.Empty), htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(jsDependencies, ClientDependencyType.Javascript, http); + foreach (var s in comp) + { + sb.Append(RenderSingleJsFile(string.Format("'{0}','{1}'", s, string.Empty), htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleJsFile(string js, IDictionary htmlAttributes) + { + var strClientLoader = new StringBuilder("CDLazyLoader"); + strClientLoader.AppendFormat(".AddJs({0})", js); + strClientLoader.Append(';'); + return strClientLoader.ToString(); + } + + protected override string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!cssDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in cssDependencies) + { + sb.Append(RenderSingleCssFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(cssDependencies, ClientDependencyType.Css, http); + foreach (var s in comp) + { + sb.Append(RenderSingleCssFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleCssFile(string css, IDictionary htmlAttributes) + { + var strClientLoader = new StringBuilder("CDLazyLoader"); + strClientLoader.AppendFormat(".AddCss('{0}')", css); + strClientLoader.Append(';'); + return strClientLoader.ToString(); + } + + protected override void RegisterDependencies(HttpContextBase http, string js, string css) + { + if (!(http.CurrentHandler is Page)) + { + throw new InvalidOperationException("The current HttpHandler in a WebFormsFileRegistrationProvider must be of type Page"); + } + var page = (Page)http.CurrentHandler; + + page.ClientScript.RegisterClientScriptResource(typeof(LazyLoadProvider), DependencyLoaderResourceName); + + RegisterScript(js, page); + RegisterScript(css, page); + } + + private void RegisterScript(string strScript, Page page) + { + var mgr = ScriptManager.GetCurrent(page); + + if (mgr == null) + { + if (page.Form == null) + throw new InvalidOperationException("A form tag must be present on the page with a runat='server' attribute specified"); + page.ClientScript.RegisterStartupScript(GetType(), strScript.GetHashCode().ToString(), strScript, true); + } + else + { + ScriptManager.RegisterStartupScript(page, GetType(), strScript.GetHashCode().ToString(), strScript, true); + } + } + + } + +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadRenderer.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadRenderer.cs new file mode 100644 index 00000000000..6c39439dd79 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LazyLoadRenderer.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.Config; +using System.Web.UI; +using System.Web; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class LazyLoadRenderer : BaseRenderer + { + public const string DefaultName = "LazyLoadRenderer"; + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + // Assign the provider a default name if it doesn't have one + if (string.IsNullOrEmpty(name)) + name = DefaultName; + + base.Initialize(name, config); + } + + /// Path to the dependency loader we need for adding control dependencies. + protected const string DependencyLoaderResourceName = "ClientDependency.Core.Resources.LazyLoader.js"; + + + private static readonly object Locker = new object(); + + + /// + /// This is silly to have to do this but MS don't give you a way in MVC to do this + /// + /// + /// + /// + private string GetWebResourceUrl(Type type, string resourceId) + { + if (type == null) + type = GetType(); + + var page = new Page(); + return page.ClientScript.GetWebResourceUrl(type, resourceId); + } + + /// + /// This will check if the lazy loader script has been registered yet (it does this by storing a flah in the HttpContext.Items) + /// if it hasn't then it will add the script registration to the StringBuilder + /// + /// + /// + private void RegisterLazyLoadScript(StringBuilder sb, HttpContextBase http) + { + if (http.Items["LazyLoaderLoaded"] == null || (bool)http.Items["LazyLoaderLoaded"] == false) + { + lock (Locker) + { + if (http.Items["LazyLoaderLoaded"] == null || (bool)http.Items["LazyLoaderLoaded"] == false) + { + http.Items["LazyLoaderLoaded"] = true; + + var url = GetWebResourceUrl(typeof(LazyLoadProvider), DependencyLoaderResourceName); + sb.Append(string.Format(HtmlEmbedContants.ScriptEmbedWithSource, url, "")); + } + } + } + } + + protected override string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!jsDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in jsDependencies) + { + sb.Append(RenderSingleJsFile(string.Format("'{0}','{1}'", dependency.FilePath, string.Empty), htmlAttributes)); + } + } + else + { + + RegisterLazyLoadScript(sb, http); + + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(jsDependencies, ClientDependencyType.Javascript, http); + foreach (var s in comp) + { + sb.Append(RenderSingleJsFile(string.Format("'{0}','{1}'", s, string.Empty), htmlAttributes)); + } + } + + return sb.ToString(); + } + + /// + /// Registers the Css dependencies. + /// + /// + /// + /// + /// + protected override string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!cssDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in cssDependencies) + { + sb.Append(RenderSingleCssFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + + RegisterLazyLoadScript(sb, http); + + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(cssDependencies, ClientDependencyType.Css, http); + foreach (var s in comp) + { + sb.Append(RenderSingleCssFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleJsFile(string js, IDictionary htmlAttributes) + { + var strClientLoader = new StringBuilder("CDLazyLoader"); + strClientLoader.AppendFormat(".AddJs({0})", js); + strClientLoader.Append(';'); + + return string.Format(HtmlEmbedContants.ScriptEmbedWithCode, strClientLoader.ToString()); + } + + protected override string RenderSingleCssFile(string css, IDictionary htmlAttributes) + { + var strClientLoader = new StringBuilder("CDLazyLoader"); + strClientLoader.AppendFormat(".AddCss('{0}')", css); + strClientLoader.Append(';'); + + return string.Format(HtmlEmbedContants.ScriptEmbedWithCode, strClientLoader); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LoaderControlProvider.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LoaderControlProvider.cs new file mode 100644 index 00000000000..2e18ee1598e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/LoaderControlProvider.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Web.UI; +using ClientDependency.Core.Controls; +using ClientDependency.Core.Config; +using System.Web; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class LoaderControlProvider : WebFormsFileRegistrationProvider + { + + public const string DefaultName = "LoaderControlProvider"; + + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + // Assign the provider a default name if it doesn't have one + if (string.IsNullOrEmpty(name)) + name = DefaultName; + + base.Initialize(name, config); + } + + protected override string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!jsDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in jsDependencies) + { + sb.Append(RenderSingleJsFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(jsDependencies, ClientDependencyType.Javascript, http); + foreach (var s in comp) + { + sb.Append(RenderSingleJsFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!cssDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in cssDependencies) + { + sb.Append(RenderSingleCssFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(cssDependencies, ClientDependencyType.Css, http); + foreach (var s in comp) + { + sb.Append(RenderSingleCssFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleJsFile(string js, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.ScriptEmbedWithSource, js, htmlAttributes.ToHtmlAttributes()); + } + + protected override string RenderSingleCssFile(string css, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.CssEmbedWithSource, css, htmlAttributes.ToHtmlAttributes()); + } + + /// + /// Registers the dependencies as controls of the LoaderControl controls collection + /// + /// + /// + /// + /// + /// For some reason ampersands that aren't html escaped are not compliant to HTML standards when they exist in 'link' or 'script' tags in URLs, + /// we need to replace the ampersands with & . This is only required for this one w3c compliancy, the URL itself is a valid URL. + /// + protected override void RegisterDependencies(HttpContextBase http, string js, string css) + { + AddToControl(http, css.Replace("&", "&")); + AddToControl(http, js.Replace("&", "&")); + } + + private static void AddToControl(HttpContextBase http, string literal) + { + var dCtl = new LiteralControl(literal); + ClientDependencyLoader.GetInstance(http).Controls.Add(dCtl); + } + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/PageHeaderProvider.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/PageHeaderProvider.cs new file mode 100644 index 00000000000..a18d052850c --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/PageHeaderProvider.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Linq; +using ClientDependency.Core.Config; +using System.Web; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class PageHeaderProvider : WebFormsFileRegistrationProvider + { + + public const string DefaultName = "PageHeaderProvider"; + + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + // Assign the provider a default name if it doesn't have one + if (string.IsNullOrEmpty(name)) + name = DefaultName; + + base.Initialize(name, config); + } + + protected override string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!jsDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in jsDependencies) + { + sb.Append(RenderSingleJsFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(jsDependencies, ClientDependencyType.Javascript, http); + foreach (var s in comp) + { + sb.Append(RenderSingleJsFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleJsFile(string js, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.ScriptEmbedWithSource, js, htmlAttributes.ToHtmlAttributes()); + } + + protected override string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!cssDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in cssDependencies) + { + sb.Append(RenderSingleCssFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(cssDependencies, ClientDependencyType.Css, http); + foreach (var s in comp) + { + sb.Append(RenderSingleCssFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleCssFile(string css, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.CssEmbedWithSource, css, htmlAttributes.ToHtmlAttributes()); + } + + /// + /// Registers the dependencies in the page header + /// + /// + /// + /// + /// + /// For some reason ampersands that aren't html escaped are not compliant to HTML standards when they exist in 'link' or 'script' tags in URLs, + /// we need to replace the ampersands with & . This is only required for this one w3c compliancy, the URL itself is a valid URL. + /// + /// + protected override void RegisterDependencies(HttpContextBase http, string js, string css) + { + if (!(http.CurrentHandler is Page)) + { + throw new InvalidOperationException("The current HttpHandler in a WebFormsFileRegistrationProvider must be of type Page"); + } + var page = (Page) http.CurrentHandler; + + if (page.Header == null) + throw new NullReferenceException("PageHeaderProvider requires a runat='server' tag in the page's header tag"); + + var jsScriptBlock = new LiteralControl(js.Replace("&", "&")); + var cssStyleBlock = new LiteralControl(css.Replace("&", "&")); + page.Header.Controls.Add(cssStyleBlock); + page.Header.Controls.Add(jsScriptBlock); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/RendererCollection.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/RendererCollection.cs new file mode 100644 index 00000000000..e85a07174c3 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/RendererCollection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration.Provider; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class RendererCollection : ProviderCollection + { + public new BaseRenderer this[string name] + { + get { return (BaseRenderer)base[name]; } + } + + public override void Add(ProviderBase provider) + { + if (provider == null) + throw new ArgumentNullException("provider"); + + if (!(provider is BaseRenderer)) + throw new ArgumentException("Invalid provider type", "provider"); + + base.Add(provider); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/StandardRenderer.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/StandardRenderer.cs new file mode 100644 index 00000000000..7187e2866c8 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/StandardRenderer.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.Config; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public class StandardRenderer : BaseRenderer + { + + public const string DefaultName = "StandardRenderer"; + + public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) + { + // Assign the provider a default name if it doesn't have one + if (string.IsNullOrEmpty(name)) + name = DefaultName; + + base.Initialize(name, config); + } + + protected override string RenderJsDependencies(IEnumerable jsDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!jsDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in jsDependencies) + { + sb.Append(RenderSingleJsFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(jsDependencies, ClientDependencyType.Javascript, http); + foreach (var s in comp) + { + sb.Append(RenderSingleJsFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderCssDependencies(IEnumerable cssDependencies, HttpContextBase http, IDictionary htmlAttributes) + { + if (!cssDependencies.Any()) + return string.Empty; + + var sb = new StringBuilder(); + + if (http.IsDebuggingEnabled || !EnableCompositeFiles) + { + foreach (var dependency in cssDependencies) + { + sb.Append(RenderSingleCssFile(dependency.FilePath, htmlAttributes)); + } + } + else + { + var comp = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList(cssDependencies, ClientDependencyType.Css, http); + foreach (var s in comp) + { + sb.Append(RenderSingleCssFile(s, htmlAttributes)); + } + } + + return sb.ToString(); + } + + protected override string RenderSingleJsFile(string js, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.ScriptEmbedWithSource, js, htmlAttributes.ToHtmlAttributes()); + } + + protected override string RenderSingleCssFile(string css, IDictionary htmlAttributes) + { + return string.Format(HtmlEmbedContants.CssEmbedWithSource, css, htmlAttributes.ToHtmlAttributes()); + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/WebFormsFileRegistrationProvider.cs b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/WebFormsFileRegistrationProvider.cs new file mode 100644 index 00000000000..a7b2a6820f7 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/FileRegistration/Providers/WebFormsFileRegistrationProvider.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Configuration.Provider; +using System.Web; +using System.Linq; +using ClientDependency.Core.Controls; +using ClientDependency.Core.Config; + +namespace ClientDependency.Core.FileRegistration.Providers +{ + public abstract class WebFormsFileRegistrationProvider : BaseFileRegistrationProvider + { + /// + /// Called to register the js and css into the page/control/output. + /// + /// + /// + /// + protected abstract void RegisterDependencies(HttpContextBase http, string js, string css); + + /// + /// Called to register the dependencies into the page/control/output + /// + /// + /// + /// + /// + public void RegisterDependencies( + Control dependantControl, + List allDependencies, + HashSet paths, + HttpContextBase http) + { + var ctl = dependantControl; + + var folderPaths = paths; + + UpdateFilePaths(allDependencies, folderPaths, http); + EnsureNoDuplicates(allDependencies, folderPaths); + + var cssBuilder = new StringBuilder(); + var jsBuilder = new StringBuilder(); + + // find the groups + var groups = allDependencies + .Select(x => x.Group) + .Distinct() + .ToList(); + + // sort them + groups.Sort((a, b) => a.CompareTo(b)); + + foreach (var group in groups) + { + var g = group; + // get the js and css dependencies for this group + var jsDependencies = allDependencies + .Where(x => x.Group == g && x.DependencyType == ClientDependencyType.Javascript) + .ToList(); + + var cssDependencies = allDependencies + .Where(x => x.Group == g && x.DependencyType == ClientDependencyType.Css) + .ToList(); + + // sort according to priority + jsDependencies.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + cssDependencies.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + + //render + WriteStaggeredDependencies(cssDependencies, http, cssBuilder, RenderCssDependencies, RenderSingleCssFile); + WriteStaggeredDependencies(jsDependencies, http, jsBuilder, RenderJsDependencies, RenderSingleJsFile); + } + + var cssOutput = cssBuilder.ToString(); + var jsOutput = jsBuilder.ToString(); + RegisterDependencies(http, jsOutput, cssOutput); + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/HtmlAttributesStringParser.cs b/DNN Platform/Components/ClientDependency/Source/HtmlAttributesStringParser.cs new file mode 100644 index 00000000000..11478924eea --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/HtmlAttributesStringParser.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Query.Dynamic; + +namespace ClientDependency.Core +{ + internal static class HtmlAttributesStringParser + { + + internal static void ParseIntoDictionary(string attributes, IDictionary destination) + { + if (string.IsNullOrEmpty(attributes)) + return; + if (destination == null) + return; + + foreach (var parts in attributes.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Split(new[] {':'}, StringSplitOptions.RemoveEmptyEntries))) + { + if (parts.Length != 2) + { + throw new ParseException("Could not parse html string attributes, the format must be key1:value1,key2:value2", parts.Length); + } + + if (!destination.ContainsKey(parts[0])) + destination.Add(parts[0], parts[1]); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/HttpContextBaseExtensions.cs b/DNN Platform/Components/ClientDependency/Source/HttpContextBaseExtensions.cs new file mode 100644 index 00000000000..9517d780611 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/HttpContextBaseExtensions.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +namespace ClientDependency.Core +{ + + /// + /// Extension methods for the HttpContext object + /// + public static class HttpContextBaseExtensions + { + + public static void AddCompressionResponseHeader(this HttpContextBase context, CompressionType cType) + { + if (cType == CompressionType.deflate) + { + context.Response.AddHeader("Content-encoding", "deflate"); + } + else if (cType == CompressionType.gzip) + { + context.Response.AddHeader("Content-encoding", "gzip"); + } + } + + /// + /// Check what kind of compression to use. Need to select the first available compression + /// from the header value as this is how .Net performs caching by compression so we need to follow + /// this process. + /// If IE 6 is detected, we will ignore compression as it's known that some versions of IE 6 + /// have issues with it. + /// + public static CompressionType GetClientCompression(this HttpContextBase context) + { + CompressionType type = CompressionType.none; + + if (context.Request.UserAgent.Contains("MSIE 6")) + { + return type; + } + + string acceptEncoding = context.Request.Headers["Accept-Encoding"]; + + if (!string.IsNullOrEmpty(acceptEncoding)) + { + string[] supported = acceptEncoding.Split(','); + //get the first type that we support + for (var i = 0; i < supported.Length; i++) + { + if (supported[i].Contains("deflate")) + { + type = CompressionType.deflate; + break; + } + else if (supported[i].Contains("gzip")) //sometimes it could be x-gzip! + { + type = CompressionType.gzip; + break; + } + } + } + + return type; + } + + + /// + /// Checks for absolute path to root of the website. + /// + /// + /// This was taken from the mono source so should be accurate. + /// The reason we're not using the VirtualPathUtility one is because it has bugs in 3.5 whereas + /// if the path has query strings, it throws exceptions. + /// + /// + /// + /// + public static bool IsAbsolute(this HttpContextBase context, string virtualPath) + { + if (IsAbsolutePath(context, virtualPath)) + { + throw new InvalidOperationException("IsAbsolute method will check if a Virtual path is absolute, it is not supported for full URLs"); + } + + if (string.IsNullOrEmpty(virtualPath)) + throw new ArgumentNullException("virtualPath"); + + return (virtualPath[0] == '/' || virtualPath[0] == '\\'); + } + + /// + /// Returns a site relative HTTP path from a partial path starting out with a ~. + /// Same syntax that ASP.Net internally supports but this method can be used + /// outside of the Page framework. + /// + /// Works like Control.ResolveUrl including support for ~ syntax + /// but returns an absolute URL. + /// + /// + /// Any Url including those starting with ~ + /// relative url + public static string ResolveUrl(this HttpContextBase context, string originalUrl) + { + if (string.IsNullOrEmpty(originalUrl)) + return originalUrl; + + // *** Absolute path - just return + if (context.IsAbsolutePath(originalUrl)) + return originalUrl; + + // *** We don't start with the '~' -> we don't process the Url + if (!originalUrl.StartsWith("~/")) + return originalUrl; + + // *** Fix up path for ~ root app dir directory + // VirtualPathUtility blows up if there is a + // query string, so we have to account for this. + int queryStringStartIndex = originalUrl.IndexOf('?'); + if (queryStringStartIndex != -1) + { + string queryString = originalUrl.Substring(queryStringStartIndex); + string baseUrl = originalUrl.Substring(0, queryStringStartIndex); + + return string.Concat( + VirtualPathUtility.ToAbsolute(baseUrl, context.Request.ApplicationPath), + queryString); + } + else + { + return VirtualPathUtility.ToAbsolute(originalUrl, context.Request.ApplicationPath); + } + + } + + /// + /// Checks for an absolute http path + /// + /// + /// Takes into account this type of url: + /// ~/pathtoresolve/page.aspx?returnurl=http://servertoredirect/resource.aspx + /// which is not an absolute path but contains the characters to describe it as one. + /// + /// + /// + /// + public static bool IsAbsolutePath(this HttpContextBase context, string originalUrl) + { + // *** Absolute path - just return + var indexOfSlashes = originalUrl.IndexOf("://"); + var indexOfQuestionMarks = originalUrl.IndexOf("?"); + + if (indexOfSlashes > -1 && + (indexOfQuestionMarks < 0 || + (indexOfQuestionMarks > -1 && indexOfQuestionMarks > indexOfSlashes) + ) + ) + return true; + + return false; + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IClientDependencyFile.cs b/DNN Platform/Components/ClientDependency/Source/IClientDependencyFile.cs new file mode 100644 index 00000000000..c2b93372985 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IClientDependencyFile.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClientDependency.Core +{ + public interface IClientDependencyFile + { + string FilePath { get; set; } + ClientDependencyType DependencyType { get; } + int Priority { get; set; } + int Group { get; set; } + string PathNameAlias { get; set; } + string ForceProvider { get; set; } + bool ForceBundle { get; set; } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IClientDependencyFileExtensions.cs b/DNN Platform/Components/ClientDependency/Source/IClientDependencyFileExtensions.cs new file mode 100644 index 00000000000..ed137752b9e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IClientDependencyFileExtensions.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +namespace ClientDependency.Core +{ + public static class ClientDependencyFileExtensions + { + /// + /// Resolves an absolute web path for the file path + /// + /// + /// + /// + public static string ResolveFilePath(this IClientDependencyFile file, HttpContextBase http) + { + var trimmedPath = file.FilePath.Trim(); + if (string.IsNullOrEmpty(trimmedPath)) + { + throw new ArgumentException("The Path specified is null", "Path"); + } + if (trimmedPath.StartsWith("~/")) + { + return http.ResolveUrl(file.FilePath); + } + if (trimmedPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) + || trimmedPath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) + { + return file.FilePath; + } + if (!http.IsAbsolute(file.FilePath)) + { + //get the relative path + var path = http.Request.AppRelativeCurrentExecutionFilePath.Substring(0, http.Request.AppRelativeCurrentExecutionFilePath.LastIndexOf('/') + 1); + return http.ResolveUrl(path + file.FilePath); + } + return file.FilePath; + } + + + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IClientDependencyPath.cs b/DNN Platform/Components/ClientDependency/Source/IClientDependencyPath.cs new file mode 100644 index 00000000000..15b2fccb60d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IClientDependencyPath.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core +{ + public interface IClientDependencyPath + { + + string Name { get; set; } + string Path { get; set; } + bool ForceBundle { get; set; } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IClientDependencyPathExtensions.cs b/DNN Platform/Components/ClientDependency/Source/IClientDependencyPathExtensions.cs new file mode 100644 index 00000000000..7682b91f3ab --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IClientDependencyPathExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +namespace ClientDependency.Core +{ + public static class ClientDependencyPathExtensions + { + + public static string ResolvePath(this IClientDependencyPath path, HttpContextBase http) + { + if (string.IsNullOrEmpty(path.Path)) + { + throw new ArgumentException("The Path specified is null", "Path"); + } + if (path.Path.StartsWith("~/")) + { + return http.ResolveUrl(path.Path); + } + return path.Path; + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IHaveHtmlAttributes.cs b/DNN Platform/Components/ClientDependency/Source/IHaveHtmlAttributes.cs new file mode 100644 index 00000000000..a3fcb3bd76f --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IHaveHtmlAttributes.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace ClientDependency.Core +{ + /// + /// interface defining that an object has Html attributes + /// + public interface IHaveHtmlAttributes + { + + /// + /// Used to store additional attributes in the HTML markup for the item + /// + /// + /// Mostly used for CSS Media, but could be for anything + /// + IDictionary HtmlAttributes { get; } + + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/IHttpProvider.cs b/DNN Platform/Components/ClientDependency/Source/IHttpProvider.cs new file mode 100644 index 00000000000..d45d466970d --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IHttpProvider.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +namespace ClientDependency.Core +{ + /// + /// A provider that requires initialization under an Http context. + /// The Http initialization will happen after the standard provider initialization. + /// + public interface IHttpProvider + { + + void Initialize(HttpContextBase http); + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/IRequiresHtmlAttributesParsing.cs b/DNN Platform/Components/ClientDependency/Source/IRequiresHtmlAttributesParsing.cs new file mode 100644 index 00000000000..9184f681c8e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/IRequiresHtmlAttributesParsing.cs @@ -0,0 +1,16 @@ +namespace ClientDependency.Core +{ + /// + /// interface defining that an IClientDependencyFile has html attributes applied as a string which require parsing + /// + public interface IRequiresHtmlAttributesParsing : IHaveHtmlAttributes + { + /// + /// Used to set the HtmlAttributes on this class via a string which is parsed + /// + /// + /// The syntax for the string must be: key1:value1,key2:value2 etc... + /// + string HtmlAttributesAsString { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/Logging/ILogger.cs b/DNN Platform/Components/ClientDependency/Source/Logging/ILogger.cs new file mode 100644 index 00000000000..05b1189df68 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Logging/ILogger.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Configuration.Provider; + +namespace ClientDependency.Core.Logging +{ + public interface ILogger + { + void Debug(string msg); + void Info(string msg); + void Warn(string msg); + void Error(string msg, Exception ex); + void Fatal(string msg, Exception ex); + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Logging/NullLogger.cs b/DNN Platform/Components/ClientDependency/Source/Logging/NullLogger.cs new file mode 100644 index 00000000000..ffccca56b1b --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Logging/NullLogger.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ClientDependency.Core.Logging +{ + internal class NullLogger : ILogger + { + #region ILogger Members + + public void Debug(string msg) + { + } + + public void Info(string msg) + { + } + + public void Warn(string msg) + { + } + + public void Error(string msg, Exception ex) + { + } + + public void Fatal(string msg, Exception ex) + { + } + + #endregion + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Module/ClientDependencyModule.cs b/DNN Platform/Components/ClientDependency/Source/Module/ClientDependencyModule.cs new file mode 100644 index 00000000000..0b07370c917 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Module/ClientDependencyModule.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Web; +using System.Web.Compilation; +using ClientDependency.Core.Config; + +namespace ClientDependency.Core.Module +{ + + /// + /// This module currently replaces rogue scripts with composite scripts. + /// Eventually it will handle css files and MVC implementation + /// + public class ClientDependencyModule : IHttpModule + { + #region IHttpModule Members + + void IHttpModule.Dispose() { } + + /// + /// Binds the events + /// + /// + void IHttpModule.Init(HttpApplication app) + { + //This event is late enough that the ContentType of the request is set + //but not too late that we've lost the ability to change the response + //app.BeginRequest += new EventHandler(HandleRequest); + app.PostRequestHandlerExecute += HandleRequest; + LoadFilterTypes(); + } + + /// + /// Checks if any assigned filters validate the current handler, if so then assigns any filter + /// that CanExecute to the response filter chain. + /// + /// Checks if the request MIME type matches the list of mime types specified in the config, + /// if it does, then it compresses it. + /// + /// + /// + void HandleRequest(object sender, EventArgs e) + { + var app = (HttpApplication)sender; + var http = new HttpContextWrapper(app.Context); + + var filters = LoadFilters(http); + + if (ValidateCurrentHandler(filters)) + { + ExecuteFilter(http, filters); + } + + //if debug is on, then don't compress + if (!http.IsDebuggingEnabled) + { + var c = new MimeTypeCompressor(new HttpContextWrapper(app.Context)); + c.AddCompression(); + } + } + + #endregion + + private List m_FilterTypes = new List(); + + #region Private Methods + + private void LoadFilterTypes() + { + foreach (var f in ClientDependencySettings.Instance.ConfigSection.Filters.Cast()) + { + var t = BuildManager.GetType(f.Type, false, true); + if (t != null) + { + m_FilterTypes.Add(t); + } + } + } + + /// + /// loads instances of all registered filters. + /// + /// + private IEnumerable LoadFilters(HttpContextBase http) + { + var loadedFilters = new List(); + + foreach (var t in m_FilterTypes) + { + var filter = (IFilter)Activator.CreateInstance(t); + filter.SetHttpContext(http); + loadedFilters.Add(filter); + + } + + return loadedFilters; + } + + /// + /// Ensure the current running handler is valid in order to proceed with the module filter. + /// + /// + /// + private static bool ValidateCurrentHandler(IEnumerable filters) + { + return filters.Any(f => f.ValidateCurrentHandler()); + } + + private void ExecuteFilter(HttpContextBase http, IEnumerable filters) + { + var filter = new ResponseFilterStream(http.Response.Filter, http); + foreach (var f in filters.Where(f => f.CanExecute())) + { + filter.TransformString += f.UpdateOutputHtml; + } + http.Response.Filter = filter; + } + + #endregion + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Module/IFilter.cs b/DNN Platform/Components/ClientDependency/Source/Module/IFilter.cs new file mode 100644 index 00000000000..931cccacdd9 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Module/IFilter.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +namespace ClientDependency.Core.Module +{ + public interface IFilter + { + void SetHttpContext(HttpContextBase ctx); + string UpdateOutputHtml(string html); + HttpContextBase CurrentContext { get; } + bool CanExecute(); + bool ValidateCurrentHandler(); + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Module/MimeTypeCompressor.cs b/DNN Platform/Components/ClientDependency/Source/Module/MimeTypeCompressor.cs new file mode 100644 index 00000000000..251c9c08037 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Module/MimeTypeCompressor.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.Config; +using System.Web; +using System.IO.Compression; +using System.Text.RegularExpressions; + +namespace ClientDependency.Core.Module +{ + public class MimeTypeCompressor + { + public MimeTypeCompressor(HttpContextBase ctx) + { + Context = ctx; + MatchedTypes = ClientDependencySettings.Instance + .ConfigSection + .CompositeFileElement + .MimeTypeCompression + .Cast() + .Where(x => Context.Request.ContentType.ToUpper().Split(';').Contains(x.MimeType.ToUpper())); + } + + protected HttpContextBase Context; + protected IEnumerable MatchedTypes; + + public void AddCompression() + { + HttpRequestBase request = Context.Request; + HttpResponseBase response = Context.Response; + + //if debug is on, then don't compress + if (!Context.IsDebuggingEnabled) + { + //check if this request should be compressed based on the mime type and path + var m = GetSupportedPath(); + if (IsSupportedMimeType() && m != null) + { + var cType = Context.GetClientCompression(); + Context.AddCompressionResponseHeader(cType); + + + + if (cType == CompressionType.deflate) + { + response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); + } + else if (cType == CompressionType.gzip) + { + response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); + } + + + + } + } + } + + protected MimeTypeCompressionElement GetSupportedPath() + { + //we're not supporting the ASP.Net AJAX calls for compression + var uRawUrl = Context.Request.RawUrl.ToUpper(); + if (uRawUrl.Contains("WEBRESOURCE.AXD") || uRawUrl.Contains("SCRIPTRESOURCE.AXD")) + return null; + + foreach (var m in MatchedTypes) + { + //if it is only "*" then convert it to proper regex + var reg = m.FilePath == "*" ? ".*" : m.FilePath; + var matched = Regex.IsMatch(Context.Request.RawUrl, reg, RegexOptions.Compiled | RegexOptions.IgnoreCase); + if (matched) return m; + } + return null; + } + + protected bool IsSupportedMimeType() + { + return MatchedTypes.Count() > 0; + + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Module/ResponseFilterStream.cs b/DNN Platform/Components/ClientDependency/Source/Module/ResponseFilterStream.cs new file mode 100644 index 00000000000..26afe7dc62f --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Module/ResponseFilterStream.cs @@ -0,0 +1,385 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.IO; +using System.Web.UI; +using System.Text.RegularExpressions; +using ClientDependency.Core.Controls; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.Config; +using ClientDependency.Core; +using System.Net; + + +namespace ClientDependency.Core.Module +{ + /// + /// A semi-generic Stream implementation for Response.Filter with + /// an event interface for handling Content transformations via + /// Stream or String. + /// + /// Use with care for large output as this implementation copies + /// the output into a memory stream and so increases memory usage. + /// + /// + public class + ResponseFilterStream : Stream + { + /// + /// The original stream + /// + readonly Stream _stream; + + private readonly HttpContextBase _http; + + /// + /// Current position in the original stream + /// + long _position; + + /// + /// Stream that original content is read into + /// and then passed to TransformStream function + /// + MemoryStream _cacheStream = new MemoryStream(5000); + + /// + /// Internal pointer that that keeps track of the size + /// of the cacheStream + /// + int _cachePointer = 0; + + + /// + /// + /// + /// + /// + public ResponseFilterStream(Stream responseStream, HttpContextBase http) + { + _stream = responseStream; + _http = http; + } + + + /// + /// Determines whether the stream is captured + /// + private bool IsCaptured + { + get + { + + if (CaptureStream != null || CaptureString != null || + TransformStream != null || TransformString != null) + return true; + + return false; + } + } + + /// + /// Determines whether the Write method is outputting data immediately + /// or delaying output until Flush() is fired. + /// + private bool IsOutputDelayed + { + get + { + if (TransformStream != null || TransformString != null) + return true; + + return false; + } + } + + + /// + /// Event that captures Response output and makes it available + /// as a MemoryStream instance. Output is captured but won't + /// affect Response output. + /// + public event Action CaptureStream; + + /// + /// Event that captures Response output and makes it available + /// as a string. Output is captured but won't affect Response output. + /// + public event Action CaptureString; + + + + /// + /// Event that allows you transform the stream as each chunk of + /// the output is written in the Write() operation of the stream. + /// This means that that it's possible/likely that the input + /// buffer will not contain the full response output but only + /// one of potentially many chunks. + /// + /// This event is called as part of the filter stream's Write() + /// operation. + /// + public event Func TransformWrite; + + + /// + /// Event that allows you to transform the response stream as + /// each chunk of bytep[] output is written during the stream's write + /// operation. This means it's possibly/likely that the string + /// passed to the handler only contains a portion of the full + /// output. Typical buffer chunks are around 16k a piece. + /// + /// This event is called as part of the stream's Write operation. + /// + public event Func TransformWriteString; + + /// + /// This event allows capturing and transformation of the entire + /// output stream by caching all write operations and delaying final + /// response output until Flush() is called on the stream. + /// + public event Func TransformStream; + + /// + /// Event that can be hooked up to handle Response.Filter + /// Transformation. Passed a string that you can modify and + /// return back as a return value. The modified content + /// will become the final output. + /// + public event Func TransformString; + + + protected virtual void OnCaptureStream(MemoryStream ms) + { + if (CaptureStream != null) + CaptureStream(ms); + } + + + private void OnCaptureStringInternal(MemoryStream ms) + { + if (CaptureString != null) + { + string content = _http.Response.ContentEncoding.GetString(ms.ToArray()); + OnCaptureString(content); + } + } + + protected virtual void OnCaptureString(string output) + { + if (CaptureString != null) + CaptureString(output); + } + + protected virtual byte[] OnTransformWrite(byte[] buffer) + { + if (TransformWrite != null) + return TransformWrite(buffer); + return buffer; + } + + private byte[] OnTransformWriteStringInternal(byte[] buffer) + { + Encoding encoding = _http.Response.ContentEncoding; + string output = OnTransformWriteString(encoding.GetString(buffer)); + return encoding.GetBytes(output); + } + + private string OnTransformWriteString(string value) + { + if (TransformWriteString != null) + return TransformWriteString(value); + return value; + } + + + protected virtual MemoryStream OnTransformCompleteStream(MemoryStream ms) + { + if (TransformStream != null) + return TransformStream(ms); + + return ms; + } + + + + + /// + /// Allows transforming of strings + /// + /// Note this handler is internal and not meant to be overridden + /// as the TransformString Event has to be hooked up in order + /// for this handler to even fire to avoid the overhead of string + /// conversion on every pass through. + /// + /// + /// + private string OnTransformCompleteString(string responseText) + { + if (TransformString != null) + TransformString(responseText); + + return responseText; + } + + /// + /// Wrapper method form OnTransformString that handles + /// stream to string and vice versa conversions + /// + /// + /// + internal MemoryStream OnTransformCompleteStringInternal(MemoryStream ms) + { + if (TransformString == null) + return ms; + + //string content = ms.GetAsString(); + string content = _http.Response.ContentEncoding.GetString(ms.ToArray()); + + content = TransformString(content); + byte[] buffer = _http.Response.ContentEncoding.GetBytes(content); + ms = new MemoryStream(); + ms.Write(buffer, 0, buffer.Length); + //ms.WriteString(content); + + return ms; + } + + /// + /// + /// + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return true; } + } + /// + /// + /// + public override bool CanWrite + { + get { return true; } + } + + /// + /// + /// + public override long Length + { + get { return 0; } + } + + /// + /// + /// + public override long Position + { + get { return _position; } + set { _position = value; } + } + + /// + /// + /// + /// + /// + /// + public override long Seek(long offset, System.IO.SeekOrigin direction) + { + return _stream.Seek(offset, direction); + } + + /// + /// + /// + /// + public override void SetLength(long length) + { + _stream.SetLength(length); + } + + /// + /// + /// + public override void Close() + { + _stream.Close(); + } + + /// + /// Override flush by writing out the cached stream data + /// + public override void Flush() + { + + if (IsCaptured && _cacheStream.Length > 0) + { + // Check for transform implementations + _cacheStream = OnTransformCompleteStream(_cacheStream); + _cacheStream = OnTransformCompleteStringInternal(_cacheStream); + + OnCaptureStream(_cacheStream); + OnCaptureStringInternal(_cacheStream); + + // write the stream back out if output was delayed + if (IsOutputDelayed) + _stream.Write(_cacheStream.ToArray(), 0, (int)_cacheStream.Length); + + // Clear the cache once we've written it out + _cacheStream.SetLength(0); + } + + // default flush behavior + _stream.Flush(); + } + + /// + /// + /// + /// + /// + /// + /// + public override int Read(byte[] buffer, int offset, int count) + { + return _stream.Read(buffer, offset, count); + } + + + /// + /// Overriden to capture output written by ASP.NET and captured + /// into a cached stream that is written out later when Flush() + /// is called. + /// + /// + /// + /// + public override void Write(byte[] buffer, int offset, int count) + { + if (IsCaptured) + { + // copy to holding buffer only - we'll write out later + _cacheStream.Write(buffer, 0, count); + _cachePointer += count; + } + + // just transform this buffer + if (TransformWrite != null) + buffer = OnTransformWrite(buffer); + if (TransformWriteString != null) + buffer = OnTransformWriteStringInternal(buffer); + + if (!IsOutputDelayed) + _stream.Write(buffer, offset, count); + + } + + } + +} diff --git a/DNN Platform/Components/ClientDependency/Source/Module/RogueFileFilter.cs b/DNN Platform/Components/ClientDependency/Source/Module/RogueFileFilter.cs new file mode 100644 index 00000000000..cf28d566e44 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Module/RogueFileFilter.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.IO; +using System.Web.UI; +using System.Text.RegularExpressions; +using ClientDependency.Core.CompositeFiles.Providers; +using ClientDependency.Core.Controls; +using ClientDependency.Core.FileRegistration.Providers; +using ClientDependency.Core.Config; +using ClientDependency.Core; +using System.Net; + +namespace ClientDependency.Core.Module +{ + + /// + /// Used as an http response filter to modify the contents of the output html. + /// This filter is used to intercept js and css rogue registrations on the html page. + /// + public class RogueFileFilter : IFilter + { + + #region Private members + + private bool? m_Runnable = null; + private string m_MatchScript = "(?<=src=\")[^\"]*(?=\"))[^>]*)|[^>]*)>(?(?:(?:\n|.)(?!(?:\n|.)"; + private string m_MatchLink = "]*(href\\s*=\\s*(['\"])(?.*?)\\2)"; + + private RogueFileCompressionElement m_FoundPath = null; + + #endregion + + #region IFilter Members + + public void SetHttpContext(HttpContextBase ctx) + { + CurrentContext = ctx; + m_FoundPath = GetSupportedPath(); + } + + /// + /// This filter can only execute when it's a Page or MvcHandler + /// + /// + public virtual bool ValidateCurrentHandler() + { + //don't filter if we're in debug mode + if (CurrentContext.IsDebuggingEnabled || !ClientDependencySettings.Instance.DefaultFileRegistrationProvider.EnableCompositeFiles) + return false; + + return (CurrentContext.CurrentHandler is Page); + } + + /// + /// Returns true when this filter should be applied + /// + /// + public bool CanExecute() + { + if (!ValidateCurrentHandler()) + { + return false; + } + + if (!m_Runnable.HasValue) + { + m_Runnable = (m_FoundPath != null); + } + return m_Runnable.Value; + + } + + /// + /// Replaces any rogue script tag's with calls to the compression handler instead + /// of just the script. + /// + public string UpdateOutputHtml(string html) + { + html = ReplaceScripts(html); + html = ReplaceStyles(html); + return html; + } + + public HttpContextBase CurrentContext { get; private set; } + + #endregion + + #region Private methods + + private RogueFileCompressionElement GetSupportedPath() + { + var rogueFiles = ClientDependencySettings.Instance + .ConfigSection + .CompositeFileElement + .RogueFileCompression; + + return (from m in rogueFiles.Cast() + let reg = m.FilePath == "*" ? ".*" : m.FilePath + let matched = Regex.IsMatch(CurrentContext.Request.RawUrl, reg, RegexOptions.Compiled | RegexOptions.IgnoreCase) + where matched + let isGood = m.ExcludePaths.Cast().Select(e => Regex.IsMatch(CurrentContext.Request.RawUrl, e.FilePath, RegexOptions.Compiled | RegexOptions.IgnoreCase)).All(excluded => !excluded) + where isGood + select m).FirstOrDefault(); + } + + /// + /// Replaces all src attribute values for a script tag with their corresponding + /// URLs as a composite script. + /// + /// + /// + private string ReplaceScripts(string html) + { + //check if we should be processing! + if (CanExecute() && m_FoundPath.CompressJs) + { + return ReplaceContent(html, "src", m_FoundPath.JsRequestExtension.Split(','), ClientDependencyType.Javascript, m_MatchScript, CurrentContext); + } + return html; + } + + /// + /// Replaces all href attribute values for a link tag with their corresponding + /// URLs as a composite style. + /// + /// + /// + private string ReplaceStyles(string html) + { + //check if we should be processing! + if (CanExecute() && m_FoundPath.CompressCss) + { + return ReplaceContent(html, "href", m_FoundPath.CssRequestExtension.Split(','), ClientDependencyType.Css, m_MatchLink, CurrentContext); + } + return html; + } + + /// + /// Replaces the content with the new js/css paths + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// For some reason ampersands that aren't html escaped are not compliant to HTML standards when they exist in 'link' or 'script' tags in URLs, + /// we need to replace the ampersands with & . This is only required for this one w3c compliancy, the URL itself is a valid URL. + /// + private static string ReplaceContent(string html, string namedGroup, string[] extensions, + ClientDependencyType type, string regex, HttpContextBase http) + { + html = Regex.Replace(html, regex, + (m) => + { + var grp = m.Groups[namedGroup]; + + //if there is no namedGroup group name or it doesn't end with a js/css extension or it's already using the composite handler, + //the return the existing string. + if (grp == null + || string.IsNullOrEmpty(grp.ToString()) + || !grp.ToString().EndsWithOneOf(extensions) + || grp.ToString().StartsWith(ClientDependencySettings.Instance.CompositeFileHandlerPath)) + return m.ToString(); + + + //make sure that it's an internal request, though we can deal with external + //requests, we'll leave that up to the developer to register an external request + //explicitly if they want to include in the composite scripts. + try + { + var url = new Uri(grp.ToString(), UriKind.RelativeOrAbsolute); + if (!url.IsLocalUri(http)) + return m.ToString(); //not a local uri + else + { + + var dependency = new BasicFile(type) { FilePath = grp.ToString() }; + + var file = new[] { new BasicFile(type) { FilePath = dependency.ResolveFilePath(http) } }; + + var resolved = ClientDependencySettings.Instance.DefaultCompositeFileProcessingProvider.ProcessCompositeList( + file, + type, + http).Single(); + + return m.ToString().Replace(grp.ToString(), resolved.Replace("&", "&")); + } + } + catch (UriFormatException) + { + //malformed url, let's exit + return m.ToString(); + } + + }, + RegexOptions.Compiled); + + return html; + } + + + #endregion + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/ObjectExtensions.cs b/DNN Platform/Components/ClientDependency/Source/ObjectExtensions.cs new file mode 100644 index 00000000000..7c359addf9e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ObjectExtensions.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace ClientDependency.Core +{ + public static class ObjectExtensions + { + public static IDictionary ToDictionary(this object o) + { + if (o != null) + { + var props = TypeDescriptor.GetProperties(o); + var d = new Dictionary(); + foreach (var prop in props.Cast()) + { + var val = prop.GetValue(o); + if (val != null) + { + d.Add(prop.Name, val); + } + } + return d; + } + return new Dictionary(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/Properties/AssemblyInfo.cs b/DNN Platform/Components/ClientDependency/Source/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..9026f91c94e --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Properties/AssemblyInfo.cs @@ -0,0 +1,24 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClientDependency.Core")] +[assembly: AssemblyDescription("Script file and Css file management for web sites")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("ClientDependency.Core")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("acb95044-dd5c-4d0a-8523-a6352470c424")] + +//ADD RESOURCES +[assembly: System.Web.UI.WebResource("ClientDependency.Core.Resources.LazyLoader.js", "text/javascript")] + +[assembly: InternalsVisibleTo("ClientDependency.UnitTests")] \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/ProviderDependencyList.cs b/DNN Platform/Components/ClientDependency/Source/ProviderDependencyList.cs new file mode 100644 index 00000000000..146bb230b4a --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/ProviderDependencyList.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ClientDependency.Core.FileRegistration.Providers; + + +namespace ClientDependency.Core +{ + internal class ProviderDependencyList + { + internal ProviderDependencyList(BaseFileRegistrationProvider provider) + { + Provider = provider; + Dependencies = new List(); + } + + internal bool ProviderIs(BaseFileRegistrationProvider provider) + { + return Provider.Name == provider.Name; + } + + internal void AddDependencies(IEnumerable list) + { + Dependencies.AddRange(list); + } + + internal void AddDependency(IClientDependencyFile file) + { + Dependencies.Add(file); + } + + internal List Dependencies { get; private set; } + internal BaseFileRegistrationProvider Provider { get; private set; } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/Resources/LazyLoader.js b/DNN Platform/Components/ClientDependency/Source/Resources/LazyLoader.js new file mode 100644 index 00000000000..5f608bbd4d9 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/Resources/LazyLoader.js @@ -0,0 +1,141 @@ +/*Special Thanks to Ruben Verborgh for his work on this and in the Umbraco core!*/ + +if (typeof ClientDependency == 'undefined') var ClientDependency = {}; +if (!ClientDependency.Sys) ClientDependency.Sys = {}; + + +ClientDependency.Sys.LazyLoader = function() { + this.addedDependencies = []; + this.jsQueue = new Array(); + this.jsQueueWaiting = false; +} + +// ********************* Dependency Loader Methods ********************* +ClientDependency.Sys.LazyLoader.prototype.AddJs = function(filePath, callbackMethod) { + if (this.addedDependencies[filePath] == undefined) { + //Sys.Debug.trace("LazyLoader: Queueing '" + filePath + "'."); + + // add script to queue + var script = new Array(); + script.filePath = filePath; + script.callbackMethod = callbackMethod; + script.loaded = false; + this.jsQueue[this.jsQueue.length] = script; + this.addedDependencies[filePath] = true; + + //Sys.Debug.trace("LazyLoader: Queued '" + filePath + "', queue length " + this.jsQueue.length + "."); + + if (!this.jsQueueWaiting) + this.LoadNextJs(); + } + else { + //Sys.Debug.trace("LazyLoader: Javascript file has already been added '" + filePath + "'."); + } + + return this; +} + +ClientDependency.Sys.LazyLoader.prototype.RegisterCallbackMethod = function(callbackMethod) { + /// + /// This registers a method to be called. The system will check if the method is available in the DOM + /// to be called, if it is not, it will wait until it is. + /// + + if (callbackMethod == "") { + return this; + } + var script = { loaded: false, callbackMethod: callbackMethod }; + ClientDependency.Sys.onScriptAvailable(script); + + return this; +} + +function logthis(txt) { + +} + +ClientDependency.Sys.LazyLoader.prototype.AddCss = function(filePath) { + if (this.addedDependencies[filePath] == undefined) { + + var tempCss = document.createElement("link") + tempCss.setAttribute("href", filePath); + tempCss.setAttribute("rel", "stylesheet"); + tempCss.setAttribute("type", "text/css"); + document.getElementsByTagName("head")[0].appendChild(tempCss); + + this.addedDependencies[filePath] = "loaded"; + + } + else { + //Sys.Debug.trace("LazyLoader: Css file has already been added: '" + filePath + "'."); + } + return this; +} + +ClientDependency.Sys.LazyLoader.prototype.LoadNextJs = function() { + if (this.jsQueue.length > 0) { + this.jsQueueWaiting = true; + + var script = this.jsQueue[0]; + this.jsQueue.splice(0, 1); + + //Sys.Debug.trace("LazyLoader: Loading '" + script.filePath + "'. (" + this.jsQueue.length + " scripts left)"); + var tempJs = document.createElement('script'); + tempJs.setAttribute("src", script.filePath); + tempJs.setAttribute("type", "text/javascript"); + + tempJs.onload = function() { ClientDependency.Sys.onScriptAvailable(script); }; + tempJs.onreadystatechange = function() { + if (this.readyState == 'loaded' || this.readyState == 'complete') { + ClientDependency.Sys.onScriptAvailable(script); + } + }; + document.getElementsByTagName("head")[0].appendChild(tempJs); + } + else { + //Sys.Debug.trace('LazyLoader: No scripts left.'); + this.jsQueueWaiting = false; + } +} + +// Initialize +var CDLazyLoader = new ClientDependency.Sys.LazyLoader(); + +ClientDependency.Sys.onScriptAvailable = function(script) { + /// + /// This method checks if the string representation of a method (sMethod) is registered as a function yet, + /// and if it is it'll call the function (oCallback), if not it'll try again after 50 ms. + /// + if (!script.loaded) { + //Sys.Debug.trace("LazyLoader: Loaded '" + script.filePath + "'."); + script.loaded = true; + } + if (script.callbackMethod == '') { + CDLazyLoader.LoadNextJs(); + } + else { + + try { + eval(script.callbackMethod); + } + catch (err) { + //the object definitely doesn't exist. + setTimeout(function() { + ClientDependency.Sys.onScriptAvailable(script); + }, 50); + return; + } + + if (typeof (eval(script.callbackMethod)) == 'function') { + CDLazyLoader.LoadNextJs(); + //Sys.Debug.trace("LazyLoader: Executing '" + script.filePath + "' callback '" + script.callbackMethod + "'."); + var func = eval(script.callbackMethod); + func.call(this); + } + else { + setTimeout(function() { + ClientDependency.Sys.onScriptAvailable(script); + }, 50); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Components/ClientDependency/Source/SimpleCompressor.cs b/DNN Platform/Components/ClientDependency/Source/SimpleCompressor.cs new file mode 100644 index 00000000000..bfd9b440f54 --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/SimpleCompressor.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.IO.Compression; + +namespace ClientDependency.Core +{ + public class SimpleCompressor + { + public static byte[] CompressBytes(CompressionType type, byte[] fileBytes) + { + MemoryStream ms = new MemoryStream(); + Stream compressedStream = null; + + if (type == CompressionType.deflate) + { + compressedStream = new DeflateStream(ms, CompressionMode.Compress, true); + } + else if (type == CompressionType.gzip) + { + compressedStream = new GZipStream(ms, CompressionMode.Compress, true); + } + + if (type != CompressionType.none) + { + //write the bytes to the compressed stream + compressedStream.Write(fileBytes, 0, fileBytes.Length); + compressedStream.Close(); + byte[] output = ms.ToArray(); + ms.Close(); + return output; + } + + //not compressed + return fileBytes; + } + + public static byte[] DecompressBytes(CompressionType type, byte[] compressedBytes) + { + MemoryStream ms = new MemoryStream(); + Stream decompressedStream = null; + + if (type == CompressionType.deflate) + { + decompressedStream = new DeflateStream(ms, CompressionMode.Decompress, true); + } + else if (type == CompressionType.gzip) + { + decompressedStream = new GZipStream(ms, CompressionMode.Decompress, true); + } + + if (type != CompressionType.none) + { + //write the bytes to the compressed stream + decompressedStream.Write(compressedBytes, 0, compressedBytes.Length); + decompressedStream.Close(); + byte[] output = ms.ToArray(); + ms.Close(); + return output; + } + + //not compressed + return compressedBytes; + } + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/StringExtensions.cs b/DNN Platform/Components/ClientDependency/Source/StringExtensions.cs new file mode 100644 index 00000000000..e01df0b4add --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/StringExtensions.cs @@ -0,0 +1,83 @@ +using System; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace ClientDependency.Core +{ + public static class StringExtensions + { + + public static string EncodeTo64Url(this string toEncode) + { + string returnValue = EncodeTo64(toEncode); + + // returnValue is base64 = may contain a-z, A-Z, 0-9, +, /, and =. + // the = at the end is just a filler, can remove + // then convert the + and / to "base64url" equivalent + // + returnValue = returnValue.TrimEnd(new char[] { '=' }); + returnValue = returnValue.Replace("+", "-"); + returnValue = returnValue.Replace("/", "_"); + + return returnValue; + } + + public static string EncodeTo64(this string toEncode) + { + byte[] toEncodeAsBytes = Encoding.Default.GetBytes(toEncode); + string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); + return returnValue; + } + public static string DecodeFrom64Url(this string toDecode) + { + // see BaseFileRegistrationProvider.EncodeTo64Url + // + toDecode = toDecode.Replace("-", "+"); + toDecode = toDecode.Replace("_", "/"); + int rem = toDecode.Length % 4; // 0 (aligned), 1, 2 or 3 (not aligned) + if (rem > 0) + toDecode = toDecode.PadRight(toDecode.Length + 4 - rem, '='); // align + + return DecodeFrom64(toDecode); + } + + public static string DecodeFrom64(this string toDecode) + { + byte[] toDecodeAsBytes = System.Convert.FromBase64String(toDecode); + return Encoding.Default.GetString(toDecodeAsBytes); + } + + /// Generate a MD5 hash of a string + /// + public static string GenerateMd5(this string str) + { + var md5 = new MD5CryptoServiceProvider(); + var byteArray = Encoding.ASCII.GetBytes(str); + byteArray = md5.ComputeHash(byteArray); + return byteArray.Aggregate("", (current, b) => current + b.ToString("x2")); + } + + /// + /// checks if the string ends with one of the strings specified. This ignores case. + /// + /// + /// + /// + public static bool EndsWithOneOf(this string str, string[] ext) + { + var upper = str.ToUpper(); + bool isExt = false; + foreach (var e in ext) + { + if (upper.EndsWith(e.ToUpper())) + { + isExt = true; + break; + } + } + return isExt; + } + + } +} diff --git a/DNN Platform/Components/ClientDependency/Source/UriExtensions.cs b/DNN Platform/Components/ClientDependency/Source/UriExtensions.cs new file mode 100644 index 00000000000..34a8361051f --- /dev/null +++ b/DNN Platform/Components/ClientDependency/Source/UriExtensions.cs @@ -0,0 +1,80 @@ +using System; +using System.Linq; +using System.Text; +using System.Web; +using System.Net; + +namespace ClientDependency.Core +{ + public static class UriExtensions + { + /// + /// Checks if the url is a local/relative uri, if it is, it makes it absolute based on the + /// current request uri. + /// + /// + /// + /// + public static Uri MakeAbsoluteUri(this Uri uri, HttpContextBase http) + { + if (!uri.IsAbsoluteUri) + { + if (http.Request.Url != null) + { + var left = http.Request.Url.GetLeftPart(UriPartial.Authority); + var absoluteUrl = new Uri(new Uri(left), uri); + return absoluteUrl; + } + } + return uri; + } + + /// + /// Determines if the uri is a locally based file + /// + /// + /// + /// + public static bool IsLocalUri(this Uri uri, HttpContextBase http) + { + var isLocal = false; + + try + { + if (!uri.IsAbsoluteUri) + { + uri = uri.MakeAbsoluteUri(http); + } + + var host = Dns.GetHostAddresses(uri.Host); + var local = Dns.GetHostAddresses(Dns.GetHostName()); + foreach (var hostAddress in host) + { + if (IPAddress.IsLoopback(hostAddress)) + { + isLocal = true; + break; + } + if (local.Contains(hostAddress)) + { + isLocal = true; + } + + if (isLocal) + { + break; + } + } + } + catch (Exception) + { + + //suppress error - triggered if user has no internet connection or environment permission + //we assume local files as we cannot support non local files without an internet connection + return true; + } + + return isLocal; + } + } +} diff --git a/DNN Platform/Components/MVC4/System.Web.WebPages.Deployment.dll b/DNN Platform/Components/MVC4/System.Web.WebPages.Deployment.dll new file mode 100644 index 00000000000..89e7d27450b Binary files /dev/null and b/DNN Platform/Components/MVC4/System.Web.WebPages.Deployment.dll differ diff --git a/DNN Platform/Components/MVC4/System.Web.WebPages.dll b/DNN Platform/Components/MVC4/System.Web.WebPages.dll new file mode 100644 index 00000000000..60e9abab508 Binary files /dev/null and b/DNN Platform/Components/MVC4/System.Web.WebPages.dll differ diff --git a/DNN Platform/Components/SharpZipLib/Readme.rtf b/DNN Platform/Components/SharpZipLib/Readme.rtf new file mode 100644 index 00000000000..30552306f21 Binary files /dev/null and b/DNN Platform/Components/SharpZipLib/Readme.rtf differ diff --git a/DNN Platform/Components/SharpZipLib/Readme.txt b/DNN Platform/Components/SharpZipLib/Readme.txt new file mode 100644 index 00000000000..1c685e410ae --- /dev/null +++ b/DNN Platform/Components/SharpZipLib/Readme.txt @@ -0,0 +1,10 @@ +Please note: + +In order for this component to be used in a Medium Trust environment, the DLL has been recompiled without the strong naming attribute from AssemblyInfo.cs: + +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("../ICSharpCode.SharpZipLib.key")] + +In addition, the dependency on NUnit.Framework.dll was also removed. + +This was done with written notification and permission from Christoph Wille of AlphaSierraPapa ( christophw@alphasierrapapa.com ) on September 23, 2004 \ No newline at end of file diff --git a/DNN Platform/Components/Telerik/DotNetNuke.Telerik.Web.dnn b/DNN Platform/Components/Telerik/DotNetNuke.Telerik.Web.dnn new file mode 100644 index 00000000000..f6d35588f90 --- /dev/null +++ b/DNN Platform/Components/Telerik/DotNetNuke.Telerik.Web.dnn @@ -0,0 +1,80 @@ + + + + DotNetNuke Telerik Web Components + Provides Telerik Components for DotNetNuke. + + + DNNCorp + DotNetNuke Corporation + www.dotnetnuke.com + support@dotnetnuke.com + + Please refer to the Telerik EULA.pdf in your site's documentation folder. + + This package includes Telerik.Web.UI assembly version 2013.2.717.40. + Please go to www.telerik.com to view release notes on this particular version. + + + + + bin + Telerik.Web.UI.dll + 2013.2.717.40 + + + bin + Telerik.Web.UI.Skins.dll + 2013.2.717.40 + + + + + + + Documentation + Telerik_EULA.pdf + + + + + + web.config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DNN Platform/Components/WebAPI/Microsoft.Web.Infrastructure.dll b/DNN Platform/Components/WebAPI/Microsoft.Web.Infrastructure.dll new file mode 100644 index 00000000000..85f1138c57b Binary files /dev/null and b/DNN Platform/Components/WebAPI/Microsoft.Web.Infrastructure.dll differ diff --git a/DNN Platform/Components/WebAPI/Newtonsoft.Json.dll b/DNN Platform/Components/WebAPI/Newtonsoft.Json.dll new file mode 100644 index 00000000000..7fe9514d7c0 Binary files /dev/null and b/DNN Platform/Components/WebAPI/Newtonsoft.Json.dll differ diff --git a/DNN Platform/Components/WebAPI/System.Net.Http.Formatting.dll b/DNN Platform/Components/WebAPI/System.Net.Http.Formatting.dll new file mode 100644 index 00000000000..367d253b9d4 Binary files /dev/null and b/DNN Platform/Components/WebAPI/System.Net.Http.Formatting.dll differ diff --git a/DNN Platform/Components/WebAPI/System.Net.Http.WebRequest.dll b/DNN Platform/Components/WebAPI/System.Net.Http.WebRequest.dll new file mode 100644 index 00000000000..b26b59a5412 Binary files /dev/null and b/DNN Platform/Components/WebAPI/System.Net.Http.WebRequest.dll differ diff --git a/DNN Platform/Components/WebAPI/System.Net.Http.dll b/DNN Platform/Components/WebAPI/System.Net.Http.dll new file mode 100644 index 00000000000..2ee8ff7a577 Binary files /dev/null and b/DNN Platform/Components/WebAPI/System.Net.Http.dll differ diff --git a/DNN Platform/Components/WebAPI/System.Web.Http.WebHost.dll b/DNN Platform/Components/WebAPI/System.Web.Http.WebHost.dll new file mode 100644 index 00000000000..1dfa8d28fe7 Binary files /dev/null and b/DNN Platform/Components/WebAPI/System.Web.Http.WebHost.dll differ diff --git a/DNN Platform/Components/WebAPI/System.Web.Http.dll b/DNN Platform/Components/WebAPI/System.Web.Http.dll new file mode 100644 index 00000000000..206c331767b Binary files /dev/null and b/DNN Platform/Components/WebAPI/System.Web.Http.dll differ diff --git a/DNN Platform/Components/WebPages/Microsoft.Web.Helpers.dll b/DNN Platform/Components/WebPages/Microsoft.Web.Helpers.dll new file mode 100644 index 00000000000..2d852ee9705 Binary files /dev/null and b/DNN Platform/Components/WebPages/Microsoft.Web.Helpers.dll differ diff --git a/DNN Platform/Components/WebPages/System.Web.Helpers.dll b/DNN Platform/Components/WebPages/System.Web.Helpers.dll new file mode 100644 index 00000000000..a41bdcc651e Binary files /dev/null and b/DNN Platform/Components/WebPages/System.Web.Helpers.dll differ diff --git a/DNN Platform/Components/WebPages/System.Web.Razor.dll b/DNN Platform/Components/WebPages/System.Web.Razor.dll new file mode 100644 index 00000000000..470f0c70685 Binary files /dev/null and b/DNN Platform/Components/WebPages/System.Web.Razor.dll differ diff --git a/DNN Platform/Components/WebPages/System.Web.WebPages.Razor.dll b/DNN Platform/Components/WebPages/System.Web.WebPages.Razor.dll new file mode 100644 index 00000000000..f9e71f8419c Binary files /dev/null and b/DNN Platform/Components/WebPages/System.Web.WebPages.Razor.dll differ diff --git a/DNN Platform/Components/WebPages/WebMatrix.Data.dll b/DNN Platform/Components/WebPages/WebMatrix.Data.dll new file mode 100644 index 00000000000..19287cea24c Binary files /dev/null and b/DNN Platform/Components/WebPages/WebMatrix.Data.dll differ diff --git a/DNN Platform/Components/WebPages/WebMatrix.WebData.dll b/DNN Platform/Components/WebPages/WebMatrix.WebData.dll new file mode 100644 index 00000000000..e058ba8664d Binary files /dev/null and b/DNN Platform/Components/WebPages/WebMatrix.WebData.dll differ diff --git a/DNN Platform/Controls/CountryListBox/CountryListBox.cs b/DNN Platform/Controls/CountryListBox/CountryListBox.cs new file mode 100644 index 00000000000..855ff1c6404 --- /dev/null +++ b/DNN Platform/Controls/CountryListBox/CountryListBox.cs @@ -0,0 +1,208 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +//------------------------------------------------------------------------------------------------ +// CountryListBox ASP.NET Web Control, lists countries and +// automatically detects country of visitors. +// +// This web control will load a listbox with all countries and +// upon loading will attempt to automatically recognize the +// country that the visitor is visiting the website from. +//------------------------------------------------------------------------------------------------ + +#region Usings + +using System; +using System.ComponentModel; +using System.IO; +using System.Web.Caching; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.WebControls +{ + [ToolboxData("<{0}:CountryListBox runat=server>")] + public class CountryListBox : DropDownList + { + private bool _CacheGeoIPData = true; + private string _GeoIPFile; + private string _LocalhostCountryCode; + private string _TestIP; + + [Bindable(true), Category("Caching"), DefaultValue(true)] + public bool CacheGeoIPData + { + get + { + return _CacheGeoIPData; + } + set + { + _CacheGeoIPData = value; + if (value == false) + { + Context.Cache.Remove("GeoIPData"); + } + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string GeoIPFile + { + get + { + return _GeoIPFile; + } + set + { + _GeoIPFile = value; + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string TestIP + { + get + { + return _TestIP; + } + set + { + _TestIP = value; + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string LocalhostCountryCode + { + get + { + return _LocalhostCountryCode; + } + set + { + _LocalhostCountryCode = value; + } + } + + protected override void OnDataBinding(EventArgs e) + { + bool IsLocal = false; + string IP; + if (!Page.IsPostBack) + { + //If GeoIPFile is not provided, assume they put it in BIN. + if (String.IsNullOrEmpty(_GeoIPFile)) + { + _GeoIPFile = "controls/CountryListBox/Data/GeoIP.dat"; + } + EnsureChildControls(); + //Check to see if a TestIP is specified + if (!String.IsNullOrEmpty(_TestIP)) + { + //TestIP is specified, let's use it + IP = _TestIP; + } + else if (Page.Request.UserHostAddress == "127.0.0.1") + { + //The country cannot be detected because the user is local. + IsLocal = true; + //Set the IP address in case they didn't specify LocalhostCountryCode + IP = Page.Request.UserHostAddress; + } + else + { + //Set the IP address so we can find the country + IP = Page.Request.UserHostAddress; + } + + //Check to see if we need to generate the Cache for the GeoIPData file + if (Context.Cache.Get("GeoIPData") == null && _CacheGeoIPData) + { + //Store it as well as setting a dependency on the file + Context.Cache.Insert("GeoIPData", CountryLookup.FileToMemory(Context.Server.MapPath(_GeoIPFile)), new CacheDependency(Context.Server.MapPath(_GeoIPFile))); + } + + //Check to see if the request is a localhost request + //and see if the LocalhostCountryCode is specified + if (IsLocal && !String.IsNullOrEmpty(_LocalhostCountryCode)) + { + //Bing the data + base.OnDataBinding(e); + //Pre-Select the value in the drop-down based + //on the LocalhostCountryCode specified. + if (Items.FindByValue(_LocalhostCountryCode) != null) + { + Items.FindByValue(_LocalhostCountryCode).Selected = true; + } + } + else + { + //Either this is a remote request or it is a local + //request with no LocalhostCountryCode specified + CountryLookup _CountryLookup; + + //Check to see if we are using the Cached + //version of the GeoIPData file + if (_CacheGeoIPData) + { + //Yes, get it from cache + _CountryLookup = new CountryLookup((MemoryStream) Context.Cache.Get("GeoIPData")); + } + else + { + //No, get it from file + _CountryLookup = new CountryLookup(Context.Server.MapPath(_GeoIPFile)); + } + //Get the country code based on the IP address + string _UserCountryCode = _CountryLookup.LookupCountryCode(IP); + + //Bind the datasource + base.OnDataBinding(e); + + //Make sure the value returned is actually + //in the drop-down list. + if (Items.FindByValue(_UserCountryCode) != null) + { + //Yes, it's there, select it based on its value + Items.FindByValue(_UserCountryCode).Selected = true; + } + else + { + //No it's not there. Let's get the Country description + //and add a new list item for the Country detected + string _UserCountry = _CountryLookup.LookupCountryName(IP); + if (_UserCountry != "N/A") + { + var newItem = new ListItem(); + newItem.Value = _UserCountryCode; + newItem.Text = _UserCountry; + Items.Insert(0, newItem); + //Now let's Pre-Select it + Items.FindByValue(_UserCountryCode).Selected = true; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Controls/CountryListBox/CountryListBox.csproj b/DNN Platform/Controls/CountryListBox/CountryListBox.csproj new file mode 100644 index 00000000000..d65545b49f9 --- /dev/null +++ b/DNN Platform/Controls/CountryListBox/CountryListBox.csproj @@ -0,0 +1,112 @@ + + + + 9.0.30729 + 2.0 + {CA056730-5759-41F8-A6C1-420F9C0C63E7} + Debug + AnyCPU + CountryListBox + None + Library + v4.0 + SAK + SAK + SAK + SAK + CountryListBox + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + bin\ + CountryListBox.xml + true + true + 4 + full + AllRules.ruleset + 1591 + default + + + bin\ + CountryListBox.xml + true + true + 4 + pdbonly + AllRules.ruleset + 1591 + + + + + 3.5 + + + + 3.5 + + + System.Web + + + + + + Code + + + Code + + + Code + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Controls/CountryListBox/CountryLookup.cs b/DNN Platform/Controls/CountryListBox/CountryLookup.cs new file mode 100644 index 00000000000..cb0e276cdfc --- /dev/null +++ b/DNN Platform/Controls/CountryListBox/CountryLookup.cs @@ -0,0 +1,286 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +//------------------------------------------------------------------------------------------------ +// This class uses an IP lookup database from MaxMind, specifically +// the GeoIP Free Database. +// +// The database and the c# implementation of this class +// are available from http://www.maxmind.com/app/csharp +//------------------------------------------------------------------------------------------------ +#region Usings + +using System; +using System.IO; +using System.Net; + +#endregion + +namespace DotNetNuke.UI.WebControls +{ + public class CountryLookup + { + private static long CountryBegin = 16776960; + + private static readonly string[] CountryName = new[] + { + "N/A", "Asia/Pacific Region", "Europe", "Andorra", "United Arab Emirates", "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", + "Armenia", "Netherlands Antilles", "Angola", "Antarctica", "Argentina", "American Samoa", "Austria", "Australia", "Aruba", "Azerbaijan", + "Bosnia and Herzegovina", "Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain", "Burundi", "Benin", "Bermuda", + "Brunei Darussalam", "Bolivia", "Brazil", "Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize", "Canada", + "Cocos (Keeling) Islands", "Congo, The Democratic Republic of the", "Central African Republic", "Congo", "Switzerland", "Cote D'Ivoire", + "Cook Islands", "Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Cuba", "Cape Verde", "Christmas Island", "Cyprus", "Czech Republic" + , "Germany", "Djibouti", "Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia", "Egypt", "Western Sahara", "Eritrea", + "Spain", "Ethiopia", "Finland", "Fiji", "Falkland Islands (Malvinas)", "Micronesia, Federated States of", "Faroe Islands", "France", + "France, Metropolitan", "Gabon", "United Kingdom", "Grenada", "Georgia", "French Guiana", "Ghana", "Gibraltar", "Greenland", "Gambia", + "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands", "Guatemala", "Guam", "Guinea-Bissau", + "Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras", "Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", + "India", "British Indian Ocean Territory", "Iraq", "Iran, Islamic Republic of", "Iceland", "Italy", "Jamaica", "Jordan", "Japan", "Kenya", + "Kyrgyzstan", "Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of", "Korea, Republic of", + "Kuwait", "Cayman Islands", "Kazakstan", "Lao People's Democratic Republic", "Lebanon", "Saint Lucia", "Liechtenstein", "Sri Lanka", + "Liberia", "Lesotho", "Lithuania", "Luxembourg", "Latvia", "Libyan Arab Jamahiriya", "Morocco", "Monaco", "Moldova, Republic of", + "Madagascar", "Marshall Islands", "Macedonia, the Former Yugoslav Republic of", "Mali", "Myanmar", "Mongolia", "Macau", + "Northern Mariana Islands", "Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives", "Malawi", "Mexico", "Malaysia", + "Mozambique", "Namibia", "New Caledonia", "Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway", "Nepal", "Nauru", + "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia", "Papua New Guinea", "Philippines", "Pakistan", "Poland", + "Saint Pierre and Miquelon", "Pitcairn", "Puerto Rico", "Palestinian Territory, Occupied", "Portugal", "Palau", "Paraguay", "Qatar", + "Reunion", "Romania", "Russian Federation", "Rwanda", "Saudi Arabia", "Solomon Islands", "Seychelles", "Sudan", "Sweden", "Singapore", + "Saint Helena", "Slovenia", "Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal", "Somalia", "Suriname", + "Sao Tome and Principe", "El Salvador", "Syrian Arab Republic", "Swaziland", "Turks and Caicos Islands", "Chad", + "French Southern Territories", "Togo", "Thailand", "Tajikistan", "Tokelau", "Turkmenistan", "Tunisia", "Tonga", "East Timor", "Turkey", + "Trinidad and Tobago", "Tuvalu", "Taiwan, Province of China", "Tanzania, United Republic of", "Ukraine", "Uganda", + "United States Minor Outlying Islands", "United States", "Uruguay", "Uzbekistan", "Holy See (Vatican City State)", + "Saint Vincent and the Grenadines", "Venezuela", "Virgin Islands, British", "Virgin Islands, U.S.", "Vietnam", "Vanuatu", + "Wallis and Futuna", "Samoa", "Yemen", "Mayotte", "Yugoslavia", "South Africa", "Zambia", "Zaire", "Zimbabwe", "Anonymous Proxy", + "Satellite Provider" + }; + + private static readonly string[] CountryCode = new[] + { + "--", "AP", "EU", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", + "BF", "BG", "BH", "BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", + "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", + "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", + "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", + "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", + "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", + "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", + "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", + "TD", "TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TP", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", + "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW", "A1", "A2" + }; + + public MemoryStream m_MemoryStream; + + public CountryLookup(MemoryStream ms) + { + m_MemoryStream = ms; + } + + public CountryLookup(string FileLocation) + { + //------------------------------------------------------------------------------------------------ + //Load the passed in GeoIP Data file to the memorystream + //------------------------------------------------------------------------------------------------ + var _FileStream = new FileStream(FileLocation, FileMode.Open, FileAccess.Read); + m_MemoryStream = new MemoryStream(); + var _Byte = new byte[256]; + while (_FileStream.Read(_Byte, 0, _Byte.Length) != 0) + { + m_MemoryStream.Write(_Byte, 0, _Byte.Length); + } + _FileStream.Close(); + } + + private long ConvertIPAddressToNumber(IPAddress _IPAddress) + { + //Convert an IP Address, (e.g. 127.0.0.1), to the numeric equivalent + string[] _Address = _IPAddress.ToString().Split('.'); + if (_Address.Length == 4) + { + return Convert.ToInt64(16777216*Convert.ToDouble(_Address[0]) + 65536*Convert.ToDouble(_Address[1]) + 256*Convert.ToDouble(_Address[2]) + Convert.ToDouble(_Address[3])); + } + else + { + return 0; + } + } + + private string ConvertIPNumberToAddress(long _IPNumber) + { + //Convert an IP Number to the IP Address equivalent + string _IPNumberPart1 = Convert.ToString(((int) (_IPNumber/16777216))%256); + string _IPNumberPart2 = Convert.ToString(((int) (_IPNumber/65536))%256); + string _IPNumberPart3 = Convert.ToString(((int) (_IPNumber/256))%256); + string _IPNumberPart4 = Convert.ToString(((int) (_IPNumber))%256); + return _IPNumberPart1 + "." + _IPNumberPart2 + "." + _IPNumberPart3 + "." + _IPNumberPart4; + } + + public static MemoryStream FileToMemory(string FileLocation) + { + //Read a given file into a Memory Stream to return as the result + FileStream _FileStream; + var _MemStream = new MemoryStream(); + var _Byte = new byte[256]; + try + { + _FileStream = new FileStream(FileLocation, FileMode.Open, FileAccess.Read); + while (_FileStream.Read(_Byte, 0, _Byte.Length) != 0) + { + _MemStream.Write(_Byte, 0, _Byte.Length); + } + _FileStream.Close(); + } + catch (FileNotFoundException exc) + { + throw new Exception(exc.Message + + " Please set the \"GeoIPFile\" Property to specify the location of this file. The property value must be set to the virtual path to GeoIP.dat (i.e. \"/controls/CountryListBox/Data/GeoIP.dat\")"); + } + return _MemStream; + } + + public string LookupCountryCode(IPAddress _IPAddress) + { + //Look up the country code, e.g. US, for the passed in IP Address + return CountryCode[Convert.ToInt32(SeekCountry(0, ConvertIPAddressToNumber(_IPAddress), 31))]; + } + + public string LookupCountryCode(string _IPAddress) + { + //Look up the country code, e.g. US, for the passed in IP Address + IPAddress _Address; + try + { + _Address = IPAddress.Parse(_IPAddress); + } + catch (FormatException) + { + return "--"; + } + return LookupCountryCode(_Address); + } + + public string LookupCountryName(IPAddress addr) + { + //Look up the country name, e.g. United States, for the IP Address + return CountryName[Convert.ToInt32(SeekCountry(0, ConvertIPAddressToNumber(addr), 31))]; + } + + public string LookupCountryName(string _IPAddress) + { + //Look up the country name, e.g. United States, for the IP Address + IPAddress _Address; + try + { + _Address = IPAddress.Parse(_IPAddress); + } + catch (FormatException) + { + return "N/A"; + } + return LookupCountryName(_Address); + } + + private long vbShiftLeft(long value, int Count) + { + //------------------------------------------------------------------------------------------------ + // Replacement for Bitwise operators which are missing in VB.NET, + // these functions are present in .NET 1.1, but for developers + // using 1.0, replacement functions must be implemented + //------------------------------------------------------------------------------------------------ + long returnValue = 0; + int _Iterator; + returnValue = value; + for (_Iterator = 1; _Iterator <= Count; _Iterator++) + { + returnValue = returnValue*2; + } + return returnValue; + } + + private long vbShiftRight(long value, int Count) + { + //------------------------------------------------------------------------------------------------ + // Replacement for Bitwise operators which are missing in VB.NET, + // these functions are present in .NET 1.1, but for developers + // using 1.0, replacement functions must be implemented + //------------------------------------------------------------------------------------------------ + long returnValue = 0; + int _Iterator; + returnValue = value; + for (_Iterator = 1; _Iterator <= Count; _Iterator++) + { + returnValue = returnValue/2; + } + return returnValue; + } + + public int SeekCountry(int Offset, long Ipnum, short Depth) + { + try + { + var Buffer = new byte[6]; + var X = new int[2]; + short I; + short J; + byte Y; + if (Depth == 0) + { + throw new Exception(); + } + m_MemoryStream.Seek(6*Offset, 0); + m_MemoryStream.Read(Buffer, 0, 6); + for (I = 0; I <= 1; I++) + { + X[I] = 0; + for (J = 0; J <= 2; J++) + { + Y = Buffer[I*3 + J]; + if (Y < 0) + { + Y = Convert.ToByte(Y + 256); + } + X[I] = Convert.ToInt32(X[I] + vbShiftLeft(Y, J*8)); + } + } + if ((Ipnum & vbShiftLeft(1, Depth)) > 0) + { + if (X[1] >= CountryBegin) + { + return Convert.ToInt32(X[1] - CountryBegin); + } + return SeekCountry(X[1], Ipnum, Convert.ToInt16(Depth - 1)); + } + else + { + if (X[0] >= CountryBegin) + { + return Convert.ToInt32(X[0] - CountryBegin); + } + return SeekCountry(X[0], Ipnum, Convert.ToInt16(Depth - 1)); + } + } + catch (Exception exc) + { + throw new Exception("Error seeking country: " + exc.Message); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Controls/CountryListBox/Properties/AssemblyInfo.cs b/DNN Platform/Controls/CountryListBox/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..835f8af5d27 --- /dev/null +++ b/DNN Platform/Controls/CountryListBox/Properties/AssemblyInfo.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Web.UI; + +#endregion + +[assembly: AssemblyTitle("DotNetNuke")] +[assembly: AssemblyDescription("Open Source Web Application Framework")] +[assembly: AssemblyCompany("DotNetNuke Corporation")] +[assembly: AssemblyProduct("http://www.dotnetnuke.com")] +[assembly: AssemblyCopyright("DotNetNuke is copyright 2002-2013 by DotNetNuke Corporation. All Rights Reserved.")] +[assembly: AssemblyTrademark("DotNetNuke")] +[assembly: CLSCompliant(true)] +[assembly: Guid("3D57E77F-F723-48BB-A58C-3FAB63C562D4")] +[assembly: AssemblyVersion("6.2.1.11")] +[assembly: TagPrefix("DotNetNuke.UI.WebControls.CountryListBox", "DotNetNuke")] diff --git a/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.cs b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.cs new file mode 100644 index 00000000000..855ff1c6404 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.cs @@ -0,0 +1,208 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +//------------------------------------------------------------------------------------------------ +// CountryListBox ASP.NET Web Control, lists countries and +// automatically detects country of visitors. +// +// This web control will load a listbox with all countries and +// upon loading will attempt to automatically recognize the +// country that the visitor is visiting the website from. +//------------------------------------------------------------------------------------------------ + +#region Usings + +using System; +using System.ComponentModel; +using System.IO; +using System.Web.Caching; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.WebControls +{ + [ToolboxData("<{0}:CountryListBox runat=server>")] + public class CountryListBox : DropDownList + { + private bool _CacheGeoIPData = true; + private string _GeoIPFile; + private string _LocalhostCountryCode; + private string _TestIP; + + [Bindable(true), Category("Caching"), DefaultValue(true)] + public bool CacheGeoIPData + { + get + { + return _CacheGeoIPData; + } + set + { + _CacheGeoIPData = value; + if (value == false) + { + Context.Cache.Remove("GeoIPData"); + } + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string GeoIPFile + { + get + { + return _GeoIPFile; + } + set + { + _GeoIPFile = value; + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string TestIP + { + get + { + return _TestIP; + } + set + { + _TestIP = value; + } + } + + [Bindable(true), Category("Appearance"), DefaultValue("")] + public string LocalhostCountryCode + { + get + { + return _LocalhostCountryCode; + } + set + { + _LocalhostCountryCode = value; + } + } + + protected override void OnDataBinding(EventArgs e) + { + bool IsLocal = false; + string IP; + if (!Page.IsPostBack) + { + //If GeoIPFile is not provided, assume they put it in BIN. + if (String.IsNullOrEmpty(_GeoIPFile)) + { + _GeoIPFile = "controls/CountryListBox/Data/GeoIP.dat"; + } + EnsureChildControls(); + //Check to see if a TestIP is specified + if (!String.IsNullOrEmpty(_TestIP)) + { + //TestIP is specified, let's use it + IP = _TestIP; + } + else if (Page.Request.UserHostAddress == "127.0.0.1") + { + //The country cannot be detected because the user is local. + IsLocal = true; + //Set the IP address in case they didn't specify LocalhostCountryCode + IP = Page.Request.UserHostAddress; + } + else + { + //Set the IP address so we can find the country + IP = Page.Request.UserHostAddress; + } + + //Check to see if we need to generate the Cache for the GeoIPData file + if (Context.Cache.Get("GeoIPData") == null && _CacheGeoIPData) + { + //Store it as well as setting a dependency on the file + Context.Cache.Insert("GeoIPData", CountryLookup.FileToMemory(Context.Server.MapPath(_GeoIPFile)), new CacheDependency(Context.Server.MapPath(_GeoIPFile))); + } + + //Check to see if the request is a localhost request + //and see if the LocalhostCountryCode is specified + if (IsLocal && !String.IsNullOrEmpty(_LocalhostCountryCode)) + { + //Bing the data + base.OnDataBinding(e); + //Pre-Select the value in the drop-down based + //on the LocalhostCountryCode specified. + if (Items.FindByValue(_LocalhostCountryCode) != null) + { + Items.FindByValue(_LocalhostCountryCode).Selected = true; + } + } + else + { + //Either this is a remote request or it is a local + //request with no LocalhostCountryCode specified + CountryLookup _CountryLookup; + + //Check to see if we are using the Cached + //version of the GeoIPData file + if (_CacheGeoIPData) + { + //Yes, get it from cache + _CountryLookup = new CountryLookup((MemoryStream) Context.Cache.Get("GeoIPData")); + } + else + { + //No, get it from file + _CountryLookup = new CountryLookup(Context.Server.MapPath(_GeoIPFile)); + } + //Get the country code based on the IP address + string _UserCountryCode = _CountryLookup.LookupCountryCode(IP); + + //Bind the datasource + base.OnDataBinding(e); + + //Make sure the value returned is actually + //in the drop-down list. + if (Items.FindByValue(_UserCountryCode) != null) + { + //Yes, it's there, select it based on its value + Items.FindByValue(_UserCountryCode).Selected = true; + } + else + { + //No it's not there. Let's get the Country description + //and add a new list item for the Country detected + string _UserCountry = _CountryLookup.LookupCountryName(IP); + if (_UserCountry != "N/A") + { + var newItem = new ListItem(); + newItem.Value = _UserCountryCode; + newItem.Text = _UserCountry; + Items.Insert(0, newItem); + //Now let's Pre-Select it + Items.FindByValue(_UserCountryCode).Selected = true; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.csproj b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.csproj new file mode 100644 index 00000000000..d65545b49f9 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.csproj @@ -0,0 +1,112 @@ + + + + 9.0.30729 + 2.0 + {CA056730-5759-41F8-A6C1-420F9C0C63E7} + Debug + AnyCPU + CountryListBox + None + Library + v4.0 + SAK + SAK + SAK + SAK + CountryListBox + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + bin\ + CountryListBox.xml + true + true + 4 + full + AllRules.ruleset + 1591 + default + + + bin\ + CountryListBox.xml + true + true + 4 + pdbonly + AllRules.ruleset + 1591 + + + + + 3.5 + + + + 3.5 + + + System.Web + + + + + + Code + + + Code + + + Code + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.xml b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.xml new file mode 100644 index 00000000000..f7a42ea7544 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryListBox.xml @@ -0,0 +1,8 @@ + + + + CountryListBox + + + + diff --git a/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryLookup.cs b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryLookup.cs new file mode 100644 index 00000000000..cb0e276cdfc --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/CountryListBox/CountryLookup.cs @@ -0,0 +1,286 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +//------------------------------------------------------------------------------------------------ +// This class uses an IP lookup database from MaxMind, specifically +// the GeoIP Free Database. +// +// The database and the c# implementation of this class +// are available from http://www.maxmind.com/app/csharp +//------------------------------------------------------------------------------------------------ +#region Usings + +using System; +using System.IO; +using System.Net; + +#endregion + +namespace DotNetNuke.UI.WebControls +{ + public class CountryLookup + { + private static long CountryBegin = 16776960; + + private static readonly string[] CountryName = new[] + { + "N/A", "Asia/Pacific Region", "Europe", "Andorra", "United Arab Emirates", "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania", + "Armenia", "Netherlands Antilles", "Angola", "Antarctica", "Argentina", "American Samoa", "Austria", "Australia", "Aruba", "Azerbaijan", + "Bosnia and Herzegovina", "Barbados", "Bangladesh", "Belgium", "Burkina Faso", "Bulgaria", "Bahrain", "Burundi", "Benin", "Bermuda", + "Brunei Darussalam", "Bolivia", "Brazil", "Bahamas", "Bhutan", "Bouvet Island", "Botswana", "Belarus", "Belize", "Canada", + "Cocos (Keeling) Islands", "Congo, The Democratic Republic of the", "Central African Republic", "Congo", "Switzerland", "Cote D'Ivoire", + "Cook Islands", "Chile", "Cameroon", "China", "Colombia", "Costa Rica", "Cuba", "Cape Verde", "Christmas Island", "Cyprus", "Czech Republic" + , "Germany", "Djibouti", "Denmark", "Dominica", "Dominican Republic", "Algeria", "Ecuador", "Estonia", "Egypt", "Western Sahara", "Eritrea", + "Spain", "Ethiopia", "Finland", "Fiji", "Falkland Islands (Malvinas)", "Micronesia, Federated States of", "Faroe Islands", "France", + "France, Metropolitan", "Gabon", "United Kingdom", "Grenada", "Georgia", "French Guiana", "Ghana", "Gibraltar", "Greenland", "Gambia", + "Guinea", "Guadeloupe", "Equatorial Guinea", "Greece", "South Georgia and the South Sandwich Islands", "Guatemala", "Guam", "Guinea-Bissau", + "Guyana", "Hong Kong", "Heard Island and McDonald Islands", "Honduras", "Croatia", "Haiti", "Hungary", "Indonesia", "Ireland", "Israel", + "India", "British Indian Ocean Territory", "Iraq", "Iran, Islamic Republic of", "Iceland", "Italy", "Jamaica", "Jordan", "Japan", "Kenya", + "Kyrgyzstan", "Cambodia", "Kiribati", "Comoros", "Saint Kitts and Nevis", "Korea, Democratic People's Republic of", "Korea, Republic of", + "Kuwait", "Cayman Islands", "Kazakstan", "Lao People's Democratic Republic", "Lebanon", "Saint Lucia", "Liechtenstein", "Sri Lanka", + "Liberia", "Lesotho", "Lithuania", "Luxembourg", "Latvia", "Libyan Arab Jamahiriya", "Morocco", "Monaco", "Moldova, Republic of", + "Madagascar", "Marshall Islands", "Macedonia, the Former Yugoslav Republic of", "Mali", "Myanmar", "Mongolia", "Macau", + "Northern Mariana Islands", "Martinique", "Mauritania", "Montserrat", "Malta", "Mauritius", "Maldives", "Malawi", "Mexico", "Malaysia", + "Mozambique", "Namibia", "New Caledonia", "Niger", "Norfolk Island", "Nigeria", "Nicaragua", "Netherlands", "Norway", "Nepal", "Nauru", + "Niue", "New Zealand", "Oman", "Panama", "Peru", "French Polynesia", "Papua New Guinea", "Philippines", "Pakistan", "Poland", + "Saint Pierre and Miquelon", "Pitcairn", "Puerto Rico", "Palestinian Territory, Occupied", "Portugal", "Palau", "Paraguay", "Qatar", + "Reunion", "Romania", "Russian Federation", "Rwanda", "Saudi Arabia", "Solomon Islands", "Seychelles", "Sudan", "Sweden", "Singapore", + "Saint Helena", "Slovenia", "Svalbard and Jan Mayen", "Slovakia", "Sierra Leone", "San Marino", "Senegal", "Somalia", "Suriname", + "Sao Tome and Principe", "El Salvador", "Syrian Arab Republic", "Swaziland", "Turks and Caicos Islands", "Chad", + "French Southern Territories", "Togo", "Thailand", "Tajikistan", "Tokelau", "Turkmenistan", "Tunisia", "Tonga", "East Timor", "Turkey", + "Trinidad and Tobago", "Tuvalu", "Taiwan, Province of China", "Tanzania, United Republic of", "Ukraine", "Uganda", + "United States Minor Outlying Islands", "United States", "Uruguay", "Uzbekistan", "Holy See (Vatican City State)", + "Saint Vincent and the Grenadines", "Venezuela", "Virgin Islands, British", "Virgin Islands, U.S.", "Vietnam", "Vanuatu", + "Wallis and Futuna", "Samoa", "Yemen", "Mayotte", "Yugoslavia", "South Africa", "Zambia", "Zaire", "Zimbabwe", "Anonymous Proxy", + "Satellite Provider" + }; + + private static readonly string[] CountryCode = new[] + { + "--", "AP", "EU", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", + "BF", "BG", "BH", "BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", + "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", + "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", + "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", + "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", + "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", + "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", + "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", + "TD", "TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TP", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", + "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW", "A1", "A2" + }; + + public MemoryStream m_MemoryStream; + + public CountryLookup(MemoryStream ms) + { + m_MemoryStream = ms; + } + + public CountryLookup(string FileLocation) + { + //------------------------------------------------------------------------------------------------ + //Load the passed in GeoIP Data file to the memorystream + //------------------------------------------------------------------------------------------------ + var _FileStream = new FileStream(FileLocation, FileMode.Open, FileAccess.Read); + m_MemoryStream = new MemoryStream(); + var _Byte = new byte[256]; + while (_FileStream.Read(_Byte, 0, _Byte.Length) != 0) + { + m_MemoryStream.Write(_Byte, 0, _Byte.Length); + } + _FileStream.Close(); + } + + private long ConvertIPAddressToNumber(IPAddress _IPAddress) + { + //Convert an IP Address, (e.g. 127.0.0.1), to the numeric equivalent + string[] _Address = _IPAddress.ToString().Split('.'); + if (_Address.Length == 4) + { + return Convert.ToInt64(16777216*Convert.ToDouble(_Address[0]) + 65536*Convert.ToDouble(_Address[1]) + 256*Convert.ToDouble(_Address[2]) + Convert.ToDouble(_Address[3])); + } + else + { + return 0; + } + } + + private string ConvertIPNumberToAddress(long _IPNumber) + { + //Convert an IP Number to the IP Address equivalent + string _IPNumberPart1 = Convert.ToString(((int) (_IPNumber/16777216))%256); + string _IPNumberPart2 = Convert.ToString(((int) (_IPNumber/65536))%256); + string _IPNumberPart3 = Convert.ToString(((int) (_IPNumber/256))%256); + string _IPNumberPart4 = Convert.ToString(((int) (_IPNumber))%256); + return _IPNumberPart1 + "." + _IPNumberPart2 + "." + _IPNumberPart3 + "." + _IPNumberPart4; + } + + public static MemoryStream FileToMemory(string FileLocation) + { + //Read a given file into a Memory Stream to return as the result + FileStream _FileStream; + var _MemStream = new MemoryStream(); + var _Byte = new byte[256]; + try + { + _FileStream = new FileStream(FileLocation, FileMode.Open, FileAccess.Read); + while (_FileStream.Read(_Byte, 0, _Byte.Length) != 0) + { + _MemStream.Write(_Byte, 0, _Byte.Length); + } + _FileStream.Close(); + } + catch (FileNotFoundException exc) + { + throw new Exception(exc.Message + + " Please set the \"GeoIPFile\" Property to specify the location of this file. The property value must be set to the virtual path to GeoIP.dat (i.e. \"/controls/CountryListBox/Data/GeoIP.dat\")"); + } + return _MemStream; + } + + public string LookupCountryCode(IPAddress _IPAddress) + { + //Look up the country code, e.g. US, for the passed in IP Address + return CountryCode[Convert.ToInt32(SeekCountry(0, ConvertIPAddressToNumber(_IPAddress), 31))]; + } + + public string LookupCountryCode(string _IPAddress) + { + //Look up the country code, e.g. US, for the passed in IP Address + IPAddress _Address; + try + { + _Address = IPAddress.Parse(_IPAddress); + } + catch (FormatException) + { + return "--"; + } + return LookupCountryCode(_Address); + } + + public string LookupCountryName(IPAddress addr) + { + //Look up the country name, e.g. United States, for the IP Address + return CountryName[Convert.ToInt32(SeekCountry(0, ConvertIPAddressToNumber(addr), 31))]; + } + + public string LookupCountryName(string _IPAddress) + { + //Look up the country name, e.g. United States, for the IP Address + IPAddress _Address; + try + { + _Address = IPAddress.Parse(_IPAddress); + } + catch (FormatException) + { + return "N/A"; + } + return LookupCountryName(_Address); + } + + private long vbShiftLeft(long value, int Count) + { + //------------------------------------------------------------------------------------------------ + // Replacement for Bitwise operators which are missing in VB.NET, + // these functions are present in .NET 1.1, but for developers + // using 1.0, replacement functions must be implemented + //------------------------------------------------------------------------------------------------ + long returnValue = 0; + int _Iterator; + returnValue = value; + for (_Iterator = 1; _Iterator <= Count; _Iterator++) + { + returnValue = returnValue*2; + } + return returnValue; + } + + private long vbShiftRight(long value, int Count) + { + //------------------------------------------------------------------------------------------------ + // Replacement for Bitwise operators which are missing in VB.NET, + // these functions are present in .NET 1.1, but for developers + // using 1.0, replacement functions must be implemented + //------------------------------------------------------------------------------------------------ + long returnValue = 0; + int _Iterator; + returnValue = value; + for (_Iterator = 1; _Iterator <= Count; _Iterator++) + { + returnValue = returnValue/2; + } + return returnValue; + } + + public int SeekCountry(int Offset, long Ipnum, short Depth) + { + try + { + var Buffer = new byte[6]; + var X = new int[2]; + short I; + short J; + byte Y; + if (Depth == 0) + { + throw new Exception(); + } + m_MemoryStream.Seek(6*Offset, 0); + m_MemoryStream.Read(Buffer, 0, 6); + for (I = 0; I <= 1; I++) + { + X[I] = 0; + for (J = 0; J <= 2; J++) + { + Y = Buffer[I*3 + J]; + if (Y < 0) + { + Y = Convert.ToByte(Y + 256); + } + X[I] = Convert.ToInt32(X[I] + vbShiftLeft(Y, J*8)); + } + } + if ((Ipnum & vbShiftLeft(1, Depth)) > 0) + { + if (X[1] >= CountryBegin) + { + return Convert.ToInt32(X[1] - CountryBegin); + } + return SeekCountry(X[1], Ipnum, Convert.ToInt16(Depth - 1)); + } + else + { + if (X[0] >= CountryBegin) + { + return Convert.ToInt32(X[0] - CountryBegin); + } + return SeekCountry(X[0], Ipnum, Convert.ToInt16(Depth - 1)); + } + } + catch (Exception exc) + { + throw new Exception("Error seeking country: " + exc.Message); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Controls/SolpartMenu/CountryListBox/Properties/AssemblyInfo.cs b/DNN Platform/Controls/SolpartMenu/CountryListBox/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..835f8af5d27 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/CountryListBox/Properties/AssemblyInfo.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Web.UI; + +#endregion + +[assembly: AssemblyTitle("DotNetNuke")] +[assembly: AssemblyDescription("Open Source Web Application Framework")] +[assembly: AssemblyCompany("DotNetNuke Corporation")] +[assembly: AssemblyProduct("http://www.dotnetnuke.com")] +[assembly: AssemblyCopyright("DotNetNuke is copyright 2002-2013 by DotNetNuke Corporation. All Rights Reserved.")] +[assembly: AssemblyTrademark("DotNetNuke")] +[assembly: CLSCompliant(true)] +[assembly: Guid("3D57E77F-F723-48BB-A58C-3FAB63C562D4")] +[assembly: AssemblyVersion("6.2.1.11")] +[assembly: TagPrefix("DotNetNuke.UI.WebControls.CountryListBox", "DotNetNuke")] diff --git a/DNN Platform/Controls/SolpartMenu/License.txt b/DNN Platform/Controls/SolpartMenu/License.txt new file mode 100644 index 00000000000..15cd5411ff3 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/License.txt @@ -0,0 +1,27 @@ +'============================================================================= +'No Nonsense Copyright and License for Solpart ASP.NET Hierarchical WebControl +'============================================================================= +' +'Copyright: +' +'This library was written by me. You are welcome to use it, modify it to suit +'your needs, distribute it as you see fit. I'm happy if you use it for +'personal stuff or for commercial gain. +' +'The only thing you can't do is to restrict anyone else from using it however +'they see fit. You may not copyright it yourself or change the rules I have +'set on how it can be used. +' +'Solpart ASP.NET Hierarchical WebControl Copyright (C) 2002 by Jon Henning +' +'License: +' +'You can use this however you like. I make no guarantees whatsoever that it +'will suit your purpose. You take full responsibility for getting it working +'properly and for any implications of its failure or inability to satisfy your +'every need. +' +'============================================================================= +' +'Email: jhenning@solpart.com +'Web: http://www.solpart.com/techcorner diff --git a/DNN Platform/Controls/SolpartMenu/ReleaseNotes.txt b/DNN Platform/Controls/SolpartMenu/ReleaseNotes.txt new file mode 100644 index 00000000000..af19cd51569 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/ReleaseNotes.txt @@ -0,0 +1,348 @@ +========================================================== +SolpartMenu v1.6.0.1 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- MacIE support added! + +========================================================== +SolpartMenu v1.6.0.0 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Addition of SPMenuCaps.config file to configure which browsers + have which features (i.e. which ones render uplevel vs. downlevel) + + +========================================================== +SolpartMenu v1.5.0.2 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed issue with Safari upgrade 1.3.312 + +========================================================== +SolpartMenu v1.5.0.0 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed issue with Safari (IFrame trick caused menu not to show) +- Fixed function naming for Netscape/FireFox/Mozilla + when control has '-' character in it. + +========================================================== +SolpartMenu v1.4.0.3 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed issue with IFRAME trick and SSL (void(0) no longer + works no using src=spacer.gif + +========================================================== +SolpartMenu v1.4.0.2 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed minor issue with rendering vertical menu and it + scrolled off page. +- Fixed error When rendering ForceFullMenuList and no child nodes + exist +- Fixed issue that stopped menu from being used in a + Trust=Medium + +========================================================== +SolpartMenu v1.4.0.0 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed issues with Safari + - sub-menu alignment (Safari bug workaround) + - mouseout delay always set to 5 sec + - Browser identification sometimes rendered downlevel + +- applying keeping saved css class on hover +- Applying submenu class to menu when forcefullmenuList on +- reading in zindex for menu and incrementing 1 higher for + iframe trick. + + +========================================================== +SolpartMenu v1.3.0.5 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed MapPath issue with menu module +- Added new menu provider to allow role based custom menus + +========================================================== +SolpartMenu v1.3.0.3 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Made IFrame trick a property to turn off +- When using IFrame trick setting src = javascript code + to avoid page not found message bleeding through +- Made different technique to avoid operation aborted and + load up front at the same time + +========================================================== +SolpartMenu v1.3.0.2 - Notes +========================================================== +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Changed dir="rtl" alignment of submenus to be from right corner +- Fixed issue with IFRAME trick and SSL +- Fixed issue with IE5/5.5 for pages with menus that were set + to be invisible. +- Absolute positioned menu support added! +- Default way of handling windowed controls now is using an + IFRAME. Therefore you will no longer see your SELECT and + OBJECT tags disappear when the menu overlaps. + It should be noted that this idea originated from + http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx +- New CSS class ability ItemSelectedCss - for specifying a + different class for the selected item than the default MenuItemSel +- Allowing Seperators to contain HTML - new overloaded methods + for AddBreak now accepts HTML parameter +- New MenuEffect Property MouseOverScroll. Defaults to true, + when set having the mouse over the ... will scroll the menu + in addition to clicking ... +- Added Target property to allow menu items with urls specified + to change the source of specified frame. +- New examples - showing absolute positioning and image menus + + +========================================================== +SolpartMenu v1.2.0.3 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Added new method FindMenuItem. Useful for applying a + specific style to selected menu item. +- Now hiding overlapping OBJECT tags (along with SELECT tags) +- Fixed issue with submenus positioning when root menu items + scrolled off page +- Fixed issue with Mozilla/NS/Opera where submenu would scroll + off page +- ItemStyle now applying to TDs in addition to the TR + WARNING: MAY CAUSE DISPLAY CHANGES IF PROPERTY WAS USED! +- Added ItemCss to go along with ItemStyle so that special + class can be applied on item level. +- Fixed minor issue with savecss (for menuitem css). + +--- DNN MenuModule Specific --- +---------------------------------------------------------- +- Added new MenuDataProvider to allow the showing of only + child tabs from current active tab +- Changed ForceFullMenuList to output tree-like structure, + complete with styles. Allows for an easy way to do a site + map. +- Added ForceFullMenuList to MenuDesigner in DNN +- Added Tooltip to menuitem for MenuDesigner in DNN +- Added css to menuitem for MenuDesigner in DNN +- Fixed css style applying to preview in MenuDesigner + + +========================================================== +SolpartMenu v1.2.0.0 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- + +- Added ToolTip functionality +- When menu detects there is not enough room to display + it will automatically add a scroll menu item to the top + and bottom when applicable. +- New MenuCSS.MenuScroll class to customize display +- Fixed Mozilla/Netscape border color issues +- Minor fixes to ALT text of images +- Fixed issue with menu designer where left/righthtml + not safely encoded +- If menu detects dir="rtl" it will cause sub-menus to be + displayed on the left instead of right. IE seems to work + correctly, Mozilla/Netscape seem to have problems. + + +========================================================== +SolpartMenu v1.1.1.2 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- + +- Added functionality to detect Crawlers and have menu + render in a fashion that the Crawler can detect +- Added property ForceFullMenuList - to force output to + render as if Crawler is requesting the page +- Added DataBindMappings collection to allow for any menu + item attribute to be bound to datasource +- Fixed Netscape 7.1 problem where doesn't report 'this' + onclick of menu item (now runat server works for this + browser) +- Fixed Opera 7 postbacks (cannot access name property on client) +- Added root level menubreak +- Added script type to SCRIPT tags (javascript) + + +========================================================== +SolpartMenu v1.1.1.0 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Fixed problem with MenuClick event when in a UserControl +- Added MenuItems collection to navigate through nodes +- Added SeparateCSS property to stop sending of CSS styles +- Fixed Shadow issue when no transition style specified +- Fixed problem with sending duplicate styles down after postback +- renamed attributes to be under 15 characters to allow + getAttribute to work with Konqueror and Safari. + (SystemImagesPath --> SysImgPath) +- Allowing Data binding to have non-numeric keys +- Fixed positioning when window is scrolled +- Updated Safari support +- Fixed problem when SmartNavigation is turned on + - Problem: postback with SmartNav enabled does + not fire the readystate event + - Solution: when smartnav is enabled menu will + use setTimeout to continually poll + the page until readyState is complete + +========================================================== +SolpartMenu v1.1.0.7 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Support for new Mac browser Safari + - Problem: Safari doesn't report offsetWidths/heights of some elements + - Solution: go to parent to get width/height + - Problem: Safari needs to include BODY when getting element positions via offsetTop/Left + - Solution: apparently only the root menu items need to include Body offset + - Problem: a bug in Safari where the HTMLcollection object returned for cells is always empty + - Solution: none, safari menus cannot display selected border colors until its resolved by safari development team. + this has been entered into the Safari bug tracking system (#3426081) + +- Added new property MenuItems to access collection of SPMenuItemNode +- Added script to handle lack of events firing when SmartNavigation is enabled + + + +========================================================== +SolpartMenu v1.1.0.6 - Notes +========================================================== +I just realized that you may want the source of the menu +that is used in the DNN menu designer. Thus, am doing this +minor release. + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- using SafeClientID property to render menu (fixes IDs starting with _) +- attempting to fix Safari (not there yet) + + +========================================================== +SolpartMenu v1.1 - Notes +========================================================== + +---------------------------------------------------------- +Enhancements +---------------------------------------------------------- +- Introduced wrapper class around Menu Item XMLNode called SPMenuItemNode to ease programming of attributes. +- Downlevel browser appearance has been updated to handle new properties, including placing icons on menu bar (also supported on uplevel browsers) +- Added ability to render UpLevel menu in browser without an XML parser using JS array +- Added Menu designer - see comments in code to help out integrating with DNN +- Added ALT tags to images to improve ADA compliance + + +---------------------------------------------------------- +Properties of interest +---------------------------------------------------------- +- Menu Object +-- IconImagesPath Location of the icon images (in DNN this would be the GUID location) if not specified defaults to SystemImagePath +-- SystemImagesPath Location of the images specific to the rendering of the menu (i.e. spacer.gif) +-- MenuBarLeftHTML - allows custom HTML to be placed to the left of the menu bar +-- MenuBarRightHTML - allows custom HTML to be placed to the right of the menu bar +-- MenuCSSPlaceHolderControl - allows a placeholder tag to be specified so menu's css properties can be set within the tag. + +-MenuItem Object +-- ImagePath If icon is not coming from the IconImagesPath then specify a path here. This is for admin icons. +-- LeftHTML Allows for a custom HTML to be displayed to the left of the menuitems Title. +-- RightHTML Allows for a custom HTML to be displayed to the right of the menuitems Title. This is for the selected menu item image. + + + +---------------------------------------------------------- +The following browsers will render the UpLevel menu +---------------------------------------------------------- +IE 5.0 - uses JSXMLArray +IE5.5 - uses XML DataIslands (for superior caching) +IE6 - uses XML DataIslands (for superior caching) +Mozilla (Mac/Win/Linux) - uses XML Parser +Netscape 6 (Mac/Win/Linux) - uses XML Parser +Netscape 7 (Mac/Win/Linux) - uses XML Parser +Opera 7 (Win/Linux) - uses JSXMLArray - DNN HTML Layout issues causes transparent menus +Konqueror(Linux) - minor positioning issues +Safari (Mac) - trying... + +---------------------------------------------------------- +The following browsers will render the DownLevel menu +---------------------------------------------------------- +IE5 (Mac) - Absolute positioning issues +NS 4 - +Opera 6 - +Any other browser - + + +---------------------------------------------------------- +IMPORTANT! MenuCSSPlaceHolderControl +---------------------------------------------------------- +I have added a property called MenuCSSPlaceHolderControl which is set to SPMenuStyle. This allows the menu's +CSS style to be inserted at the desired location within the tag. It is highly +recommended that you place the following tag within the section. + +Failure to do so will result in the menu placing its style at the very beginning of the output stream, +which I believe is not valid in some browsers. + + +---------------------------------------------------------- +Fixes +---------------------------------------------------------- +- Fixed registering of systemscript so only sends down once +- Fixed 1 pixel jump to right on entry of submenu, was due to the menu not having a border set. Now am checking this before applying left border on icon. +- Fixed issue with border on root arrow +- Fixed style issue for netscape 4 + + + +---------------------------------------------------------- +IE For the Mac +---------------------------------------------------------- +Well what can I say? After many attempts at getting this to work in an uplevel fashion I have +made some headway but not enough. I have determined that this is not going to hold up my release +any longer, so for now the menu will render downlevel. On a positive note I have determined +what was causing the css not to render properly (extra spaces in the class property). Unfortunately, +I have not been able to resolve the positioning yet (you should only need to modify the spm_elementTop +and spm_elementLeft functions in the .js file). I want to say thank you to everyone who has +helped out with this issue, especially Davor and Erin. + + + diff --git a/DNN Platform/Controls/SolpartMenu/SPMenuCaps.config b/DNN Platform/Controls/SolpartMenu/SPMenuCaps.config new file mode 100644 index 00000000000..30754e38ba5 --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/SPMenuCaps.config @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Controls/SolpartMenu/Solution Partners ASP.NET Hierarchical Menu.doc b/DNN Platform/Controls/SolpartMenu/Solution Partners ASP.NET Hierarchical Menu.doc new file mode 100644 index 00000000000..d387aa9e0b1 Binary files /dev/null and b/DNN Platform/Controls/SolpartMenu/Solution Partners ASP.NET Hierarchical Menu.doc differ diff --git a/DNN Platform/Controls/SolpartMenu/spmenu.js b/DNN Platform/Controls/SolpartMenu/spmenu.js new file mode 100644 index 00000000000..013fd4ab71b --- /dev/null +++ b/DNN Platform/Controls/SolpartMenu/spmenu.js @@ -0,0 +1,2134 @@ +//------------------------------------------------------// +// Solution Partner's ASP.NET Hierarchical Menu Control // +// Copyright (c) 2002-2010 // +// Jon Henning - Solution Partner's Inc // +// jhenning@solpart.com - http://www.solpart.com // +// Compatible Menu Version: // +// // +// \r\n"); + cs.RegisterClientScriptBlock(GetType(), scriptName, scriptBuilder.ToString()); + } + } + } + + protected override object SaveControlState() + { + return _itemCount > 0 ? (object) _itemCount : null; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEmptyTemplate.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEmptyTemplate.cs new file mode 100644 index 00000000000..caaaf9f407f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEmptyTemplate.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnFormEmptyTemplate : WebControl, INamingContainer + { + protected override HtmlTextWriterTag TagKey + { + get + { + return HtmlTextWriterTag.Div; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEnumItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEnumItem.cs new file mode 100644 index 00000000000..1063ed38f6d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormEnumItem.cs @@ -0,0 +1,58 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Linq; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormEnumItem : DnnFormComboBoxItem + { + private string _enumType; + + public string EnumType + { + get + { + return _enumType; + } + set + { + _enumType = value; + // ReSharper disable AssignNullToNotNullAttribute + ListSource = (from object enumValue in Enum.GetValues(Type.GetType(_enumType)) + select new { Name = Enum.GetName(Type.GetType(_enumType), enumValue), Value = (int)enumValue }) + .ToList(); + // ReSharper restore AssignNullToNotNullAttribute + } + } + + protected override void BindList() + { + ListTextField = "Name"; + ListValueField = "Value"; + + BindListInternal(ComboBox, Convert.ToInt32(Value), ListSource, ListTextField, ListValueField); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormItemBase.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormItemBase.cs new file mode 100644 index 00000000000..1a9aa1a6d03 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormItemBase.cs @@ -0,0 +1,447 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Collections; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public abstract class DnnFormItemBase : WebControl, INamingContainer + { + private object _value; + private string _requiredMessageSuffix = ".Required"; + private string _validationMessageSuffix = ".RegExError"; + + protected DnnFormItemBase() + { + FormMode = DnnFormMode.Inherit; + IsValid = true; + + Validators = new List(); + } + + #region Protected Properties + + protected PropertyInfo ChildProperty + { + get + { + Type type = Property.PropertyType; + IList props = new List(type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)); + return props.SingleOrDefault(p => p.Name == DataField); + } + } + + protected PortalSettings PortalSettings + { + get { return PortalController.GetCurrentPortalSettings(); } + } + + protected PropertyInfo Property + { + get + { + Type type = DataSource.GetType(); + IList props = new List(type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)); + return !String.IsNullOrEmpty(DataMember) + ? props.SingleOrDefault(p => p.Name == DataMember) + : props.SingleOrDefault(p => p.Name == DataField); + } + } + + protected override HtmlTextWriterTag TagKey + { + get + { + return HtmlTextWriterTag.Div; + } + } + + public object Value + { + get { return _value; } + set { _value = value; } + } + + #endregion + + #region Public Properties + + public string DataField { get; set; } + + public string DataMember { get; set; } + + internal object DataSource { get; set; } + + public DnnFormMode FormMode { get; set; } + + public bool IsValid { get; private set; } + + public string OnClientClicked { get; set; } + + public string LocalResourceFile { get; set; } + + public bool Required { get; set; } + + public string ResourceKey { get; set; } + + public string RequiredMessageSuffix + { + get + { + return _requiredMessageSuffix; + } + set + { + _requiredMessageSuffix = value; + } + } + + public string ValidationMessageSuffix + { + get + { + return _validationMessageSuffix; + } + set + { + _validationMessageSuffix = value; + } + } + + [Category("Behavior"), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public List Validators { get; private set; } + + public string ValidationExpression { get; set; } + + #endregion + + #region Control Hierarchy and Data Binding + + private void AddValidators(string controlId) + { + var value = Value as String; + Validators.Clear(); + + //Add Validators + if (Required) + { + var requiredValidator = new RequiredFieldValidator + { + ID = ID + "_Required", + ErrorMessage = ResourceKey + RequiredMessageSuffix + }; + if (String.IsNullOrEmpty(value) && Page.IsPostBack) + { + requiredValidator.IsValid = false; + IsValid = requiredValidator.IsValid; + } + Validators.Add(requiredValidator); + } + + if (!String.IsNullOrEmpty(ValidationExpression)) + { + var regexValidator = new RegularExpressionValidator + { + ID = ID + "_RegEx", + ErrorMessage = ResourceKey + ValidationMessageSuffix, + ValidationExpression = ValidationExpression + }; + if (!String.IsNullOrEmpty(value)) + { + regexValidator.IsValid = Regex.IsMatch(value, ValidationExpression); + IsValid = regexValidator.IsValid; + } + Validators.Add(regexValidator); + } + + if (Validators.Count > 0) + { + foreach (BaseValidator validator in Validators) + { + validator.ControlToValidate = controlId; + validator.Display = ValidatorDisplay.Dynamic; + validator.ErrorMessage = LocalizeString(validator.ErrorMessage); + validator.CssClass = "dnnFormMessage dnnFormError"; + Controls.Add(validator); + } + } + } + + public void CheckIsValid() + { + IsValid = true; + foreach (BaseValidator validator in Validators) + { + validator.Validate(); + if (!validator.IsValid) + { + IsValid = false; + break; + } + } + } + + protected virtual void CreateControlHierarchy() + { + //Load Item Style + CssClass = "dnnFormItem"; + CssClass += (FormMode == DnnFormMode.Long) ? "" : " dnnFormShort"; + + if (String.IsNullOrEmpty(ResourceKey)) + { + ResourceKey = DataField; + } + + //Add Label + var label = new DnnFormLabel + { + LocalResourceFile = LocalResourceFile, + ResourceKey = ResourceKey + ".Text", + ToolTipKey = ResourceKey + ".Help" + }; + + if (Required) { + + label.RequiredField = true; + } + + Controls.Add(label); + + WebControl inputControl = CreateControlInternal(this); + label.AssociatedControlID = inputControl.ID; + AddValidators(inputControl.ID); + } + + /// + /// Use container to add custom control hierarchy to + /// + /// + /// An "input" control that can be used for attaching validators + protected virtual WebControl CreateControlInternal(Control container) + { + return null; + } + + protected override void CreateChildControls() + { + // CreateChildControls re-creates the children (the items) + // using the saved view state. + // First clear any existing child controls. + Controls.Clear(); + + CreateControlHierarchy(); + } + + protected void DataBindInternal(string dataField, ref object value) + { + var dictionary = DataSource as IDictionary; + if (dictionary != null) + { + if (!String.IsNullOrEmpty(dataField) && dictionary.Contains(dataField)) + { + value = dictionary[dataField]; + } + } + else + { + if (!String.IsNullOrEmpty(dataField)) + { + if (String.IsNullOrEmpty(DataMember)) + { + if (Property != null && Property.GetValue(DataSource, null) != null) + { + // ReSharper disable PossibleNullReferenceException + value = Property.GetValue(DataSource, null); + // ReSharper restore PossibleNullReferenceException + } + } + else + { + if (Property != null && Property.GetValue(DataSource, null) != null) + { + // ReSharper disable PossibleNullReferenceException + object parentValue = Property.GetValue(DataSource, null); + if (ChildProperty != null && ChildProperty.GetValue(parentValue, null) != null) + { + value = ChildProperty.GetValue(parentValue, null); + } + // ReSharper restore PossibleNullReferenceException + } + } + } + } + } + + protected virtual void DataBindInternal() + { + DataBindInternal(DataField, ref _value); + } + + public void DataBindItem(bool useDataSource) + { + if (useDataSource) + { + base.OnDataBinding(EventArgs.Empty); + Controls.Clear(); + ClearChildViewState(); + TrackViewState(); + + DataBindInternal(); + + CreateControlHierarchy(); + ChildControlsCreated = true; + } + else + { + if (!String.IsNullOrEmpty(DataField)) + { + UpdateDataSourceInternal(null, _value, DataField); + } + } + } + + private void UpdateDataSourceInternal(object oldValue, object newValue, string dataField) + { + if (DataSource != null) + { + if (DataSource is IDictionary) + { + var dictionary = DataSource as IDictionary; + if (dictionary.ContainsKey(dataField) && !ReferenceEquals(newValue, oldValue)) + { + dictionary[dataField] = newValue as string; + } + } + else if(DataSource is IIndexable) + { + var indexer = DataSource as IIndexable; + indexer[dataField] = newValue; + } + else + { + if (String.IsNullOrEmpty(DataMember)) + { + if (Property != null) + { + if (!ReferenceEquals(newValue, oldValue)) + { + if (Property.PropertyType.IsEnum) + { + Property.SetValue(DataSource, Enum.Parse(Property.PropertyType, newValue.ToString()), null); + } + else + { + Property.SetValue(DataSource, Convert.ChangeType(newValue, Property.PropertyType), null); + } + } + } + } + else + { + if (Property != null) + { + object parentValue = Property.GetValue(DataSource, null); + if (parentValue != null) + { + if (parentValue is IDictionary) + { + var dictionary = parentValue as IDictionary; + if (dictionary.ContainsKey(dataField) && !ReferenceEquals(newValue, oldValue)) + { + dictionary[dataField] = newValue as string; + } + } + else if (parentValue is IIndexable) + { + var indexer = parentValue as IIndexable; + indexer[dataField] = newValue; + } + else if (ChildProperty != null) + { + if (Property.PropertyType.IsEnum) + { + ChildProperty.SetValue(parentValue, Enum.Parse(ChildProperty.PropertyType, newValue.ToString()), null); + } + else + { + ChildProperty.SetValue(parentValue, Convert.ChangeType(newValue, ChildProperty.PropertyType), null); + } + } + } + } + } + } + } + } + + protected void UpdateDataSource(object oldValue, object newValue, string dataField) + { + CheckIsValid(); + + _value = newValue; + + UpdateDataSourceInternal(oldValue, newValue, dataField); + } + + #endregion + + #region Protected Methods + + protected override void LoadControlState(object state) + { + _value = state; + } + + protected string LocalizeString(string key) + { + return Localization.GetString(key, LocalResourceFile); + } + + protected override void OnInit(EventArgs e) + { + Page.RegisterRequiresControlState(this); + base.OnInit(e); + } + + protected override object SaveControlState() + { + return _value; + } + + #endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLabel.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLabel.cs new file mode 100644 index 00000000000..b0067f4f9d2 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLabel.cs @@ -0,0 +1,106 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Framework; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.UserControls; +using DotNetNuke.UI.Utilities; +using DotNetNuke.Web.Client.ClientResourceManagement; + +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormLabel : Panel + { + public string AssociatedControlID { get; set; } + + public string LocalResourceFile { get; set; } + + public string ResourceKey { get; set; } + + public string ToolTipKey { get; set; } + + public bool RequiredField { get; set; } + + protected override void CreateChildControls() + { + string toolTipText = LocalizeString(ToolTipKey); + if (string.IsNullOrEmpty(CssClass)) + CssClass = "dnnLabel"; + + else if (!CssClass.Contains("dnnLabel")) + CssClass += " dnnLabel"; + + + //var outerPanel = new Panel(); + //outerPanel.CssClass = "dnnLabel"; + //Controls.Add(outerPanel); + + var outerLabel = new System.Web.UI.HtmlControls.HtmlGenericControl { TagName = "label" }; + Controls.Add(outerLabel); + + var label = new Label { ID = "Label", Text = LocalizeString(ResourceKey) }; + if (RequiredField) + { + label.CssClass += " dnnFormRequired"; + } + outerLabel.Controls.Add(label); + + var link = new LinkButton { ID = "Link", CssClass = "dnnFormHelp", TabIndex = -1 }; + Controls.Add(link); + + if (!String.IsNullOrEmpty(toolTipText)) + { + //CssClass += "dnnLabel"; + + var tooltipPanel = new Panel() { CssClass = "dnnTooltip"}; + Controls.Add(tooltipPanel); + + var panel = new Panel { ID = "Help", CssClass = "dnnFormHelpContent dnnClear" }; + tooltipPanel.Controls.Add(panel); + + var helpLabel = new Label { ID = "Text", CssClass="dnnHelpText", Text = LocalizeString(ToolTipKey) }; + panel.Controls.Add(helpLabel); + + var pinLink = new HyperLink {CssClass = "pinHelp"}; + pinLink.Attributes.Add("href", "#"); + panel.Controls.Add(pinLink); + + ClientAPI.RegisterClientReference(Page, ClientAPI.ClientNamespaceReferences.dnn); + jQuery.RequestHoverIntentRegistration(); + jQuery.RequestDnnPluginsRegistration(); + //ClientResourceManager.RegisterScript(this.Page, "~/Resources/Shared/Scripts/initTooltips.js"); + } + } + + protected string LocalizeString(string key) + { + return Localization.GetString(key, LocalResourceFile); + } + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormListItemBase.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormListItemBase.cs new file mode 100644 index 00000000000..7030bab54e1 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormListItemBase.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public abstract class DnnFormListItemBase : DnnFormItemBase + { + private IEnumerable _listSource; + + public string DefaultValue { get; set; } + + public IEnumerable ListSource + { + get + { + return _listSource; + } + set + { + if (_listSource != value) + { + _listSource = value; + BindList(); + } + } + } + + public string ListTextField { get; set; } + + public string ListValueField { get; set; } + + protected virtual void BindList() + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLiteralItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLiteralItem.cs new file mode 100644 index 00000000000..6ca180eaf15 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormLiteralItem.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormLiteralItem : DnnFormItemBase + { + protected override WebControl CreateControlInternal(Control container) + { + var literal = new Label {ID = ID + "_Label", Text = Convert.ToString(Value)}; + container.Controls.Add(literal); + return literal; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormMode.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormMode.cs new file mode 100644 index 00000000000..88775a8682a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormMode.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.UI.WebControls +{ + public enum DnnFormMode + { + Inherit = 0, + Short = 1, + Long = 2 + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormNumericTextBoxItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormNumericTextBoxItem.cs new file mode 100644 index 00000000000..54e5c817b0e --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormNumericTextBoxItem.cs @@ -0,0 +1,92 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Framework; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormNumericTextBoxItem : DnnFormItemBase + { + //private DnnNumericTextBox _textBox; + private TextBox _textBox; + + public DnnFormNumericTextBoxItem() + { + TextBoxWidth = new Unit(100); + ShowSpinButtons = true; + Type = NumericType.Number; + DecimalDigits = 0; + } + + public int DecimalDigits { get; set; } + + public bool ShowSpinButtons { get; set; } + + public Unit TextBoxWidth { get; set; } + + public NumericType Type { get; set; } + + private void TextChanged(object sender, EventArgs e) + { + UpdateDataSource(Value, _textBox.Text, DataField); + } + + protected override WebControl CreateControlInternal(Control container) + { + //_textBox = new DnnNumericTextBox {EmptyMessage = LocalizeString(ResourceKey + ".Hint"), ID = ID + "_TextBox", Width = TextBoxWidth }; + _textBox = new TextBox(); + _textBox.CssClass = "DnnNumericTextBox"; + //_textBox.Style.Add("float", "none"); + //_textBox.EmptyMessageStyle.CssClass += "dnnformHint"; + //_textBox.Type = Type; + //_textBox.NumberFormat.DecimalDigits = DecimalDigits; + //_textBox.ShowSpinButtons = ShowSpinButtons; + _textBox.TextChanged += TextChanged; + + //Load from ControlState + _textBox.Text = Convert.ToString(Value); + + container.Controls.Add(_textBox); + jQuery.RegisterDnnJQueryPlugins(this.Page); + + var initalizeScript = ""; + Page.ClientScript.RegisterClientScriptBlock(GetType(), "DnnFormNumericTextBoxItem", initalizeScript); + + return _textBox; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + FormMode = DnnFormMode.Short; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPagesItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPagesItem.cs new file mode 100644 index 00000000000..f3bb15694bb --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPagesItem.cs @@ -0,0 +1,39 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Localization; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormPagesItem : DnnFormComboBoxItem + { + public DnnFormPagesItem() + { + ListSource = TabController.GetPortalTabs(PortalSettings.PortalId, Null.NullInteger, true, "<" + Localization.GetString("None_Specified") + ">", true, false, true, true, false); + ListTextField = "TabName"; + ListValueField = "TabID"; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPanel.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPanel.cs new file mode 100644 index 00000000000..49f1e47b063 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPanel.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormPanel : WebControl + { + + public bool Expanded { get; set; } + + public string Text { get; set; } + + protected override void Render(HtmlTextWriter writer) + { + writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass); + writer.RenderBeginTag(HtmlTextWriterTag.H2); + + if (Expanded) + { + writer.AddAttribute(HtmlTextWriterAttribute.Class, "dnnSectionExpanded"); + } + writer.RenderBeginTag(HtmlTextWriterTag.A); + writer.Write(Text); + writer.RenderEndTag(); + + writer.RenderEndTag(); + + writer.RenderBeginTag(HtmlTextWriterTag.Fieldset); + + RenderChildren(writer); + + writer.RenderEndTag(); + } + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPasswordItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPasswordItem.cs new file mode 100644 index 00000000000..a178e8d04e7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormPasswordItem.cs @@ -0,0 +1,128 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; +using DotNetNuke.Web.Client.ClientResourceManagement; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormPasswordItem : DnnFormItemBase + { + private TextBox _password; + + public string TextBoxCssClass + { + get + { + return ViewState.GetValue("TextBoxCssClass", string.Empty); + } + set + { + ViewState.SetValue("TextBoxCssClass", value, string.Empty); + } + } + + public string ContainerCssClass + { + get + { + return ViewState.GetValue("ContainerCssClass", string.Empty); + } + set + { + ViewState.SetValue("ContainerCssClass", value, string.Empty); + } + } + + private void TextChanged(object sender, EventArgs e) + { + UpdateDataSource(Value, _password.Text, DataField); + } + + /// + /// Use container to add custom control hierarchy to + /// + /// + /// An "input" control that can be used for attaching validators + protected override WebControl CreateControlInternal(Control container) + { + _password = new TextBox() + { + ID = ID + "_TextBox", + TextMode = TextBoxMode.Password, + CssClass = TextBoxCssClass, + MaxLength = 20, //ensure password cannot be cut if too long + Text = Convert.ToString(Value) // Load from ControlState + }; + _password.TextChanged += TextChanged; + + var passwordContainer = new Panel() { ID = "passwordContainer", CssClass = ContainerCssClass }; + + // add control hierarchy to the container + container.Controls.Add(passwordContainer); + + passwordContainer.Controls.Add(_password); + + // return input control that can be used for validation + return _password; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + ClientResourceManager.RegisterScript(Page, "~/Resources/Shared/scripts/dnn.jquery.extensions.js"); + ClientResourceManager.RegisterScript(Page, "~/Resources/Shared/scripts/dnn.jquery.tooltip.js"); + ClientResourceManager.RegisterScript(Page, "~/Resources/Shared/scripts/dnn.PasswordStrength.js"); + + jQuery.RequestDnnPluginsRegistration(); + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + var options = new DnnPaswordStrengthOptions(); + var optionsAsJsonString = Json.Serialize(options); + var script = string.Format("dnn.initializePasswordStrength('.{0}', {1});{2}", + TextBoxCssClass, optionsAsJsonString, Environment.NewLine); + + if (ScriptManager.GetCurrent(Page) != null) + { + // respect MS AJAX + ScriptManager.RegisterStartupScript(Page, GetType(), "PasswordStrength", script, true); + } + else + { + Page.ClientScript.RegisterStartupScript(GetType(), "PasswordStrength", script, true); + } + + } + + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormRadioButtonListItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormRadioButtonListItem.cs new file mode 100644 index 00000000000..815a18003d1 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormRadioButtonListItem.cs @@ -0,0 +1,93 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormRadioButtonListItem : DnnFormListItemBase + { + private RadioButtonList _radioButtonList; + + protected override void BindList() + { + if (_radioButtonList != null) + { + string selectedValue = !_radioButtonList.Page.IsPostBack ? Convert.ToString(Value) : _radioButtonList.Page.Request.Form[_radioButtonList.UniqueID]; + + if (ListSource is Dictionary) + { + var items = ListSource as Dictionary; + foreach (var item in items) + { + var listItem = new ListItem(item.Key, item.Value); + listItem.Attributes.Add("onClick", OnClientClicked); + + _radioButtonList.Items.Add(listItem); + } + } + else + { + _radioButtonList.DataTextField = ListTextField; + _radioButtonList.DataValueField = ListValueField; + _radioButtonList.DataSource = ListSource; + + _radioButtonList.DataBind(); + } + if (String.IsNullOrEmpty(selectedValue)) + { + selectedValue = DefaultValue; + } + + //Reset SelectedValue + if (_radioButtonList.Items.FindByValue(selectedValue) != null) + { + _radioButtonList.Items.FindByValue(selectedValue).Selected = true; + } + + if (selectedValue != Convert.ToString(Value)) + { + UpdateDataSource(Value, selectedValue, DataField); + } + } + } + + protected override WebControl CreateControlInternal(Control container) + { + _radioButtonList = new RadioButtonList { ID = ID + "_RadioButtonList", RepeatColumns = 1, RepeatDirection = RepeatDirection.Vertical, RepeatLayout = RepeatLayout.Flow}; + + container.Controls.Add(_radioButtonList); + + if (ListSource != null) + { + BindList(); + } + + return _radioButtonList; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSection.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSection.cs new file mode 100644 index 00000000000..7fb5d721581 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSection.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.ComponentModel; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnFormSection : WebControl, INamingContainer + { + public DnnFormSection() + { + Items = new List(); + } + + public bool Expanded { get; set; } + + [Category("Behavior"), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public List Items { get; private set; } + + public string ResourceKey { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSectionTemplate.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSectionTemplate.cs new file mode 100644 index 00000000000..a7237a40128 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSectionTemplate.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + internal class DnnFormSectionTemplate : ITemplate + { + public DnnFormSectionTemplate() + { + Items = new List(); + } + + public List Items { get; private set; } + + public string LocalResourceFile { get; set; } + + #region ITemplate Members + + public void InstantiateIn(Control container) + { + var webControl = container as WebControl; + if (webControl != null) + { + DnnFormEditor.SetUpItems(Items, webControl, LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSkinsItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSkinsItem.cs new file mode 100644 index 00000000000..4047e3614dd --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormSkinsItem.cs @@ -0,0 +1,135 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormSkinsItem : DnnFormItemBase + { + //private DropDownList _containerCombo; + private DnnComboBox _containerCombo; + private object _containerValue; + //private DropDownList _skinCombo; + private DnnComboBox _skinCombo; + private object _skinValue; + + public string ContainerDataField { get; set; } + + public bool IncludePortalSkins { get; set; } + + public int PortalId { get; set; } + + public string SkinDataField { get; set; } + + private void ContainerIndexChanged(object sender, EventArgs e) + { + UpdateDataSource(_containerValue, _containerCombo.SelectedValue, ContainerDataField); + } + + private void SkinIndexChanged(object sender, EventArgs e) + { + UpdateDataSource(_skinValue, _skinCombo.SelectedValue, SkinDataField); + } + + private Dictionary GetSkins(string skinRoot) + { + // load host skins + var skins = SkinController.GetSkins(null, skinRoot, SkinScope.Host).ToDictionary(skin => skin.Key, skin => skin.Value); + + if (IncludePortalSkins) + { + // load portal skins + var portalController = new PortalController(); + var portal = portalController.GetPortal(PortalId); + + foreach (var skin in SkinController.GetSkins(portal, skinRoot, SkinScope.Site)) + { + skins.Add(skin.Key, skin.Value); + } + } + return skins; + } + + protected override WebControl CreateControlInternal(Control container) + { + var panel = new Panel(); + + container.Controls.Add(panel); + + var skinLabel = new Label { Text = LocalizeString("Skin") }; + skinLabel.CssClass += "dnnFormSkinLabel"; + panel.Controls.Add(skinLabel); + + //_skinCombo = new DropDownList { ID = ID + "_SkinComboBox" }; + _skinCombo = new DnnComboBox { ID = ID + "_SkinComboBox" }; + _skinCombo.CssClass += "dnnFormSkinInput"; + _skinCombo.SelectedIndexChanged += SkinIndexChanged; + panel.Controls.Add(_skinCombo); + + DnnFormComboBoxItem.BindListInternal(_skinCombo, _skinValue, GetSkins(SkinController.RootSkin), "Key", "Value"); + + var containerLabel = new Label { Text = LocalizeString("Container") }; + containerLabel.CssClass += "dnnFormSkinLabel"; + panel.Controls.Add(containerLabel); + + //_containerCombo = new DropDownList { ID = ID + "_ContainerComboBox" }; + _containerCombo = new DnnComboBox { ID = ID + "_ContainerComboBox" }; + _containerCombo.CssClass += "dnnFormSkinInput"; + _containerCombo.SelectedIndexChanged += ContainerIndexChanged; + panel.Controls.Add(_containerCombo); + + DnnFormComboBoxItem.BindListInternal(_containerCombo, _containerValue, GetSkins(SkinController.RootContainer), "Key", "Value"); + + return panel; + } + + protected override void DataBindInternal() + { + DataBindInternal(SkinDataField, ref _skinValue); + + DataBindInternal(ContainerDataField, ref _containerValue); + + Value = new Pair {First = _skinValue, Second = _containerValue}; + } + + protected override void LoadControlState(object state) + { + base.LoadControlState(state); + var pair = Value as Pair; + if (pair != null) + { + _skinValue = pair.First; + _containerValue = pair.Second; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTab.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTab.cs new file mode 100644 index 00000000000..ec93219d656 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTab.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.ComponentModel; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnFormTab : WebControl, INamingContainer + { + public DnnFormTab() + { + Sections = new List(); + Items = new List(); + } + + public bool IncludeExpandAll { get; set; } + + internal string ExpandAllScript { get; set; } + + [Category("Behavior"), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public List Items { get; private set; } + + [Category("Behavior"), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public List Sections { get; private set; } + + public string ResourceKey { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTabStrip.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTabStrip.cs new file mode 100644 index 00000000000..8506740ed52 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTabStrip.cs @@ -0,0 +1,51 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormTabStrip : ListControl + { + + protected override void Render(HtmlTextWriter writer) + { + writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass); + writer.RenderBeginTag(HtmlTextWriterTag.Ul); + + foreach (ListItem item in Items) + { + writer.RenderBeginTag(HtmlTextWriterTag.Li); + + writer.AddAttribute(HtmlTextWriterAttribute.Href, item.Value); + writer.RenderBeginTag(HtmlTextWriterTag.A); + writer.Write(item.Text); + + writer.RenderEndTag(); + + writer.RenderEndTag(); + } + + writer.RenderEndTag(); + } + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTemplateItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTemplateItem.cs new file mode 100644 index 00000000000..2b282f61148 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTemplateItem.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; +using System.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnFormTemplateItem : DnnFormItemBase + { + [Browsable(false), DefaultValue(null), Description("The Item Template."), TemplateInstance(TemplateInstance.Single), PersistenceMode(PersistenceMode.InnerProperty), + TemplateContainer(typeof (DnnFormEmptyTemplate))] + public ITemplate ItemTemplate { get; set; } + + protected override void CreateControlHierarchy() + { + CssClass += " dnnFormItem"; + CssClass += (FormMode == DnnFormMode.Long) ? " dnnFormLong" : " dnnFormShort"; + + var template = new DnnFormEmptyTemplate(); + ItemTemplate.InstantiateIn(template); + Controls.Add(template); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTextBoxItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTextBoxItem.cs new file mode 100644 index 00000000000..f79200daf10 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormTextBoxItem.cs @@ -0,0 +1,95 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormTextBoxItem : DnnFormItemBase + { + private TextBox _textBox; + + public AutoCompleteType AutoCompleteType { get; set; } + + public int Columns { get; set; } + + public int Rows { get; set; } + + public string TextBoxCssClass + { + get + { + return ViewState.GetValue("TextBoxCssClass", string.Empty); + } + set + { + ViewState.SetValue("TextBoxCssClass", value, string.Empty); + } + } + + public TextBoxMode TextMode { get; set; } + + private void TextChanged(object sender, EventArgs e) + { + UpdateDataSource(Value, _textBox.Text, DataField); + } + + protected override WebControl CreateControlInternal(Control container) + { + + _textBox = new TextBox { ID = ID + "_TextBox" }; + + _textBox.Rows = Rows; + _textBox.Columns = Columns; + _textBox.TextMode = TextMode; + _textBox.CssClass = TextBoxCssClass; + _textBox.AutoCompleteType = AutoCompleteType; + _textBox.TextChanged += TextChanged; + + //Load from ControlState + _textBox.Text = Convert.ToString(Value); + + container.Controls.Add(_textBox); + + return _textBox; + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + if (TextMode == TextBoxMode.Password) + { + _textBox.Attributes.Add("value", Convert.ToString(Value)); + } + } + + } + +} + diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormToggleButtonItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormToggleButtonItem.cs new file mode 100644 index 00000000000..3f9741c61c9 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnFormToggleButtonItem.cs @@ -0,0 +1,111 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnFormToggleButtonItem : DnnFormItemBase + { + #region CheckBoxMode enum + + public enum CheckBoxMode + { + TrueFalse = 0, + YN = 1, + YesNo = 2 + } + + #endregion + + //private DnnRadButton _checkBox; + private CheckBox _checkBox; + + public DnnFormToggleButtonItem() + { + Mode = CheckBoxMode.TrueFalse; + } + + public CheckBoxMode Mode { get; set; } + + private void CheckedChanged(object sender, EventArgs e) + { + string newValue; + switch (Mode) + { + case CheckBoxMode.YN: + newValue = (_checkBox.Checked) ? "Y" : "N"; + break; + case CheckBoxMode.YesNo: + newValue = (_checkBox.Checked) ? "Yes" : "No"; + break; + default: + newValue = (_checkBox.Checked) ? "true" : "false"; + break; + } + UpdateDataSource(Value, newValue, DataField); + } + + protected override WebControl CreateControlInternal(Control container) + { + //_checkBox = new DnnRadButton {ID = ID + "_CheckBox", ButtonType = RadButtonType.ToggleButton, ToggleType = ButtonToggleType.CheckBox, AutoPostBack = false}; + _checkBox = new CheckBox{ ID = ID + "_CheckBox", AutoPostBack = false }; + + _checkBox.CheckedChanged += CheckedChanged; + container.Controls.Add(_checkBox); + + //Load from ControlState + if (!_checkBox.Page.IsPostBack) + { + } + switch (Mode) + { + case CheckBoxMode.YN: + case CheckBoxMode.YesNo: + var stringValue = Value as string; + if (stringValue != null) + { + _checkBox.Checked = stringValue.ToUpperInvariant().StartsWith("Y"); + } + break; + default: + _checkBox.Checked = Convert.ToBoolean(Value); + break; + } + + return _checkBox; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + FormMode = DnnFormMode.Short; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGenericHiddenField.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGenericHiddenField.cs new file mode 100644 index 00000000000..64f3b0c219d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGenericHiddenField.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Specialized; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; + + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGenericHiddenField : HiddenField where T : class, new() + { + + private T _typedValue = null; + + private bool _isValueSerialized = false; + public T TypedValue + { + get + { + return _typedValue; + } + set + { + _typedValue = value; + _isValueSerialized = false; + } + } + + public T TypedValueOrDefault + { + get + { + return TypedValue ?? (TypedValue = new T()); + } + } + + public bool HasValue + { + get { return _typedValue != null; } + } + + protected override object SaveViewState() + { + // The _typedValue can be a composite class. To ensure that all the chnaged properties of + // this class are serialized we need to call the SerializeValue method. + SerializeValue(); + return base.SaveViewState(); + } + + protected override void LoadViewState(object savedState) + { + base.LoadViewState(savedState); + SetTypedValue(); + } + + protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection) + { + var stateChanged = base.LoadPostData(postDataKey, postCollection); + if (stateChanged) + { + SetTypedValue(); + } + return stateChanged; + } + + private void SetTypedValue() + { + _typedValue = string.IsNullOrEmpty(Value) ? null : Json.Deserialize(Value); + } + + private void EnsureValue() + { + if (!_isValueSerialized) + { + SerializeValue(); + } + } + + private void SerializeValue() + { + Value = _typedValue == null ? string.Empty : Json.Serialize(_typedValue); + _isValueSerialized = true; + } + + protected override void TrackViewState() + { + // The _typedValue can be a composite class. To ensure that all the chnaged properties of + // this class are serialized we need to call the SerializeValue method. + SerializeValue(); + base.TrackViewState(); + } + + public override void RenderControl(HtmlTextWriter writer) + { + EnsureValue(); + base.RenderControl(writer); + } + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGrid.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGrid.cs new file mode 100644 index 00000000000..1e10aef13ad --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGrid.cs @@ -0,0 +1,84 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using DotNetNuke.Framework; + +#endregion + +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGrid : RadGrid + { + + #region public properties + + public int ScreenRowNumber { get; set; } + + public int RowHeight { get; set; } + + #endregion + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + base.EnableEmbeddedBaseStylesheet = false; + Utilities.ApplySkin(this); + jQuery.RegisterDnnJQueryPlugins(this.Page); + if (string.IsNullOrEmpty(ClientSettings.ClientEvents.OnGridCreated)) + { + ClientSettings.ClientEvents.OnGridCreated = "$.dnnGridCreated"; + } + + this.PreRender += new EventHandler(DnnGrid_PreRender); + } + + void DnnGrid_PreRender(object sender, EventArgs e) + { + var items = this.MasterTableView.Items; + if (ScreenRowNumber == 0) + ScreenRowNumber = 15; + + if (items.Count > ScreenRowNumber) + { + // need scroll + this.ClientSettings.Scrolling.AllowScroll = true; + this.ClientSettings.Scrolling.UseStaticHeaders = true; + + if(RowHeight == 0) + RowHeight = 25; + + this.ClientSettings.Scrolling.ScrollHeight = RowHeight * ScreenRowNumber; + } + else + { + this.ClientSettings.Scrolling.AllowScroll = false; + } + + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridAttachmentColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridAttachmentColumn.cs new file mode 100644 index 00000000000..7f1feced767 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridAttachmentColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridGroupSplitterColumn : GridGroupSplitterColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridGroupSplitterColumn dnnGridColumn = new DnnGridGroupSplitterColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBinaryImageColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBinaryImageColumn.cs new file mode 100644 index 00000000000..64c3db38f95 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBinaryImageColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridBinaryImageColumn : GridBinaryImageColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridBinaryImageColumn dnnGridColumn = new DnnGridBinaryImageColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBoundColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBoundColumn.cs new file mode 100644 index 00000000000..143182fa59b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridBoundColumn.cs @@ -0,0 +1,81 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridBoundColumn : GridBoundColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridBoundColumn dnnGridColumn = new DnnGridBoundColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + GridHeaderItem headerItem = inItem as GridHeaderItem; + string columnName = DataField; + if (!Owner.AllowSorting) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + else + { + LinkButton button = (LinkButton) headerItem[columnName].Controls[0]; + button.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridButtonColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridButtonColumn.cs new file mode 100644 index 00000000000..fa30101e44f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridButtonColumn.cs @@ -0,0 +1,110 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridButtonColumn : GridButtonColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridButtonColumn dnnGridColumn = new DnnGridButtonColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Icon Key to obtain ImageURL + /// + /// A String + /// ----------------------------------------------------------------------------- + public string IconKey { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// The Icon Siz to obtain ImageURL + /// + /// A String + /// ----------------------------------------------------------------------------- + public string IconSize { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// The Icon Style to obtain ImageURL + /// + /// A String + /// ----------------------------------------------------------------------------- + public string IconStyle { get; set; } + + public override string ImageUrl + { + get + { + if (string.IsNullOrEmpty(base.ImageUrl)) + base.ImageUrl = Entities.Icons.IconController.IconURL(IconKey, IconSize, IconStyle); + + return base.ImageUrl; + } + set + { + base.ImageUrl = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCalculatedColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCalculatedColumn.cs new file mode 100644 index 00000000000..102608c6bb7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCalculatedColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridCalculatedColumn : GridCalculatedColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridCalculatedColumn dnnGridColumn = new DnnGridCalculatedColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCheckBoxColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCheckBoxColumn.cs new file mode 100644 index 00000000000..d976ccec893 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridCheckBoxColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridCheckBoxColumn : GridCheckBoxColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridCheckBoxColumn dnnGridColumn = new DnnGridCheckBoxColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridClientSelectColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridClientSelectColumn.cs new file mode 100644 index 00000000000..8434893ce42 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridClientSelectColumn.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridClientSelectColumn : GridClientSelectColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + var dnnGridColumn = new DnnGridClientSelectColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + if (! inItem.OwnerTableView.OwnerGrid.AllowMultiRowSelection) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridColumn.cs new file mode 100644 index 00000000000..ef3f15f11a2 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridColumn.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridColumn : GridColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + var dnnGridColumn = new DnnGridColumn(); + dnnGridColumn.CopyBaseProperties(this); + dnnGridColumn.setHeaderText = HeaderText; + return dnnGridColumn; + } + + private String _HeaderText; + + public override string HeaderText + { + get + { + if (String.IsNullOrEmpty(base.HeaderText)) + base.HeaderText = Localization.GetString(string.Format("{0}.Header", _HeaderText), DotNetNuke.Web.UI.Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent)); + return base.HeaderText; + } + set + { + _HeaderText = value; + base.HeaderText = ""; + } + } + + public String setHeaderText + { + set + { + base.HeaderText = value; + } + } + + + #endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDataItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDataItem.cs new file mode 100644 index 00000000000..f5c3c6f7bb1 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDataItem.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridDataItem : GridDataItem + { + public DnnGridDataItem(GridTableView ownerTableView, int itemIndex, int dataSetIndex) : base(ownerTableView, itemIndex, dataSetIndex) + { + } + + public DnnGridDataItem(GridTableView ownerTableView, int itemIndex, int dataSetIndex, GridItemType itemType) : base(ownerTableView, itemIndex, dataSetIndex, itemType) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDateTimeColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDateTimeColumn.cs new file mode 100644 index 00000000000..c6627c3fa1c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDateTimeColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridDateTimeColumn : GridDateTimeColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridDateTimeColumn dnnGridColumn = new DnnGridDateTimeColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDropDownColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDropDownColumn.cs new file mode 100644 index 00000000000..bd4051486d2 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridDropDownColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridDropDownColumn : GridDropDownColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridDropDownColumn dnnGridColumn = new DnnGridDropDownColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditColumn.cs new file mode 100644 index 00000000000..aa2fe36aeb1 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditColumn.cs @@ -0,0 +1,57 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridEditColumn : GridEditCommandColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridEditColumn dnnGridColumn = new DnnGridEditColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditFormSettings.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditFormSettings.cs new file mode 100644 index 00000000000..aadbf0398d4 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridEditFormSettings.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridEditFormSettings : GridEditFormSettings + { + public DnnGridEditFormSettings(DnnGridTableView owner) : base(owner) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridExpandColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridExpandColumn.cs new file mode 100644 index 00000000000..701cabb6582 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridExpandColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridExpandColumn : GridColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridExpandColumn dnnGridColumn = new DnnGridExpandColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridFooterItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridFooterItem.cs new file mode 100644 index 00000000000..ca43a05dd54 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridFooterItem.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridFooterItem : GridFooterItem + { + public DnnGridFooterItem(GridTableView ownerTableView, int itemIndex, int dataSetIndex) : base(ownerTableView, itemIndex, dataSetIndex) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridGroupSplitterColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridGroupSplitterColumn.cs new file mode 100644 index 00000000000..a2a01a8751b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridGroupSplitterColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridAttachmentColumn : GridAttachmentColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridAttachmentColumn dnnGridColumn = new DnnGridAttachmentColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHTMLEditorColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHTMLEditorColumn.cs new file mode 100644 index 00000000000..170d0cc9dee --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHTMLEditorColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridHTMLEditorColumn : GridHTMLEditorColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridHTMLEditorColumn dnnGridColumn = new DnnGridHTMLEditorColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHeaderItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHeaderItem.cs new file mode 100644 index 00000000000..a6ca00e5f30 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHeaderItem.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridHeaderItem : GridHeaderItem + { + public DnnGridHeaderItem(GridTableView ownerTableView, int itemIndex, int dataSetIndex) : base(ownerTableView, itemIndex, dataSetIndex) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHyperlinkColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHyperlinkColumn.cs new file mode 100644 index 00000000000..a01daaa5fee --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridHyperlinkColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridHyperLinkColumn : GridHyperLinkColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridHyperLinkColumn dnnGridColumn = new DnnGridHyperLinkColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageColumn.cs new file mode 100644 index 00000000000..fa49d57b72a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridImageColumn : GridImageColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridImageColumn dnnGridColumn = new DnnGridImageColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumn.cs new file mode 100644 index 00000000000..20409e7123d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumn.cs @@ -0,0 +1,207 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Web; +using System.Web.UI.WebControls; +using DotNetNuke.Entities.Icons; +using DotNetNuke.UI.WebControls; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridImageCommandColumn : DnnGridTemplateColumn + { + private ImageCommandColumnEditMode _editMode = ImageCommandColumnEditMode.Command; + private bool _showImage = true; + + private string _imageURL = string.Empty; + + /// + /// Gets or sets the CommandName for the Column + /// + /// A String + public string CommandName { get; set; } + + + /// + /// EditMode for the Column + /// + /// A String + public ImageCommandColumnEditMode EditMode + { + get { return _editMode; } + set { _editMode = value; } + } + + + /// + /// Gets or sets the URL of the Image + /// + /// A String + public string ImageURL + { + get + { + if (!string.IsNullOrEmpty(_imageURL)) + { + return _imageURL; + } + + return IconController.IconURL(IconKey, IconSize, IconStyle); + } + set { _imageURL = value; } + } + + + /// + /// The Icon Key to obtain ImageURL + /// + /// A String + public string IconKey { get; set; } + + + /// + /// The Icon Siz to obtain ImageURL + /// + /// A String + public string IconSize { get; set; } + + + /// + /// The Icon Style to obtain ImageURL + /// + /// A String + public string IconStyle { get; set; } + + + /// + /// The Key Field that provides a Unique key to the data Item + /// + /// A String + public string KeyField { get; set; } + + + /// + /// Gets or sets the URL of the Link (unless DataBinding through KeyField) + /// + /// A String + /// + /// [cnurse] 02/17/2006 Created + /// + public string NavigateURL { get; set; } + + + /// + /// Gets or sets the URL Formatting string + /// + /// A String + /// + /// [cnurse] 01/06/2006 Created + /// + public string NavigateURLFormatString { get; set; } + + + /// + /// Javascript text to attach to the OnClick Event + /// + /// A String + public string OnClickJs { get; set; } + + + /// + /// Gets or sets whether an Image is displayed + /// + /// Defaults to True + /// A Boolean + public bool ShowImage + { + get { return _showImage; } + set { _showImage = value; } + } + + + /// + /// Gets or sets the Text (for Header/Footer Templates) + /// + /// A String + public string Text { get; set; } + + + /// + /// An flag that indicates whether the buttons are visible. + /// + /// A Boolean + public string VisibleField { get; set; } + + + /// + /// Creates a ImageCommandColumnTemplate + /// + /// A ImageCommandColumnTemplate + private DnnGridImageCommandColumnTemplate CreateTemplate(GridItemType type) + { + bool isDesignMode = HttpContext.Current == null; + var template = new DnnGridImageCommandColumnTemplate(type); + if (type != GridItemType.Header) + { + template.ImageURL = ImageURL; + if (!isDesignMode) + { + template.CommandName = CommandName; + template.VisibleField = VisibleField; + template.KeyField = KeyField; + } + } + template.EditMode = EditMode; + template.NavigateURL = NavigateURL; + template.NavigateURLFormatString = NavigateURLFormatString; + template.OnClickJs = OnClickJs; + template.ShowImage = ShowImage; + template.Visible = Visible; + + template.Text = type == GridItemType.Header ? HeaderText : Text; + + //Set Design Mode to True + template.DesignMode = isDesignMode; + + return template; + } + + /// + /// Initialises the Column + /// + public override void Initialize() + { + ItemTemplate = CreateTemplate(GridItemType.Item); + EditItemTemplate = CreateTemplate(GridItemType.EditItem); + HeaderTemplate = CreateTemplate(GridItemType.Header); + + if (HttpContext.Current == null) + { + HeaderStyle.Font.Names = new[] { "Tahoma, Verdana, Arial" }; + HeaderStyle.Font.Size = new FontUnit("10pt"); + HeaderStyle.Font.Bold = true; + } + ItemStyle.HorizontalAlign = HorizontalAlign.Center; + HeaderStyle.HorizontalAlign = HorizontalAlign.Center; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumnTemplate.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumnTemplate.cs new file mode 100644 index 00000000000..c38c2dbb181 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridImageCommandColumnTemplate.cs @@ -0,0 +1,323 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Specialized; +using System.Globalization; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Common.Utilities; +using DotNetNuke.UI.Utilities; +using DotNetNuke.UI.WebControls; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridImageCommandColumnTemplate : IBindableTemplate + { + private ImageCommandColumnEditMode _editMode = ImageCommandColumnEditMode.Command; + private GridItemType _itemType = GridItemType.Item; + private bool _showImage = true; + private bool _visible = true; + + public DnnGridImageCommandColumnTemplate() + : this(GridItemType.Item) + { + } + + public DnnGridImageCommandColumnTemplate(GridItemType itemType) + { + ItemType = itemType; + } + + + /// + /// Gets or sets the CommandName for the Column + /// + /// A String + /// + /// [cnurse] 02/17/2006 Created + /// + public string CommandName { get; set; } + + + /// + /// Gets or sets the Design Mode of the Column + /// + /// A Boolean + /// + /// [cnurse] 02/24/2006 Created + /// + public bool DesignMode { get; set; } + + + /// + /// Gets or sets the CommandName for the Column + /// + /// A String + public ImageCommandColumnEditMode EditMode + { + get { return _editMode; } + set { _editMode = value; } + } + + + /// + /// Gets or sets the URL of the Image + /// + /// A String + public string ImageURL { get; set; } + + + /// + /// The type of Template to Create + /// + /// A String + public GridItemType ItemType + { + get { return _itemType; } + set { _itemType = value; } + } + + + /// + /// The Key Field that provides a Unique key to the data Item + /// + /// A String + public string KeyField { get; set; } + + + /// + /// Gets or sets the URL of the Link (unless DataBinding through KeyField) + /// + /// A String + public string NavigateURL { get; set; } + + + /// + /// Gets or sets the URL Formatting string + /// + /// A String + public string NavigateURLFormatString { get; set; } + + + /// + /// Javascript text to attach to the OnClick Event + /// + /// A String + public string OnClickJs { get; set; } + + + /// + /// Gets or sets whether an Image is displayed + /// + /// Defaults to True + /// A Boolean + public bool ShowImage + { + get { return _showImage; } + set { _showImage = value; } + } + + + /// + /// Gets or sets the Text (for Header/Footer Templates) + /// + /// A String + public string Text { get; set; } + + + /// + /// An flag that indicates whether the buttons are visible (this is overridden if + /// the VisibleField is set) + /// changed + /// + /// A Boolean + public bool Visible + { + get { return _visible; } + set { _visible = value; } + } + + + /// + /// An flag that indicates whether the buttons are visible. + /// + /// A Boolean + public string VisibleField { get; set; } + + #region ITemplate Members + + /// + /// InstantiateIn instantiates the template (implementation of ITemplate) + /// + /// + /// + /// The parent container (DataGridItem) + public void InstantiateIn(Control container) + { + switch (ItemType) + { + case GridItemType.Item: + case GridItemType.AlternatingItem: + case GridItemType.SelectedItem: + case GridItemType.EditItem: + if (EditMode == ImageCommandColumnEditMode.URL) + { + var hypLink = new HyperLink {ToolTip = Text}; + if (!String.IsNullOrEmpty(ImageURL) && ShowImage) + { + var img = new Image {ImageUrl = DesignMode ? ImageURL.Replace("~/", "../../") : ImageURL}; + hypLink.Controls.Add(img); + img.ToolTip = Text; + } + else + { + hypLink.Text = Text; + } + hypLink.DataBinding += ItemDataBinding; + container.Controls.Add(hypLink); + } + else + { + if (!String.IsNullOrEmpty(ImageURL) && ShowImage) + { + var colIcon = new ImageButton + {ImageUrl = DesignMode ? ImageURL.Replace("~/", "../../") : ImageURL, ToolTip = Text}; + if (!String.IsNullOrEmpty(OnClickJs)) + { + ClientAPI.AddButtonConfirm(colIcon, OnClickJs); + } + colIcon.CommandName = CommandName; + colIcon.DataBinding += ItemDataBinding; + container.Controls.Add(colIcon); + } + if (!String.IsNullOrEmpty(Text) && !ShowImage) + { + var colLink = new LinkButton {ToolTip = Text}; + if (!String.IsNullOrEmpty(OnClickJs)) + { + ClientAPI.AddButtonConfirm(colLink, OnClickJs); + } + colLink.CommandName = CommandName; + colLink.Text = Text; + colLink.DataBinding += ItemDataBinding; + container.Controls.Add(colLink); + } + } + break; + case GridItemType.Footer: + case GridItemType.Header: + container.Controls.Add(new LiteralControl(Text)); + break; + } + } + + public IOrderedDictionary ExtractValues(Control container) + { + //do nothing we don't really support databinding + //but the telerik grid trys to databind to all template columns regardless + return new OrderedDictionary(); + } + + #endregion + + /// + /// Gets whether theButton is visible + /// + /// The parent container (DataGridItem) + private bool GetIsVisible(GridItem container) + { + if (!String.IsNullOrEmpty(VisibleField)) + { + return Convert.ToBoolean(DataBinder.Eval(container.DataItem, VisibleField)); + } + + return Visible; + } + + + /// + /// Gets the value of the key + /// + /// The parent container (DataGridItem) + private int GetValue(GridItem container) + { + int keyValue = Null.NullInteger; + if (!String.IsNullOrEmpty(KeyField)) + { + keyValue = Convert.ToInt32(DataBinder.Eval(container.DataItem, KeyField)); + } + return keyValue; + } + + + /// + /// Item_DataBinding runs when an Item of type GridItemType.Item is being data-bound + /// + /// + /// + /// The object that triggers the event + /// An EventArgs object + private void ItemDataBinding(object sender, EventArgs e) + { + GridItem container; + int keyValue; + if (EditMode == ImageCommandColumnEditMode.URL) + { + var hypLink = (HyperLink) sender; + container = (GridItem) hypLink.NamingContainer; + keyValue = GetValue(container); + if (!String.IsNullOrEmpty(NavigateURLFormatString)) + { + hypLink.NavigateUrl = string.Format(NavigateURLFormatString, keyValue); + } + else + { + hypLink.NavigateUrl = keyValue.ToString(CultureInfo.InvariantCulture); + } + } + else + { + //Bind Image Button + if (!String.IsNullOrEmpty(ImageURL) && ShowImage) + { + var colIcon = (ImageButton) sender; + container = (GridItem) colIcon.NamingContainer; + keyValue = GetValue(container); + colIcon.CommandArgument = keyValue.ToString(CultureInfo.InvariantCulture); + colIcon.Visible = GetIsVisible(container); + } + if (!String.IsNullOrEmpty(Text) && !ShowImage) + { + //Bind Link Button + var colLink = (LinkButton) sender; + container = (GridItem) colLink.NamingContainer; + keyValue = GetValue(container); + colLink.CommandArgument = keyValue.ToString(CultureInfo.InvariantCulture); + colLink.Visible = GetIsVisible(container); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItem.cs new file mode 100644 index 00000000000..6ba04cf7e2c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItem.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridItem : GridItem + { + public DnnGridItem(GridTableView ownerTableView, int itemIndex, int dataSetIndex, GridItemType itemType) : base(ownerTableView, itemIndex, dataSetIndex, itemType) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventArgs.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventArgs.cs new file mode 100644 index 00000000000..36e319f1744 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventArgs.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridItemSelectedEventArgs : EventArgs + { + private readonly GridItemCollection _SelectedItems; + + #region "Constructors" + + public DnnGridItemSelectedEventArgs(GridItemCollection selectedItems) + { + _SelectedItems = selectedItems; + } + + #endregion + + #region "Public Properties" + + public GridItemCollection SelectedItems + { + get + { + return _SelectedItems; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventHandler.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventHandler.cs new file mode 100644 index 00000000000..5ff7559c8b2 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridItemSelectedEventHandler.cs @@ -0,0 +1,24 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.UI.WebControls +{ + public delegate void DnnGridItemSelectedEventHandler(object sender, DnnGridItemSelectedEventArgs e); +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridMaskedColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridMaskedColumn.cs new file mode 100644 index 00000000000..e03af42c2da --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridMaskedColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridMaskedColumn : GridMaskedColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridMaskedColumn dnnGridColumn = new DnnGridMaskedColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridNumericColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridNumericColumn.cs new file mode 100644 index 00000000000..48ee56935be --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridNumericColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridNumericColumn : GridNumericColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridNumericColumn dnnGridColumn = new DnnGridNumericColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRatingColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRatingColumn.cs new file mode 100644 index 00000000000..046cd0775ce --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRatingColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridRatingColumn : GridRatingColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridRatingColumn dnnGridColumn = new DnnGridRatingColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRowIndicatorColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRowIndicatorColumn.cs new file mode 100644 index 00000000000..bdc47e292cc --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridRowIndicatorColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridRowIndicatorColumn : GridRowIndicatorColumn + { + #region Public Properties + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region Public Methods + + public override GridColumn Clone() + { + DnnGridRowIndicatorColumn dnnGridColumn = new DnnGridRowIndicatorColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTableView.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTableView.cs new file mode 100644 index 00000000000..7d5db57167f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTableView.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridTableView : GridTableView + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTemplateColumn.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTemplateColumn.cs new file mode 100644 index 00000000000..2977d4c5ec5 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnGridTemplateColumn.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnGridTemplateColumn : GridTemplateColumn + { + #region "Public Properties" + + public string LocalResourceFile + { + get + { + return Utilities.GetLocalResourceFile(Owner.OwnerGrid.Parent); + } + } + + #endregion + + #region "Public Methods" + + public override GridColumn Clone() + { + DnnGridTemplateColumn dnnGridColumn = new DnnGridTemplateColumn(); + + //you should override CopyBaseProperties if you have some column specific properties + dnnGridColumn.CopyBaseProperties(this); + + return dnnGridColumn; + } + + public override void InitializeCell(TableCell cell, int columnIndex, GridItem inItem) + { + base.InitializeCell(cell, columnIndex, inItem); + if (inItem is GridHeaderItem && HeaderTemplate == null && !String.IsNullOrEmpty(HeaderText)) + { + cell.Text = Localization.GetString(string.Format("{0}.Header", HeaderText), LocalResourceFile); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImage.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImage.cs new file mode 100644 index 00000000000..8f16e1dc5e7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImage.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnImage : Image + { + + #region Public Properties + + public string IconKey { get; set; } + public string IconSize { get; set; } + public string IconStyle { get; set; } + + #endregion + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + if (string.IsNullOrEmpty(ImageUrl)) + ImageUrl = Entities.Icons.IconController.IconURL(IconKey, IconSize, IconStyle); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageButton.cs new file mode 100644 index 00000000000..ec8e4d75d8a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageButton.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnImageButton : ImageButton + { + + #region Public Properties + + public string IconKey { get; set; } + public string IconSize { get; set; } + public string IconStyle { get; set; } + + #endregion + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + if (string.IsNullOrEmpty(ImageUrl)) + ImageUrl = Entities.Icons.IconController.IconURL(IconKey, IconSize, IconStyle); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageEditControl.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageEditControl.cs new file mode 100644 index 00000000000..8d5298579dc --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnImageEditControl.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnImageEditControl : DnnFileEditControl + { + public DnnImageEditControl() + { + FileFilter = "jpg,jpeg,gif,png"; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnInputManager.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnInputManager.cs new file mode 100644 index 00000000000..fc7409a7667 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnInputManager.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnInputManager : RadInputManager + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLabel.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLabel.cs new file mode 100644 index 00000000000..fe6a56a9da7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLabel.cs @@ -0,0 +1,105 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnLabel : Label, ILocalizable + { + + private bool _localize = true; + + #region Constructors + + public DnnLabel() + { + CssClass = "dnnFormLabel"; + } + + #endregion + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + #endregion + + #region ILocalizable Implementation + + public bool Localize + { + get + { + return !DesignMode && _localize; + } + set + { + _localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if (Localize) + { + if (!string.IsNullOrEmpty(ToolTip)) + { + ToolTip = Localization.GetString(ToolTip, LocalResourceFile); + } + + if (!string.IsNullOrEmpty(Text)) + { + var unLocalized = Text; + + Text = Localization.GetString(unLocalized, LocalResourceFile); + + if (string.IsNullOrEmpty(ToolTip)) + { + ToolTip = Localization.GetString(unLocalized + ".ToolTip", LocalResourceFile); + } + } + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageComboBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageComboBox.cs new file mode 100644 index 00000000000..5a475a3d6a2 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageComboBox.cs @@ -0,0 +1,329 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Personalization; + +using Telerik.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnLanguageComboBox : WebControl + { + private readonly string _viewTypePersonalizationKey; + private DnnComboBox _englishCombo; + private LanguagesListType _languagesListType = LanguagesListType.Enabled; + private RadioButtonList _modeRadioButtonList; + private DnnComboBox _nativeCombo; + + private string _originalValue; + + protected override HtmlTextWriterTag TagKey + { + get + { + return HtmlTextWriterTag.Div; + } + } + + #region "Public Events" + + public event EventHandler ItemChanged; + public event EventHandler ModeChanged; + + #endregion + + #region "Constructor" + + public DnnLanguageComboBox() + { + AutoPostBack = Null.NullBoolean; + CausesValidation = Null.NullBoolean; + ShowFlag = true; + ShowModeButtons = true; + HideLanguagesList = new Dictionary(); + FlagImageUrlFormatString = "~/images/Flags/{0}.gif"; + _viewTypePersonalizationKey = "ViewType" + PortalId; + } + + #endregion + + #region "Public Properties" + + private string DisplayMode + { + get + { + string displayMode = Convert.ToString(Personalization.GetProfile("LanguageDisplayMode", _viewTypePersonalizationKey)); + if (string.IsNullOrEmpty(displayMode)) + { + displayMode = "NATIVE"; + } + return displayMode; + } + } + + public string FlagImageUrlFormatString { get; set; } + + public Dictionary HideLanguagesList { get; set; } + + public bool IncludeNoneSpecified { get; set; } + + public LanguagesListType LanguagesListType + { + get + { + return _languagesListType; + } + set + { + _languagesListType = value; + } + } + + public int PortalId { get; set; } + + public string SelectedValue + { + get + { + string selectedValue = DisplayMode.ToUpperInvariant() == "NATIVE" ? _nativeCombo.SelectedValue : _englishCombo.SelectedValue; + if (selectedValue == "None") + { + selectedValue = Null.NullString; + } + return selectedValue; + } + } + + public bool ShowFlag { get; set; } + + public bool ShowModeButtons { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Determines whether the List Auto Posts Back + /// + /// ----------------------------------------------------------------------------- + public bool AutoPostBack { get; set; } + + public bool CausesValidation { get; set; } + + #endregion + + #region "Private Methods" + + public void BindData(bool refresh) + { + if (refresh) + { + List cultures; + switch (LanguagesListType) + { + case LanguagesListType.Supported: + cultures = LocaleController.Instance.GetCultures(LocaleController.Instance.GetLocales(Null.NullInteger)); + break; + case LanguagesListType.Enabled: + cultures = LocaleController.Instance.GetCultures(LocaleController.Instance.GetLocales(PortalId)); + break; + default: + cultures = new List(CultureInfo.GetCultures(CultureTypes.SpecificCultures)); + break; + } + + foreach (KeyValuePair lang in HideLanguagesList) + { + string cultureCode = lang.Value.Code; + CultureInfo culture = cultures.Where(c => c.Name == cultureCode).SingleOrDefault(); + if (culture != null) + { + cultures.Remove(culture); + } + } + + _nativeCombo.DataSource = cultures.OrderBy(c => c.NativeName); + _englishCombo.DataSource = cultures.OrderBy(c => c.EnglishName); + } + + + _nativeCombo.DataBind(); + _englishCombo.DataBind(); + + if (IncludeNoneSpecified && refresh) + { + _englishCombo.Items.Insert(0, new RadComboBoxItem(Localization.GetString("System_Default", Localization.SharedResourceFile), "None")); + _nativeCombo.Items.Insert(0, new RadComboBoxItem(Localization.GetString("System_Default", Localization.SharedResourceFile), "None")); + } + } + + #endregion + + #region "Protected Methods" + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + _nativeCombo = new DnnComboBox(); + _nativeCombo.DataValueField = "Name"; + _nativeCombo.DataTextField = "NativeName"; + _nativeCombo.SelectedIndexChanged += ItemChangedInternal; + Controls.Add(_nativeCombo); + + _englishCombo = new DnnComboBox(); + _englishCombo.DataValueField = "Name"; + _englishCombo.DataTextField = "EnglishName"; + _englishCombo.SelectedIndexChanged += ItemChangedInternal; + Controls.Add(_englishCombo); + + _modeRadioButtonList = new RadioButtonList(); + _modeRadioButtonList.AutoPostBack = true; + _modeRadioButtonList.RepeatDirection = RepeatDirection.Horizontal; + _modeRadioButtonList.Items.Add(new ListItem(Localization.GetString("NativeName", Localization.GlobalResourceFile), "NATIVE")); + _modeRadioButtonList.Items.Add(new ListItem(Localization.GetString("EnglishName", Localization.GlobalResourceFile), "ENGLISH")); + _modeRadioButtonList.SelectedIndexChanged += ModeChangedInternal; + Controls.Add(_modeRadioButtonList); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + _originalValue = SelectedValue; + } + + protected virtual void OnItemChanged() + { + if (ItemChanged != null) + { + ItemChanged(this, new EventArgs()); + } + } + + protected void OnModeChanged(EventArgs e) + { + if (ModeChanged != null) + { + ModeChanged(this, e); + } + } + + + protected override void OnPreRender(EventArgs e) + { + if (DisplayMode.ToUpperInvariant() == "ENGLISH") + { + if (_englishCombo.Items.FindItemByValue(_originalValue) != null) + { + _englishCombo.Items.FindItemByValue(_originalValue).Selected = true; + } + } + else + { + if (_nativeCombo.Items.FindItemByValue(_originalValue) != null) + { + _nativeCombo.Items.FindItemByValue(_originalValue).Selected = true; + } + } + + _modeRadioButtonList.Items.FindByValue(DisplayMode).Selected = true; + + foreach (RadComboBoxItem item in _englishCombo.Items) + { + item.ImageUrl = string.Format(FlagImageUrlFormatString, item.Value); + } + foreach (RadComboBoxItem item in _nativeCombo.Items) + { + item.ImageUrl = string.Format(FlagImageUrlFormatString, item.Value); + } + + _englishCombo.AutoPostBack = AutoPostBack; + _englishCombo.CausesValidation = CausesValidation; + _englishCombo.Visible = (DisplayMode.ToUpperInvariant() == "ENGLISH"); + + _nativeCombo.AutoPostBack = AutoPostBack; + _nativeCombo.CausesValidation = CausesValidation; + _nativeCombo.Visible = (DisplayMode.ToUpperInvariant() == "NATIVE"); + + _modeRadioButtonList.Visible = ShowModeButtons; + + _englishCombo.Width = Width; + _nativeCombo.Width = Width; + + base.OnPreRender(e); + } + + #endregion + + #region "Public Methods" + + public void SetLanguage(string code) + { + if (string.IsNullOrEmpty(code)) + { + _nativeCombo.SelectedIndex = _nativeCombo.FindItemIndexByValue("None"); + _englishCombo.SelectedIndex = _englishCombo.FindItemIndexByValue("None"); + } + else + { + _nativeCombo.SelectedIndex = _nativeCombo.FindItemIndexByValue(code); + _englishCombo.SelectedIndex = _englishCombo.FindItemIndexByValue(code); + } + } + + public override void DataBind() + { + BindData(!Page.IsPostBack); + } + + #endregion + + #region "Event Handlers" + + private void ModeChangedInternal(object sender, EventArgs e) + { + Personalization.SetProfile("LanguageDisplayMode", _viewTypePersonalizationKey, _modeRadioButtonList.SelectedValue); + + //Resort + BindData(true); + + OnModeChanged(EventArgs.Empty); + } + + private void ItemChangedInternal(object sender, EventArgs e) + { + OnItemChanged(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageLabel.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageLabel.cs new file mode 100644 index 00000000000..860c09e9710 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLanguageLabel.cs @@ -0,0 +1,182 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Personalization; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnLanguageLabel : CompositeControl, ILocalizable + { + #region "Public Enums" + + #endregion + + #region "Controls" + + private Image _Flag; + + private Label _Label; + + #endregion + + private bool _Localize = true; + + #region "Public Properties" + + public CultureDropDownTypes DisplayType { get; set; } + + public string Language + { + get + { + return (string) ViewState["Language"]; + } + set + { + ViewState["Language"] = value; + } + } + + #endregion + + #region "Protected Methods" + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateChildControls overrides the Base class's method to correctly build the + /// control based on the configuration + /// + /// + /// [cnurse] 07/31/2006 created + /// + /// ----------------------------------------------------------------------------- + protected override void CreateChildControls() + { + //First clear the controls collection + Controls.Clear(); + + _Flag = new Image(); + Controls.Add(_Flag); + + Controls.Add(new LiteralControl(" ")); + + _Label = new Label(); + Controls.Add(_Label); + + //Call base class's method + + base.CreateChildControls(); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnPreRender runs just before the control is rendered + /// + /// + /// [cnurse] 07/31/2006 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + if (string.IsNullOrEmpty(Language)) + { + _Flag.ImageUrl = "~/images/Flags/none.gif"; + } + else + { + _Flag.ImageUrl = string.Format("~/images/Flags/{0}.gif", Language); + } + + if (DisplayType == 0) + { + PortalSettings _PortalSettings = PortalController.GetCurrentPortalSettings(); + string _ViewTypePersonalizationKey = "ViewType" + _PortalSettings.PortalId; + string _ViewType = Convert.ToString(Personalization.GetProfile("LanguageDisplayMode", _ViewTypePersonalizationKey)); + switch (_ViewType) + { + case "NATIVE": + DisplayType = CultureDropDownTypes.NativeName; + break; + case "ENGLISH": + DisplayType = CultureDropDownTypes.EnglishName; + break; + default: + DisplayType = CultureDropDownTypes.DisplayName; + break; + } + } + + string localeName = null; + if (string.IsNullOrEmpty(Language)) + { + localeName = Localization.GetString("NeutralCulture", Localization.GlobalResourceFile); + } + else + { + localeName = Localization.GetLocaleName(Language, DisplayType); + } + _Label.Text = localeName; + _Flag.AlternateText = localeName; + } + + #endregion + + #region "ILocalizable Implementation" + + public bool Localize + { + get + { + return _Localize; + } + set + { + _Localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + } + + #endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBox.cs new file mode 100644 index 00000000000..1204dcff348 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBox.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnListBox : RadListBox + { + + //public DnnListBox() + //{ + // Utilities.ApplySkin(this); + //} + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBoxItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBoxItem.cs new file mode 100644 index 00000000000..3fa130d7062 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListBoxItem.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnListBoxItem : RadListBoxItem + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListView.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListView.cs new file mode 100644 index 00000000000..acd01f178c3 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListView.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnListView : RadListView + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItem.cs new file mode 100644 index 00000000000..655115f3441 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItem.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnListViewItem : RadListViewItem + { + public DnnListViewItem(RadListViewItemType itemType, RadListView ownerView) : base(itemType, ownerView) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItemDragHandle.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItemDragHandle.cs new file mode 100644 index 00000000000..4762c5c97f7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnListViewItemDragHandle.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnListViewItemDragHandle : RadListViewItemDragHandle + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLiteral.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLiteral.cs new file mode 100644 index 00000000000..323b6bda02b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnLiteral.cs @@ -0,0 +1,82 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnLiteral : Literal, ILocalizable + { + private bool _Localize = true; + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + #endregion + + #region "ILocalizable Implementation" + + public bool Localize + { + get + { + return _Localize; + } + set + { + _Localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((Localize)) + { + if ((!string.IsNullOrEmpty(Text))) + { + Text = Localization.GetString(Text, LocalResourceFile); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMaskedTextBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMaskedTextBox.cs new file mode 100644 index 00000000000..d7f7d64650c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMaskedTextBox.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnMaskedTextBox : RadMaskedTextBox + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMemberListControl.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMemberListControl.cs new file mode 100644 index 00000000000..25ec5ef1042 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMemberListControl.cs @@ -0,0 +1,221 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + /// + /// This control is used for displaying a template based list of users based upon various filter and sorting capabilities. + /// + [ToolboxData("<{0}:DnnMemberListControl runat=\"server\">")] + public class DnnMemberListControl : WebControl + { + #region Private Variables + + private UserInfo _currentUser; + private RelationshipController _relationshipController; + + #endregion + + #region Properties + + #region Layout Properties + + /// + /// Gets or sets the template for displaying the header section of a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string HeaderTemplate { get; set; } + + /// + /// Gets or sets the template for the row header. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string RowHeaderTemplate { get; set; } + + /// + /// Gets or sets the template for displaying an item in a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string ItemTemplate { get; set; } + + /// + /// Gets or sets the template for the row footer. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string RowFooterTemplate { get; set; } + + /// + /// Gets or sets the template for displaying the alternating row headers in a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string AlternatingRowHeaderTemplate { get; set; } + + /// + /// Gets or sets the template for displaying the alternating items in a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string AlternatingItemTemplate { get; set; } + + /// + /// Gets or sets the template for displaying the alternating row footers in a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string AlternatingRowFooterTemplate { get; set; } + + /// + /// Gets or sets the template for displaying the footer section of a DnnMemberListControl object. + /// + [DefaultValue(""), PersistenceMode(PersistenceMode.InnerProperty)] + public string FooterTemplate { get; set; } + + #endregion + + #region Filter Properties + + /// + /// Gets or sets the index of the currently displayed page. + /// + [DefaultValue(1)] + public int PageIndex { get; set; } + + /// + /// Gets or sets the number of records to display on a page in a DnnMemberListControl object. + /// + [DefaultValue(10)] + public int PageSize { get; set; } + + /// + /// Gets or sets the number of items displayed on each row. + /// + [DefaultValue(1)] + public int RowSize { get; set; } + + /// + /// Sets the property value to sort by. + /// + [DefaultValue("UserId")] + public string SortBy { get; set; } + + /// + /// Gets or sets the sort direction + /// + [DefaultValue(true)] + public bool SortAscending { get; set; } + + /// + /// Gets or sets the collection of filters to apply when getting the list of members. + /// + /// + /// Posible keys are: RoleId, RelationshipTypeId, UserId, Profile:PropertyName, FirstName, LastName, DisplayName, Username, Email. + /// + public IDictionary Filters { get; set; } + + #endregion + + #endregion + + #region Event Handlers + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + _currentUser = UserController.GetCurrentUserInfo(); + _relationshipController = new RelationshipController(); + } + + protected override void Render(HtmlTextWriter writer) + { + if (ItemTemplate == "") return; + + writer.Write(HeaderTemplate); + + // Filters + if (Filters == null) Filters = new Dictionary(); + var additionalFilters = new Dictionary(); + additionalFilters.Add("Records", PageSize.ToString()); + additionalFilters.Add("PageIndex", PageIndex.ToString()); + additionalFilters.Add("Rowsize", RowSize.ToString()); + additionalFilters.Add("SortBy", SortBy); + additionalFilters.Add("SortAscending", SortAscending.ToString()); + + // Currently Not Used by the SPROC + var filterUser = Filters.ContainsKey("UserId") && Filters["UserId"] != null ? new UserInfo() { UserID = int.Parse(Filters["UserId"]) } : new UserInfo() { PortalID = _currentUser.PortalID }; + var role = Filters.ContainsKey("RoleId") && Filters["RoleId"] != null ? new UserRoleInfo() { RoleID = int.Parse(Filters["RoleId"]) } : null; + var relationship = Filters.ContainsKey("RelationshipTypeId") && Filters["RelationshipTypeId"] != null ? new RelationshipType() { RelationshipTypeId = int.Parse(Filters["RelationshipTypeId"]) } : null; + + foreach (var filter in Filters.Where(filter => !additionalFilters.ContainsKey(filter.Key))) + { + additionalFilters.Add(filter.Key, filter.Value); + } + + var row = 0; + var users = new DataTable(); + + //users.Load(_relationshipController.GetUsersAdvancedSearch(_currentUser, filterUser, role, relationship, Filters, additionalFilters)); + + if (users.Rows.Count > 0) + { + foreach (DataRow user in users.Rows) + { + //Row Header + writer.Write(string.IsNullOrEmpty(AlternatingRowHeaderTemplate) || row%2 == 0 ? RowHeaderTemplate : AlternatingRowHeaderTemplate); + + var tokenReplace = new TokenReplace(); + var tokenKeyValues = new Dictionary(); + + foreach (var col in user.Table.Columns.Cast().Where(col => !tokenKeyValues.ContainsKey(col.ColumnName))) + { + tokenKeyValues.Add(col.ColumnName, user[col.ColumnName].ToString()); + } + + var listItem = string.IsNullOrEmpty(AlternatingItemTemplate) || row%2 == 0 ? ItemTemplate : AlternatingItemTemplate; + listItem = tokenReplace.ReplaceEnvironmentTokens(listItem, tokenKeyValues, "Member"); + writer.Write(listItem); + + //Row Footer + writer.Write(string.IsNullOrEmpty(AlternatingRowFooterTemplate) || row%2 == 0 ? RowFooterTemplate : AlternatingRowFooterTemplate); + + row++; + } + } + + writer.Write(FooterTemplate); + } + + #endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenu.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenu.cs new file mode 100644 index 00000000000..bca4ba20df4 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenu.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnMenu : RadMenu + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItem.cs new file mode 100644 index 00000000000..f43b0a6540a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItem.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnMenuItem : RadMenuItem + { + public DnnMenuItem() + { + } + + public DnnMenuItem(string text) : base(text) + { + } + + public DnnMenuItem(string text, string navigateUrl) : base(text, navigateUrl) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItemBinding.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItemBinding.cs new file mode 100644 index 00000000000..dbd10a97290 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMenuItemBinding.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnMenuItemBinding : RadMenuItemBinding + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnModuleComboBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnModuleComboBox.cs new file mode 100644 index 00000000000..8031c49006c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnModuleComboBox.cs @@ -0,0 +1,235 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Installer.Packages; + +using Telerik.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnModuleComboBox : WebControl + { + private const string DefaultExtensionImage = "icon_extensions_32px.png"; + + #region Public Events + + public event EventHandler ItemChanged; + + #endregion + + #region Public Properties + + public Func, bool> Filter { get; set; } + + public int ItemCount + { + get + { + return _moduleCombo.Items.Count; + } + } + + public string SelectedValue + { + get + { + return _moduleCombo.SelectedValue; + } + } + + public string RadComboBoxClientId + { + get + { + return _moduleCombo.ClientID; + } + } + + #endregion + + #region Private Methods + + private Dictionary GetPortalDesktopModules() + { + IOrderedEnumerable> portalModulesList; + if (Filter == null) + { + portalModulesList = DesktopModuleController.GetPortalDesktopModules(PortalSettings.Current.PortalId) + .Where((kvp) => kvp.Value.DesktopModule.Category == "Uncategorised" || String.IsNullOrEmpty(kvp.Value.DesktopModule.Category)) + .OrderBy(c => c.Key); + } + else + { + portalModulesList = DesktopModuleController.GetPortalDesktopModules(PortalSettings.Current.PortalId) + .Where(Filter) + .OrderBy(c => c.Key); + } + + return portalModulesList.ToDictionary(portalModule => portalModule.Value.DesktopModuleID, + portalModule => portalModule.Key); + } + + private static Dictionary GetTabModules(int tabID) + { + var tabCtrl = new TabController(); + var moduleCtrl = new ModuleController(); + var tabModules = moduleCtrl.GetTabModules(tabID); + + // Is this tab from another site? + var isRemote = tabCtrl.GetTab(tabID, Null.NullInteger, false).PortalID != PortalSettings.Current.PortalId; + + var pageModules = tabModules.Values.Where(m => !isRemote || ModuleSuportsSharing(m)).Where(m => ModulePermissionController.CanAdminModule(m) && m.IsDeleted == false).ToList(); + + return pageModules.ToDictionary(module => module.ModuleID, module => module.ModuleTitle); + } + + private static bool ModuleSuportsSharing(ModuleInfo moduleInfo) + { + switch (moduleInfo.DesktopModule.Shareable) + { + case ModuleSharing.Supported: + case ModuleSharing.Unknown: + return moduleInfo.IsShareable; + default: + return false; + } + } + + private void BindPortalDesktopModuleImages() + { + var portalDesktopModules = DesktopModuleController.GetDesktopModules(PortalSettings.Current.PortalId); + var packages = PackageController.GetPackages(PortalSettings.Current.PortalId); + + foreach (RadComboBoxItem item in _moduleCombo.Items) + { + string imageUrl = + (from pkgs in packages + join portMods in portalDesktopModules on pkgs.PackageID equals portMods.Value.PackageID + where portMods.Value.DesktopModuleID.ToString() == item.Value + select pkgs.IconFile).FirstOrDefault(); + + item.ImageUrl = String.IsNullOrEmpty(imageUrl) ? Globals.ImagePath + DefaultExtensionImage : imageUrl; + } + } + + private void BindTabModuleImages(int tabID) + { + var tabModules = new ModuleController().GetTabModules(tabID); + var portalDesktopModules = DesktopModuleController.GetDesktopModules(PortalSettings.Current.PortalId); + var moduleDefnitions = ModuleDefinitionController.GetModuleDefinitions(); + var packages = PackageController.GetPackages(PortalSettings.Current.PortalId); + + foreach (RadComboBoxItem item in _moduleCombo.Items) + { + string imageUrl = (from pkgs in packages + join portMods in portalDesktopModules on pkgs.PackageID equals portMods.Value.PackageID + join modDefs in moduleDefnitions on portMods.Value.DesktopModuleID equals modDefs.Value.DesktopModuleID + join tabMods in tabModules on modDefs.Value.DesktopModuleID equals tabMods.Value.DesktopModuleID + where tabMods.Value.ModuleID.ToString() == item.Value + select pkgs.IconFile).FirstOrDefault(); + + item.ImageUrl = String.IsNullOrEmpty(imageUrl) ? Globals.ImagePath + DefaultExtensionImage : imageUrl; + } + } + + #endregion + + #region Protected Methods + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + _moduleCombo = new DnnComboBox(); + _moduleCombo.DataValueField = "key"; + _moduleCombo.DataTextField = "value"; + Controls.Add(_moduleCombo); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + _originalValue = SelectedValue; + } + + protected virtual void OnItemChanged() + { + if (ItemChanged != null) + { + ItemChanged(this, new EventArgs()); + } + } + + protected override void OnPreRender(EventArgs e) + { + if (_moduleCombo.Items.FindItemByValue(_originalValue) != null) + { + _moduleCombo.Items.FindItemByValue(_originalValue).Selected = true; + } + + _moduleCombo.Width = Width; + base.OnPreRender(e); + } + + #endregion + + #region Public Methods + + public void BindAllPortalDesktopModules() + { + _moduleCombo.DataSource = GetPortalDesktopModules(); + _moduleCombo.DataBind(); + BindPortalDesktopModuleImages(); + } + + public void BindTabModulesByTabID(int tabID) + { + _moduleCombo.DataSource = GetTabModules(tabID); + _moduleCombo.DataBind(); + BindTabModuleImages(tabID); + } + + public void SetModule(string code) + { + _moduleCombo.SelectedIndex = _moduleCombo.FindItemIndexByValue(code); + } + + #endregion + + private DnnComboBox _moduleCombo; + private string _originalValue; + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMonthYearPicker.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMonthYearPicker.cs new file mode 100644 index 00000000000..d4e6b8e0b7f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMonthYearPicker.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + class DnnMonthYearPicker : RadMonthYearPicker + { + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMultiPage.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMultiPage.cs new file mode 100644 index 00000000000..7ffdc3c513a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnMultiPage.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnMultiPage : RadMultiPage + { + //TODO: Hide properties that we don't want to expose + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnNumericTextBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnNumericTextBox.cs new file mode 100644 index 00000000000..06f8d97f6ec --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnNumericTextBox.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnNumericTextBox : RadNumericTextBox + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageDropDownList.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageDropDownList.cs new file mode 100644 index 00000000000..16e648ea2a0 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageDropDownList.cs @@ -0,0 +1,90 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Localization; +using DotNetNuke.Web.UI.WebControls.Extensions; + +namespace DotNetNuke.Web.UI.WebControls +{ + [ToolboxData("<{0}:DnnPageDropDownList runat='server'>")] + public class DnnPageDropDownList : DnnDropDownList + { + + private readonly Lazy _controller = new Lazy(() => new TabController()); + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + SelectItemDefaultText = Localization.GetString("DropDownList.SelectWebPageDefaultText", Localization.SharedResourceFile); + Services.GetTreeMethod = "ItemListService/GetPages"; + Services.GetNodeDescendantsMethod = "ItemListService/GetPageDescendants"; + Services.SearchTreeMethod = "ItemListService/SearchPages"; + Services.GetTreeWithNodeMethod = "ItemListService/GetTreePathForPage"; + Services.ServiceRoot = "InternalServices"; + Services.SortTreeMethod = "ItemListService/SortPages"; + } + + protected override void OnPreRender(EventArgs e) + { + this.AddCssClass("page"); + if (InternalPortalId.HasValue) + { + Services.Parameters.Add("PortalId", InternalPortalId.Value.ToString(CultureInfo.InvariantCulture)); + } + base.OnPreRender(e); + } + + public int PortalId + { + get + { + if (InternalPortalId.HasValue) + { + return InternalPortalId.Value; + } + return PortalSettings.Current.ActiveTab.IsSuperTab ? -1 : PortalSettings.Current.PortalId; + } + set + { + InternalPortalId = value; + } + } + + private int? InternalPortalId + { + get + { + return ViewState.GetValue("PortalId", null); + } + set + { + ViewState.SetValue("PortalId", value, null); + } + } + + /// + /// Gets the selected Page in the control, or selects the Page in the control. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public TabInfo SelectedPage + { + get + { + var pageId = SelectedItemValueAsInt; + return (pageId == Null.NullInteger) ? null : _controller.Value.GetTab(pageId, PortalId, false); + } + set + { + SelectedItem = (value != null) ? new ListItem() { Text = value.IndentedTabName, Value = value.TabID.ToString(CultureInfo.InvariantCulture) } : null; + } + } + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageView.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageView.cs new file mode 100644 index 00000000000..8b0be5e5aaa --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPageView.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnPageView : RadPageView + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelBar.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelBar.cs new file mode 100644 index 00000000000..048d7d43a14 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelBar.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnPanelBar : RadPanelBar + { + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + Utilities.ApplySkin(this); + } + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItem.cs new file mode 100644 index 00000000000..fccb293735b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItem.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnPanelItem : RadPanelItem + { + public DnnPanelItem() + { + } + + public DnnPanelItem(string text) : base(text) + { + } + + public DnnPanelItem(string text, string navigateUrl) : base(text, navigateUrl) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItemBinding.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItemBinding.cs new file mode 100644 index 00000000000..11eecb90d4b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPanelItemBinding.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnPanelItemBinding : RadPanelItemBinding + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPaswordStrengthOptions.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPaswordStrengthOptions.cs new file mode 100644 index 00000000000..fe6ecdc8723 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPaswordStrengthOptions.cs @@ -0,0 +1,98 @@ +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users.Membership; + +namespace DotNetNuke.Web.UI.WebControls +{ + [DataContract] + public class DnnPaswordStrengthOptions + { + [DataMember(Name = "minLength")] + public int MinLength; + + [DataMember(Name = "minNumberOfSpecialChars")] + public int MinNumberOfSpecialChars; + + [DataMember(Name = "minLengthText")] + public string MinLengthText; + + [DataMember(Name = "weakText")] + public string WeakText; + + [DataMember(Name = "fairText")] + public string FairText; + + [DataMember(Name = "strongText")] + public string StrongText; + + [DataMember(Name = "weakColor")] + public string WeakColor; + + [DataMember(Name = "fairColor")] + public string FairColor; + + [DataMember(Name = "strongColor")] + public string StrongColor; + + [DataMember(Name = "labelCss")] + public string LabelCss; + + [DataMember(Name = "meterCss")] + public string MeterCss; + + [DataMember(Name = "criteriaOneUpperCaseLetterText")] + public string CriteriaOneUpperCaseLetterText; + + [DataMember(Name = "criteriaOneLowerCaseLetterText")] + public string CriteriaOneLowerCaseLetterText; + + [DataMember(Name = "criteriaSpecialCharText")] + public string CriteriaSpecialCharText; + + [DataMember(Name = "criteriaOneNumberText")] + public string CriteriaOneNumberText; + + [DataMember(Name = "criteriaAtLeastNCharsText")] + public string CriteriaAtLeastNCharsText; + + public DnnPaswordStrengthOptions() + { + // all the PasswordStrength related resources are located under the Website\App_GlobalResources\WebControls.resx + MinLengthText = Utilities.GetLocalizedString("PasswordStrengthMinLength"); + WeakText = Utilities.GetLocalizedString("PasswordStrengthWeak"); + FairText = Utilities.GetLocalizedString("PasswordStrengthFair"); ; + StrongText = Utilities.GetLocalizedString("PasswordStrengthStrong"); ; + + CriteriaOneUpperCaseLetterText = Utilities.GetLocalizedString("CriteriaOneUpperCaseLetter"); + CriteriaOneLowerCaseLetterText = Utilities.GetLocalizedString("CriteriaOneLowerCaseLetter"); + CriteriaOneNumberText = Utilities.GetLocalizedString("CriteriaOneNumber"); + CriteriaAtLeastNCharsText = Utilities.GetLocalizedString("CriteriaAtLeastNChars"); + + WeakColor = "#ed1e24"; + FairColor = "#f6d50a"; + StrongColor = "#69bd44"; + + LabelCss = "min-length-text"; + MeterCss = "meter"; + } + + /// + /// To avoid fetching data from the database in constructor, the OnSerializing method is consumed + /// + /// + [OnSerializing] + public void OnSerializing(StreamingContext context) + { + var settings = new MembershipPasswordSettings(PortalController.GetCurrentPortalSettings().PortalId); + MinLength = settings.MinPasswordLength; + CriteriaAtLeastNCharsText = string.Format(CriteriaAtLeastNCharsText, MinLength); + + MinNumberOfSpecialChars = settings.MinNonAlphanumericCharacters; + CriteriaSpecialCharText = MinNumberOfSpecialChars > 0 ? + string.Format(Utilities.GetLocalizedString("CriteriaAtLeastNSpecialChars"), MinNumberOfSpecialChars) : + Utilities.GetLocalizedString("CriteriaSpecialChar"); + } + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPortalPageDropDownList.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPortalPageDropDownList.cs new file mode 100644 index 00000000000..7d72afb8502 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnPortalPageDropDownList.cs @@ -0,0 +1,59 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Localization; +using DotNetNuke.Web.UI.WebControls.Extensions; + +namespace DotNetNuke.Web.UI.WebControls +{ + [ToolboxData("<{0}:DnnPortalPageDropDownList runat='server'>")] + public class DnnPortalPageDropDownList : DnnDropDownList + { + + private readonly Lazy _controller = new Lazy(() => new TabController()); + private readonly Lazy _portalId = new Lazy(() => PortalSettings.Current.ActiveTab.IsSuperTab ? -1 : PortalSettings.Current.PortalId); + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + SelectItemDefaultText = Localization.GetString("DropDownList.SelectWebPageDefaultText", Localization.SharedResourceFile); + Services.GetTreeMethod = "ItemListService/GetPagesInPortalGroup"; + Services.GetNodeDescendantsMethod = "ItemListService/GetPageDescendantsInPortalGroup"; + Services.SearchTreeMethod = "ItemListService/SearchPagesInPortalGroup"; + Services.GetTreeWithNodeMethod = "ItemListService/GetTreePathForPageInPortalGroup"; + Services.SortTreeMethod = "ItemListService/SortPagesInPortalGroup"; + Services.ServiceRoot = "InternalServices"; + } + + protected override void OnPreRender(EventArgs e) + { + this.AddCssClass("page"); + base.OnPreRender(e); + } + + /// + /// Gets the selected Page in the control, or selects the Page in the control. + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public TabInfo SelectedPage + { + get + { + var pageId = SelectedItemValueAsInt; + return (pageId == Null.NullInteger) ? null : _controller.Value.GetTab(pageId, _portalId.Value, false); + } + set + { + SelectedItem = (value != null) ? new ListItem() { Text = value.IndentedTabName, Value = value.TabID.ToString(CultureInfo.InvariantCulture) } : null; + } + } + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressArea.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressArea.cs new file mode 100644 index 00000000000..a21969ca928 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressArea.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnProgressArea : RadProgressArea + { + + //public DnnProgressArea() + //{ + // Utilities.ApplySkin(this); + //} + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressManager.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressManager.cs new file mode 100644 index 00000000000..454bb45648a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnProgressManager.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnProgressManager : RadProgressManager + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadButton.cs new file mode 100644 index 00000000000..a16e7ef7831 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadButton.cs @@ -0,0 +1,97 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; + +using DotNetNuke.Services.Localization; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRadButton : RadButton + { + private bool _Localize = true; + + #region Protected Methods + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + #endregion + + #region ILocalizable Implementation + + public bool Localize + { + get + { + if (DesignMode) + { + return false; + } + return _Localize; + } + set + { + _Localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((Localize)) + { + if ((!string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(ToolTip, LocalResourceFile); + } + + if ((!string.IsNullOrEmpty(Text))) + { + Text = Localization.GetString(Text, LocalResourceFile); + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(string.Format("{0}.ToolTip", Text), LocalResourceFile); + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadRibbonBar.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadRibbonBar.cs new file mode 100644 index 00000000000..0618318dfda --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadRibbonBar.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRadRibbonBar : RadRibbonBar + { + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadioButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadioButton.cs new file mode 100644 index 00000000000..291b4c59a5d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRadioButton.cs @@ -0,0 +1,101 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRadioButton : RadioButton, ILocalizable + { + private bool _Localize = true; + + #region "Constructors" + + public DnnRadioButton() + { + CssClass = "SubHead dnnLabel"; + } + + #endregion + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + #endregion + + #region "ILocalizable Implementation" + + public bool Localize + { + get + { + return _Localize; + } + set + { + _Localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((Localize)) + { + if ((!string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(ToolTip, LocalResourceFile); + } + + if ((!string.IsNullOrEmpty(Text))) + { + Text = Localization.GetString(Text, LocalResourceFile); + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(Text + ".ToolTip", LocalResourceFile); + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRating.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRating.cs new file mode 100644 index 00000000000..741b0186d7d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRating.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRating : RadRating + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRatingItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRatingItem.cs new file mode 100644 index 00000000000..e7bbae71753 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRatingItem.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRatingItem : RadRatingItem + { + public DnnRatingItem() + { + } + + public DnnRatingItem(string imageUrl) : base(imageUrl) + { + } + + public DnnRatingItem(string imageUrl, string selectedImageUrl) : base(imageUrl, selectedImageUrl) + { + } + + public DnnRatingItem(string imageUrl, string selectedImageUrl, string hoveredImageUrl) : base(imageUrl, selectedImageUrl, hoveredImageUrl) + { + } + + public DnnRatingItem(string imageUrl, string selectedImageUrl, string hoveredImageUrl, string hoveredSelectedImageUrl) + : base(imageUrl, selectedImageUrl, hoveredImageUrl, hoveredSelectedImageUrl) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBar.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBar.cs new file mode 100644 index 00000000000..7a57e9ac4d5 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBar.cs @@ -0,0 +1,126 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; +using System.Web.UI; +using System.Web.UI.WebControls; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnRibbonBar : WebControl + { + public DnnRibbonBar() : base("div") + { + CssClass = "dnnRibbon"; + Control control = this; + Utilities.ApplySkin(control, "", "RibbonBar", "RibbonBar"); + } + + [Category("Behavior"), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public DnnRibbonBarGroupCollection Groups + { + get + { + return (DnnRibbonBarGroupCollection) Controls; + } + } + + protected override void AddParsedSubObject(object obj) + { + if (obj is DnnRibbonBarGroup) + { + base.AddParsedSubObject(obj); + } + else + { + throw new NotSupportedException("DnnRibbonBarGroupCollection must contain controls of type DnnRibbonBarGroup"); + } + } + + protected override ControlCollection CreateControlCollection() + { + return new DnnRibbonBarGroupCollection(this); + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + if (Visible) + { + Utilities.ApplySkin(this, "", "RibbonBar", "RibbonBar"); + } + } + + protected override void Render(HtmlTextWriter writer) + { + if ((Groups.Count > 0)) + { + Groups[0].CssClass = Groups[0].CssClass + " " + Groups[0].CssClass.Trim() + "First"; + Groups[Groups.Count - 1].CssClass = Groups[Groups.Count - 1].CssClass + " " + Groups[Groups.Count - 1].CssClass.Trim() + "Last"; + } + + base.RenderBeginTag(writer); + + writer.AddAttribute("class", "barContent"); + writer.RenderBeginTag("div"); + + writer.AddAttribute("cellpadding", "0"); + writer.AddAttribute("cellspacing", "0"); + writer.AddAttribute("border", "0"); + writer.RenderBeginTag("table"); + writer.RenderBeginTag("tr"); + + foreach (DnnRibbonBarGroup grp in Groups) + { + if ((grp.Visible)) + { + writer.RenderBeginTag("td"); + grp.RenderControl(writer); + writer.RenderEndTag(); + } + } + //MyBase.RenderChildren(writer) + + writer.RenderEndTag(); + //tr + writer.RenderEndTag(); + //table + writer.RenderEndTag(); + //div + + writer.AddAttribute("class", "barBottomLeft"); + writer.RenderBeginTag("div"); + writer.RenderEndTag(); + + writer.AddAttribute("class", "barBottomRight"); + writer.RenderBeginTag("div"); + writer.RenderEndTag(); + + base.RenderEndTag(writer); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroup.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroup.cs new file mode 100644 index 00000000000..e9c0c649e3e --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroup.cs @@ -0,0 +1,173 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnRibbonBarGroup : WebControl + { + private bool _CheckToolVisibility = true; + private HtmlGenericControl _contentContainer; + + public DnnRibbonBarGroup() : base("div") + { + CssClass = "dnnRibbonGroup"; + } + + public override ControlCollection Controls + { + get + { + EnsureChildControls(); + return base.Controls; + } + } + + [TemplateInstance(TemplateInstance.Single)] + public virtual ITemplate Footer { get; set; } + + [TemplateInstance(TemplateInstance.Single)] + public virtual ITemplate Content { get; set; } + + public virtual bool CheckToolVisibility + { + get + { + return _CheckToolVisibility; + } + set + { + _CheckToolVisibility = value; + } + } + + protected override void CreateChildControls() + { + Controls.Clear(); + + HtmlGenericControl topLeft = new HtmlGenericControl("div"); + topLeft.Attributes.Add("class", "topLeft"); + HtmlGenericControl topRight = new HtmlGenericControl("div"); + topRight.Attributes.Add("class", "topRight"); + + HtmlGenericControl bottomLeft = new HtmlGenericControl("div"); + bottomLeft.Attributes.Add("class", "bottomLeft"); + HtmlGenericControl bottomRight = new HtmlGenericControl("div"); + bottomRight.Attributes.Add("class", "bottomRight"); + + _contentContainer = new HtmlGenericControl("div"); + _contentContainer.Attributes.Add("class", "content"); + + HtmlGenericControl footerContainer = new HtmlGenericControl("div"); + footerContainer.Attributes.Add("class", "footer"); + + Controls.Add(topLeft); + Controls.Add(topRight); + Controls.Add(_contentContainer); + Controls.Add(footerContainer); + Controls.Add(bottomLeft); + Controls.Add(bottomRight); + + if (Content != null) + { + Content.InstantiateIn(_contentContainer); + } + + if (Footer != null) + { + Footer.InstantiateIn(footerContainer); + } + } + + private bool CheckVisibility() + { + bool returnValue = true; + if ((Visible && CheckToolVisibility)) + { + //Hide group if all tools are invisible + bool foundTool = false; + ControlCollection controls = _contentContainer.Controls; + returnValue = AreChildToolsVisible(ref controls, ref foundTool); + } + return returnValue; + } + + private bool AreChildToolsVisible(ref ControlCollection children, ref bool foundTool) + { + bool returnValue = false; + + foreach (Control ctrl in children) + { + if ((ctrl is IDnnRibbonBarTool)) + { + foundTool = true; + if ((ctrl.Visible)) + { + returnValue = true; + break; + } + } + else + { + ControlCollection controls = ctrl.Controls; + if ((AreChildToolsVisible(ref controls, ref foundTool))) + { + if ((foundTool)) + { + returnValue = true; + break; + } + } + } + } + + if ((!foundTool)) + { + return true; + } + + return returnValue; + } + + public override Control FindControl(string id) + { + EnsureChildControls(); + return base.FindControl(id); + } + + public override void RenderControl(HtmlTextWriter writer) + { + if ((CheckVisibility())) + { + base.RenderBeginTag(writer); + base.RenderChildren(writer); + base.RenderEndTag(writer); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroupCollection.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroupCollection.cs new file mode 100644 index 00000000000..ecc2276e350 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarGroupCollection.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRibbonBarGroupCollection : ControlCollection + { + public DnnRibbonBarGroupCollection(Control owner) : base(owner) + { + } + + public new DnnRibbonBarGroup this[int index] + { + get + { + return (DnnRibbonBarGroup) base[index]; + } + } + + public override void Add(Control child) + { + if (child is DnnRibbonBarGroup) + { + base.Add(child); + } + else + { + throw new ArgumentException("DnnRibbonBarGroupCollection must contain controls of type DnnRibbonBarGroup"); + } + } + + public override void AddAt(int index, Control child) + { + if (child is DnnRibbonBarGroup) + { + base.AddAt(index, child); + } + else + { + throw new ArgumentException("DnnRibbonBarGroupCollection must contain controls of type DnnRibbonBarGroup"); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarTool.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarTool.cs new file mode 100644 index 00000000000..22c609895af --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRibbonBarTool.cs @@ -0,0 +1,618 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Web.UI; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Web.Client.ClientResourceManagement; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnRibbonBarTool : Control, IDnnRibbonBarTool + { + #region Properties + + private IDictionary _allTools; + private DnnTextLink _dnnLink; + private DnnTextButton _dnnLinkButton; + + public virtual RibbonBarToolInfo ToolInfo + { + get + { + if ((ViewState["ToolInfo"] == null)) + { + ViewState.Add("ToolInfo", new RibbonBarToolInfo()); + } + return (RibbonBarToolInfo) ViewState["ToolInfo"]; + } + set + { + ViewState["ToolInfo"] = value; + } + } + + public virtual string NavigateUrl + { + get + { + return Utilities.GetViewStateAsString(ViewState["NavigateUrl"], Null.NullString); + } + set + { + ViewState["NavigateUrl"] = value; + } + } + + public virtual string ToolCssClass + { + get + { + return Utilities.GetViewStateAsString(ViewState["ToolCssClass"], Null.NullString); + } + set + { + ViewState["ToolCssClass"] = value; + } + } + + public virtual string Text + { + get + { + return Utilities.GetViewStateAsString(ViewState["Text"], Null.NullString); + } + set + { + ViewState["Text"] = value; + } + } + + public virtual string ToolTip + { + get + { + return Utilities.GetViewStateAsString(ViewState["ToolTip"], Null.NullString); + } + set + { + ViewState["ToolTip"] = value; + } + } + + protected virtual DnnTextButton DnnLinkButton + { + get + { + if ((_dnnLinkButton == null)) + { + // Appending _CPCommandBtn is also assumed in the RibbonBar.ascx. If changed, one would need to change in both places. + _dnnLinkButton = new DnnTextButton {ID = ID + "_CPCommandBtn"}; + } + return _dnnLinkButton; + } + } + + protected virtual DnnTextLink DnnLink + { + get + { + if ((_dnnLink == null)) + { + _dnnLink = new DnnTextLink(); + } + return _dnnLink; + } + } + + protected virtual IDictionary AllTools + { + get + { + if (_allTools == null) + { + _allTools = new Dictionary + { + //Framework + {"PageSettings", new RibbonBarToolInfo("PageSettings", false, false, "", "", "", true)}, + {"CopyPage", new RibbonBarToolInfo("CopyPage", false, false, "", "", "", true)}, + {"DeletePage", new RibbonBarToolInfo("DeletePage", false, true, "", "", "", true)}, + {"ImportPage", new RibbonBarToolInfo("ImportPage", false, false, "", "", "", true)}, + {"ExportPage", new RibbonBarToolInfo("ExportPage", false, false, "", "", "", true)}, + {"NewPage", new RibbonBarToolInfo("NewPage", false, false, "", "", "", true)}, + {"CopyPermissionsToChildren", new RibbonBarToolInfo("CopyPermissionsToChildren", false, true, "", "", "", false)}, + {"CopyDesignToChildren", new RibbonBarToolInfo("CopyDesignToChildren", false, true, "", "", "", false)}, + {"Help", new RibbonBarToolInfo("Help", false, false, "_Blank", "", "", false)}, + //Modules On Tabs + {"Console", new RibbonBarToolInfo("Console", false, false, "", "Console", "", false)}, + {"HostConsole", new RibbonBarToolInfo("HostConsole", true, false, "", "Console", "", false)}, + {"UploadFile", new RibbonBarToolInfo("UploadFile", false, false, "", "", "WebUpload", true)}, + {"NewRole", new RibbonBarToolInfo("NewRole", false, false, "", "Security Roles", "Edit", true)}, + {"NewUser", new RibbonBarToolInfo("NewUser", false, false, "", "User Accounts", "Edit", true)}, + {"ClearCache", new RibbonBarToolInfo("ClearCache", true, true, "", "", "", false)}, + {"RecycleApp", new RibbonBarToolInfo("RecycleApp", true, true, "", "", "", false)} + }; + } + + return _allTools; + } + } + + private static PortalSettings PortalSettings + { + get + { + return PortalSettings.Current; + } + } + + public virtual string ToolName + { + get + { + return ToolInfo.ToolName; + } + set + { + if ((AllTools.ContainsKey(value))) + { + ToolInfo = AllTools[value]; + } + else + { + throw new NotSupportedException("Tool not found [" + value + "]"); + } + } + } + + #endregion + + #region Events + + protected override void CreateChildControls() + { + Controls.Clear(); + Controls.Add(DnnLinkButton); + Controls.Add(DnnLink); + } + + protected override void OnInit(EventArgs e) + { + EnsureChildControls(); + DnnLinkButton.Click += ControlPanelTool_OnClick; + } + + protected override void OnPreRender(EventArgs e) + { + ProcessTool(); + Visible = (DnnLink.Visible || DnnLinkButton.Visible); + base.OnPreRender(e); + } + + public virtual void ControlPanelTool_OnClick(object sender, EventArgs e) + { + switch (ToolInfo.ToolName) + { + case "DeletePage": + if ((HasToolPermissions("DeletePage"))) + { + string url = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Tab", "action=delete"); + Page.Response.Redirect(url, true); + } + break; + case "CopyPermissionsToChildren": + if ((HasToolPermissions("CopyPermissionsToChildren"))) + { + TabController.CopyPermissionsToChildren(PortalSettings.ActiveTab, PortalSettings.ActiveTab.TabPermissions); + Page.Response.Redirect(Page.Request.RawUrl); + } + break; + case "CopyDesignToChildren": + if ((HasToolPermissions("CopyDesignToChildren"))) + { + TabController.CopyDesignToChildren(PortalSettings.ActiveTab, PortalSettings.ActiveTab.SkinSrc, PortalSettings.ActiveTab.ContainerSrc); + Page.Response.Redirect(Page.Request.RawUrl); + } + break; + case "ClearCache": + if ((HasToolPermissions("ClearCache"))) + { + ClearCache(); + ClientResourceManager.ClearCache(); + Page.Response.Redirect(Page.Request.RawUrl); + } + break; + case "RecycleApp": + if ((HasToolPermissions("RecycleApp"))) + { + RestartApplication(); + Page.Response.Redirect(Page.Request.RawUrl); + } + break; + } + } + + #endregion + + #region Methods + + protected virtual void ProcessTool() + { + DnnLink.Visible = false; + DnnLinkButton.Visible = false; + + if ((!string.IsNullOrEmpty(ToolInfo.ToolName))) + { + if ((ToolInfo.UseButton)) + { + DnnLinkButton.Visible = HasToolPermissions(ToolInfo.ToolName); + DnnLinkButton.Enabled = EnableTool(); + DnnLinkButton.Localize = false; + + DnnLinkButton.CssClass = ToolCssClass; + DnnLinkButton.DisabledCssClass = ToolCssClass + " dnnDisabled"; + + DnnLinkButton.Text = GetText(); + DnnLinkButton.ToolTip = GetToolTip(); + } + else + { + DnnLink.Visible = HasToolPermissions(ToolInfo.ToolName); + DnnLink.Enabled = EnableTool(); + DnnLink.Localize = false; + + if ((DnnLink.Enabled)) + { + DnnLink.NavigateUrl = BuildToolUrl(); + + //can't find the page, disable it? + if ((string.IsNullOrEmpty(DnnLink.NavigateUrl))) + { + DnnLink.Enabled = false; + } + //create popup event + else if (ToolInfo.ShowAsPopUp && PortalSettings.EnablePopUps) + { + // Prevent PageSettings in a popup if SSL is enabled and enforced, which causes redirection/javascript broswer security issues. + if (ToolInfo.ToolName == "PageSettings" || ToolInfo.ToolName == "CopyPage" || ToolInfo.ToolName == "NewPage") + { + if (!(PortalSettings.SSLEnabled && PortalSettings.SSLEnforced)) + { + DnnLink.Attributes.Add("onclick", "return " + UrlUtils.PopUpUrl(DnnLink.NavigateUrl, this, PortalSettings, true, false)); + } + } + else + { + DnnLink.Attributes.Add("onclick", "return " + UrlUtils.PopUpUrl(DnnLink.NavigateUrl, this, PortalSettings, true, false)); + } + } + } + + DnnLink.CssClass = ToolCssClass; + DnnLink.DisabledCssClass = ToolCssClass + " dnnDisabled"; + + DnnLink.Text = GetText(); + DnnLink.ToolTip = GetToolTip(); + DnnLink.Target = ToolInfo.LinkWindowTarget; + } + } + } + + protected virtual bool EnableTool() + { + bool returnValue = true; + + switch (ToolInfo.ToolName) + { + case "DeletePage": + if ((TabController.IsSpecialTab(TabController.CurrentPage.TabID, PortalSettings.PortalId))) + { + returnValue = false; + } + break; + case "CopyDesignToChildren": + case "CopyPermissionsToChildren": + returnValue = ActiveTabHasChildren(); + if ((returnValue && ToolInfo.ToolName == "CopyPermissionsToChildren")) + { + if ((PortalSettings.ActiveTab.IsSuperTab)) + { + returnValue = false; + } + } + break; + } + + return returnValue; + } + + protected virtual bool HasToolPermissions(string toolName) + { + bool isHostTool = false; + if ((ToolInfo.ToolName == toolName)) + { + isHostTool = ToolInfo.IsHostTool; + } + else if ((AllTools.ContainsKey(toolName))) + { + isHostTool = AllTools[toolName].IsHostTool; + } + + if ((isHostTool && !UserController.GetCurrentUserInfo().IsSuperUser)) + { + return false; + } + + bool returnValue = true; + switch (toolName) + { + case "PageSettings": + case "CopyDesignToChildren": + case "CopyPermissionsToChildren": + returnValue = TabPermissionController.CanManagePage(); + + if ((returnValue && toolName == "CopyPermissionsToChildren")) + { + if ((!PortalSecurity.IsInRole("Administrators"))) + { + returnValue = false; + } + } + break; + case "CopyPage": + returnValue = TabPermissionController.CanCopyPage(); + break; + case "DeletePage": + returnValue = (TabPermissionController.CanDeletePage()); + break; + case "ImportPage": + returnValue = TabPermissionController.CanImportPage(); + break; + case "ExportPage": + returnValue = TabPermissionController.CanExportPage(); + break; + case "NewPage": + returnValue = TabPermissionController.CanAddPage(); + break; + case "Help": + returnValue = !string.IsNullOrEmpty(Host.HelpURL); + break; + default: + //if it has a module definition, look it up and check permissions + //if it doesn't exist, assume no permission + string friendlyName = ""; + if ((ToolInfo.ToolName == toolName)) + { + friendlyName = ToolInfo.ModuleFriendlyName; + } + else if ((AllTools.ContainsKey(toolName))) + { + friendlyName = AllTools[toolName].ModuleFriendlyName; + } + + if ((!string.IsNullOrEmpty(friendlyName))) + { + returnValue = false; + ModuleInfo moduleInfo; + + if ((isHostTool)) + { + moduleInfo = GetInstalledModule(Null.NullInteger, friendlyName); + } + else + { + moduleInfo = GetInstalledModule(PortalSettings.PortalId, friendlyName); + } + + if ((moduleInfo != null)) + { + returnValue = ModulePermissionController.CanViewModule(moduleInfo); + } + } + break; + } + + return returnValue; + } + + protected virtual string BuildToolUrl() + { + if ((ToolInfo.IsHostTool && !UserController.GetCurrentUserInfo().IsSuperUser)) + { + return "javascript:void(0);"; + } + + if ((!string.IsNullOrEmpty(NavigateUrl))) + { + return NavigateUrl; + } + + string returnValue = "javascript:void(0);"; + switch (ToolInfo.ToolName) + { + case "PageSettings": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Tab", "action=edit"); + break; + + case "CopyPage": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Tab", "action=copy"); + break; + + case "DeletePage": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Tab", "action=delete"); + break; + + case "ImportPage": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "ImportTab"); + break; + + case "ExportPage": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "ExportTab"); + break; + + case "NewPage": + returnValue = Globals.NavigateURL("Tab"); + break; + case "Help": + if (!string.IsNullOrEmpty(Host.HelpURL)) + { + var version = Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, false); + returnValue = Globals.FormatHelpUrl(Host.HelpURL, PortalSettings, "Home", version); + } + break; + case "UploadFile": + case "HostUploadFile": + returnValue = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "WebUpload"); + break; + default: + if ((!string.IsNullOrEmpty(ToolInfo.ModuleFriendlyName))) + { + var additionalParams = new List(); + returnValue = GetTabURL(additionalParams); + } + break; + } + return returnValue; + } + + protected virtual string GetText() + { + if ((string.IsNullOrEmpty(Text))) + { + return GetString(string.Format("Tool.{0}.Text", ToolInfo.ToolName)); + } + + return Text; + } + + protected virtual string GetToolTip() + { + if ((ToolInfo.ToolName == "DeletePage")) + { + if ((TabController.IsSpecialTab(TabController.CurrentPage.TabID, PortalSettings.PortalId))) + { + return GetString("Tool.DeletePage.Special.ToolTip"); + } + } + + if ((string.IsNullOrEmpty(Text))) + { + string tip = GetString(string.Format("Tool.{0}.ToolTip", ToolInfo.ToolName)); + if ((string.IsNullOrEmpty(tip))) + { + tip = GetString(string.Format("Tool.{0}.Text", ToolInfo.ToolName)); + } + return tip; + } + + return ToolTip; + } + + protected virtual string GetTabURL(List additionalParams) + { + int portalId = (ToolInfo.IsHostTool) ? Null.NullInteger : PortalSettings.PortalId; + + string strURL = string.Empty; + + if (((additionalParams == null))) + { + additionalParams = new List(); + } + + var moduleCtrl = new ModuleController(); + var moduleInfo = moduleCtrl.GetModuleByDefinition(portalId, ToolInfo.ModuleFriendlyName); + + if (((moduleInfo != null))) + { + bool isHostPage = (portalId == Null.NullInteger); + if ((!string.IsNullOrEmpty(ToolInfo.ControlKey))) + { + additionalParams.Insert(0, "mid=" + moduleInfo.ModuleID); + if (ToolInfo.ShowAsPopUp && PortalSettings.EnablePopUps) + { + additionalParams.Add("popUp=true"); + } + } + + string currentCulture = Thread.CurrentThread.CurrentCulture.Name; + strURL = Globals.NavigateURL(moduleInfo.TabID, isHostPage, PortalSettings, ToolInfo.ControlKey, currentCulture, additionalParams.ToArray()); + } + + return strURL; + } + + protected virtual bool ActiveTabHasChildren() + { + var children = TabController.GetTabsByParent(PortalSettings.ActiveTab.TabID, PortalSettings.ActiveTab.PortalID); + + if (((children == null) || children.Count < 1)) + { + return false; + } + + return true; + } + + protected virtual string GetString(string key) + { + return Utilities.GetLocalizedStringFromParent(key, this); + } + + private static ModuleInfo GetInstalledModule(int portalID, string friendlyName) + { + var moduleCtrl = new ModuleController(); + return moduleCtrl.GetModuleByDefinition(portalID, friendlyName); + } + + protected virtual void ClearCache() + { + DataCache.ClearCache(); + } + + protected virtual void RestartApplication() + { + var objEv = new EventLogController(); + var objEventLogInfo = new LogInfo { BypassBuffering = true, LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString() }; + objEventLogInfo.AddProperty("Message", GetString("UserRestart")); + objEv.AddLog(objEventLogInfo); + Config.Touch(); + } + + #endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotator.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotator.cs new file mode 100644 index 00000000000..97939b8b767 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotator.cs @@ -0,0 +1,32 @@ +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + + +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRotator : RadRotator + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotatorItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotatorItem.cs new file mode 100644 index 00000000000..cbdc674473d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnRotatorItem.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnRotatorItem : RadRotatorItem + { + public DnnRotatorItem() + { + } + + public DnnRotatorItem(object dataItem) : base(dataItem) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScheduler.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScheduler.cs new file mode 100644 index 00000000000..a30fd1664dd --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScheduler.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnScheduler : RadScheduler + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerContextMenu.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerContextMenu.cs new file mode 100644 index 00000000000..67bc9ca734e --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerContextMenu.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSchedulerContextMenu : RadSchedulerContextMenu + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceStyleMapping.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceStyleMapping.cs new file mode 100644 index 00000000000..745a1c10594 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceStyleMapping.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSchedulerResourceStyleMapping : ResourceStyleMapping + { + public DnnSchedulerResourceStyleMapping() + { + } + + public DnnSchedulerResourceStyleMapping(string type, string key, string applyCssClass) : base(type, key, applyCssClass) + { + } + + public DnnSchedulerResourceStyleMapping(string type, string key, string text, string applyCssClass) : base(type, key, text, applyCssClass) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceType.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceType.cs new file mode 100644 index 00000000000..6f2f9adac30 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSchedulerResourceType.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSchedulerResourceType : ResourceType + { + public DnnSchedulerResourceType() + { + } + + public DnnSchedulerResourceType(string resourceTypeName) : base(resourceTypeName) + { + } + + public DnnSchedulerResourceType(string resourceTypeName, bool allowMultipleResourceValues) : base(resourceTypeName, allowMultipleResourceValues) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptBlock.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptBlock.cs new file mode 100644 index 00000000000..08fd01b3bc3 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptBlock.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnScriptBlock : RadScriptBlock + { + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptManager.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptManager.cs new file mode 100644 index 00000000000..adfe19a6470 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnScriptManager.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using Telerik.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + class DnnScriptManager : RadScriptManager + { + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMap.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMap.cs new file mode 100644 index 00000000000..025e8d49596 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMap.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSiteMap : RadSiteMap + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapLevelSetting.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapLevelSetting.cs new file mode 100644 index 00000000000..00544bb0839 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapLevelSetting.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSiteMapLevelSetting : SiteMapLevelSetting + { + public DnnSiteMapLevelSetting() + { + } + + public DnnSiteMapLevelSetting(int level) : base(level) + { + } + + public DnnSiteMapLevelSetting(int level, SiteMapLayout layout) : base(level, layout) + { + } + + public DnnSiteMapLevelSetting(SiteMapLayout layout) : base(layout) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNode.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNode.cs new file mode 100644 index 00000000000..d566829b1bd --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNode.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSiteMapNode : RadSiteMapNode + { + public DnnSiteMapNode() + { + } + + public DnnSiteMapNode(string text, string navigateUrl) : base(text, navigateUrl) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNodeBinding.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNodeBinding.cs new file mode 100644 index 00000000000..c1d0a2563cb --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSiteMapNodeBinding.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSiteMapNodeBinding : RadSiteMapNodeBinding + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSlider.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSlider.cs new file mode 100644 index 00000000000..dec1a588d6e --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSlider.cs @@ -0,0 +1,86 @@ +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#region Usings + +using System; + +using Telerik.Web.UI; +using DotNetNuke.Services.Localization; +using DotNetNuke.Web.UI; +using System.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSlider : RadSlider, ILocalizable + { + private bool _localize = true; + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + public string ResourceKey { get; set; } + +#region ILocalizable Implementation + public bool Localize + { + get + { + if (base.DesignMode) + { + return false; + } + return _localize; + } + set + { + _localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((this.Localize) && (!(String.IsNullOrEmpty(this.ResourceKey)))) + { + if (!(String.IsNullOrEmpty(base.DecreaseText))) + { + base.DecreaseText = Utilities.GetLocalizedStringFromParent(String.Format("{0}.Decrease", this.ResourceKey), this); + } + + if (!(String.IsNullOrEmpty(base.DragText))) + { + base.DragText = Utilities.GetLocalizedStringFromParent(String.Format("{0}.Drag", this.ResourceKey), this); + } + + if (!(String.IsNullOrEmpty(base.IncreaseText))) + { + base.IncreaseText = Utilities.GetLocalizedStringFromParent(String.Format("{0}.Increase", this.ResourceKey), this); + } + } + } +#endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSliderItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSliderItem.cs new file mode 100644 index 00000000000..fd5ed7fa586 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSliderItem.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSliderItem : RadSliderItem + { + public DnnSliderItem() + { + } + + public DnnSliderItem(string text) : base(text) + { + } + + public DnnSliderItem(string text, string value) : base(text, value) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSpell.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSpell.cs new file mode 100644 index 00000000000..38040cb3a7f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSpell.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSpell : RadSpell + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitBar.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitBar.cs new file mode 100644 index 00000000000..14ec3137c6f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitBar.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSplitBar : RadSplitBar + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitPane.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitPane.cs new file mode 100644 index 00000000000..e4ba628ebbb --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitPane.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSplitPane : RadPane + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingPane.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingPane.cs new file mode 100644 index 00000000000..d49ce9bf433 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingPane.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSplitSlidingPane : RadSlidingPane + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingZone.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingZone.cs new file mode 100644 index 00000000000..14b3ddda3d7 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitSlidingZone.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSplitSlidingZone : RadSlidingZone + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitter.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitter.cs new file mode 100644 index 00000000000..2cde741bdc3 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnSplitter.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnSplitter : RadSplitter + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTab.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTab.cs new file mode 100644 index 00000000000..47985c06c7f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTab.cs @@ -0,0 +1,75 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildren(true)] + public class DnnTab : WebControl + { + public DnnTab() : base("div") + { + } + + public override ControlCollection Controls + { + get + { + EnsureChildControls(); + return base.Controls; + } + } + + [TemplateInstance(TemplateInstance.Single)] + public virtual ITemplate Header { get; set; } + + [TemplateInstance(TemplateInstance.Single)] + public virtual ITemplate Content { get; set; } + + protected override void CreateChildControls() + { + Controls.Clear(); + + if (Content != null) + { + Content.InstantiateIn(this); + } + } + + public override Control FindControl(string id) + { + EnsureChildControls(); + return base.FindControl(id); + } + + protected override void Render(HtmlTextWriter writer) + { + base.RenderBeginTag(writer); + base.RenderChildren(writer); + base.RenderEndTag(writer); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabCollection.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabCollection.cs new file mode 100644 index 00000000000..621adeb1883 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabCollection.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTabCollection : ControlCollection + { + public DnnTabCollection(Control owner) : base(owner) + { + } + + public new DnnTab this[int index] + { + get + { + return (DnnTab) base[index]; + } + } + + public override void Add(Control child) + { + if (child is DnnTab) + { + base.Add(child); + } + else + { + throw new ArgumentException("DnnTabCollection must contain controls of type DnnTab"); + } + } + + public override void AddAt(int index, Control child) + { + if (child is DnnTab) + { + base.AddAt(index, child); + } + else + { + throw new ArgumentException("DnnTabCollection must contain controls of type DnnTab"); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabPanel.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabPanel.cs new file mode 100644 index 00000000000..06c318311b3 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabPanel.cs @@ -0,0 +1,135 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using Telerik.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [ParseChildrenAttribute(true)] + public class DnnTabPanel : WebControl + { + private DnnTabCollection _Tabs; + private RadMultiPage _TelerikPages; + private RadTabStrip _TelerikTabs; + + private RadTabStrip TelerikTabs + { + get + { + if (_TelerikTabs == null) + { + _TelerikTabs = new RadTabStrip(); + } + + return _TelerikTabs; + } + } + + private RadMultiPage TelerikPages + { + get + { + if (_TelerikPages == null) + { + _TelerikPages = new RadMultiPage(); + } + + return _TelerikPages; + } + } + + public DnnTabCollection Tabs + { + get + { + if (_Tabs == null) + { + _Tabs = new DnnTabCollection(this); + } + + return _Tabs; + } + } + + protected override void OnLoad(EventArgs e) + { + base.EnsureChildControls(); + } + + protected override void CreateChildControls() + { + Controls.Clear(); + + TelerikTabs.ID = ID + "_Tabs"; + TelerikTabs.Skin = "Office2007"; + TelerikTabs.EnableEmbeddedSkins = true; + + TelerikPages.ID = ID + "_Pages"; + + TelerikTabs.MultiPageID = TelerikPages.ID; + + Controls.Add(TelerikTabs); + Controls.Add(TelerikPages); + } + + protected override void OnPreRender(EventArgs e) + { + if ((!Page.IsPostBack)) + { + TelerikTabs.SelectedIndex = 0; + TelerikPages.SelectedIndex = 0; + + int idIndex = 0; + + foreach (DnnTab t in Tabs) + { + RadTab tab = new RadTab(); + tab.TabTemplate = t.Header; + RadPageView pageView = new RadPageView(); + pageView.Controls.Add(t); + + tab.PageViewID = "PV_" + idIndex; + pageView.ID = "PV_" + idIndex; + + TelerikTabs.Tabs.Add(tab); + TelerikPages.PageViews.Add(pageView); + + idIndex = idIndex + 1; + } + } + + base.OnPreRender(e); + } + + protected override void Render(HtmlTextWriter writer) + { + base.Render(writer); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabStrip.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabStrip.cs new file mode 100644 index 00000000000..91bb785c9fb --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTabStrip.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTabStrip : RadTabStrip + { + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + Utilities.ApplySkin(this); + } + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloud.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloud.cs new file mode 100644 index 00000000000..212c733d37e --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloud.cs @@ -0,0 +1,36 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTagCloud : RadTagCloud + { + protected void OnItemDataBound(DnnTagCloudItem item) + { + base.OnItemDataBound(item); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloudItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloudItem.cs new file mode 100644 index 00000000000..2f992630041 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTagCloudItem.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTagCloudItem : RadTagCloudItem + { + public DnnTagCloudItem() + { + } + + public DnnTagCloudItem(string text) : base(text) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextBox.cs new file mode 100644 index 00000000000..c7a86cd203c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextBox.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTextBox : RadTextBox + { + + //public DnnTextBox() + //{ + // Utilities.ApplySkin(this); + //} + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextButton.cs new file mode 100644 index 00000000000..acfe5ca5551 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextButton.cs @@ -0,0 +1,167 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTextButton : LinkButton, ILocalizable + { + private bool _localize = true; + + #region "Public Properties" + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public string ConfirmMessage + { + get + { + return ViewState["ConfirmMessage"] == null ? string.Empty : (string) ViewState["ConfirmMessage"]; + } + set + { + ViewState["ConfirmMessage"] = value; + } + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public override string CssClass + { + get + { + return ViewState["CssClass"] == null ? string.Empty : (string) ViewState["CssClass"]; + } + set + { + ViewState["CssClass"] = value; + } + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public new string DisabledCssClass + { + get + { + return ViewState["DisabledCssClass"] == null ? string.Empty : (string) ViewState["DisabledCssClass"]; + } + set + { + ViewState["DisabledCssClass"] = value; + } + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public new string Text + { + get + { + return ViewState["Text"] == null ? string.Empty : (string) ViewState["Text"]; + } + set + { + ViewState["Text"] = value; + } + } + + #endregion + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + if (!Enabled && !string.IsNullOrEmpty(DisabledCssClass)) + { + CssClass = DisabledCssClass; + } + writer.AddAttribute("class", CssClass.Trim()); + base.Render(writer); + } + + #region "ILocalizable Implementation" + + public bool Localize + { + get + { + return _localize; + } + set + { + _localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((Localize)) + { + if ((!string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(ToolTip, LocalResourceFile); + } + + if ((!string.IsNullOrEmpty(Text))) + { + Text = Localization.GetString(Text, LocalResourceFile); + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(string.Format("{0}.ToolTip", Text), LocalResourceFile); + } + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Text; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextLink.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextLink.cs new file mode 100644 index 00000000000..b1ba9f6d393 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTextLink.cs @@ -0,0 +1,214 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTextLink : WebControl, ILocalizable + { + private bool _localize = true; + private HyperLink _textHyperlinkControl; + + public DnnTextLink() : base("span") + { + CssClass = "dnnTextLink"; + DisabledCssClass = "dnnTextLink disabled"; + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public string Text + { + get + { + return TextHyperlinkControl.Text; + } + set + { + TextHyperlinkControl.Text = value; + } + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public override string ToolTip + { + get + { + return TextHyperlinkControl.ToolTip; + } + set + { + TextHyperlinkControl.ToolTip = value; + } + } + + [Bindable(true)] + [Category("Behavior")] + [DefaultValue("")] + [Localizable(true)] + public string NavigateUrl + { + get + { + return TextHyperlinkControl.NavigateUrl; + } + set + { + TextHyperlinkControl.NavigateUrl = value; + } + } + + [Bindable(true)] + [Category("Behavior")] + [DefaultValue("")] + [Localizable(true)] + public string Target + { + get + { + return TextHyperlinkControl.Target; + } + set + { + TextHyperlinkControl.Target = value; + } + } + + [Bindable(true)] + [Category("Appearance")] + [DefaultValue("")] + [Localizable(true)] + public new string DisabledCssClass + { + get + { + return ViewState["DisabledCssClass"] == null ? string.Empty : (string) ViewState["DisabledCssClass"]; + } + set + { + ViewState["DisabledCssClass"] = value; + } + } + + private HyperLink TextHyperlinkControl + { + get + { + if (_textHyperlinkControl == null) + { + _textHyperlinkControl = new HyperLink(); + } + return _textHyperlinkControl; + } + } + + protected override void CreateChildControls() + { + Controls.Clear(); + Controls.Add(TextHyperlinkControl); + } + + #region "Protected Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + LocalResourceFile = Utilities.GetLocalResourceFile(this); + } + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + + if ((!Enabled)) + { + if ((!string.IsNullOrEmpty(DisabledCssClass))) + { + CssClass = DisabledCssClass; + } + NavigateUrl = "javascript:void(0);"; + } + + base.RenderBeginTag(writer); + base.RenderChildren(writer); + base.RenderEndTag(writer); + } + + #endregion + + #region "ILocalizable Implementation" + + public bool Localize + { + get + { + return _localize; + } + set + { + _localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((Localize)) + { + if ((!string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(ToolTip, LocalResourceFile); + } + + if ((!string.IsNullOrEmpty(Text))) + { + Text = Localization.GetString(Text, LocalResourceFile); + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Localization.GetString(string.Format("{0}.ToolTip", Text), LocalResourceFile); + } + + if ((string.IsNullOrEmpty(ToolTip))) + { + ToolTip = Text; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTicker.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTicker.cs new file mode 100644 index 00000000000..60820ee1ebd --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTicker.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTicker : RadTicker + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTickerItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTickerItem.cs new file mode 100644 index 00000000000..1c77e24160b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTickerItem.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTickerItem : RadTickerItem + { + public DnnTickerItem() + { + } + + public DnnTickerItem(string text) : base(text) + { + } + + public DnnTickerItem(string text, string navigateUrl) : base(text, navigateUrl) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimePicker.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimePicker.cs new file mode 100644 index 00000000000..e5e8564a047 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimePicker.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTimePicker : RadTimePicker + { + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + base.EnableEmbeddedBaseStylesheet = true; + Utilities.ApplySkin(this, string.Empty, "DatePicker"); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeView.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeView.cs new file mode 100644 index 00000000000..36985957587 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeView.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTimeView : RadTimeView + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneComboBox.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneComboBox.cs new file mode 100644 index 00000000000..1c7dfc8af4b --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneComboBox.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnTimeZoneComboBox : DropDownList + { + + protected override void OnInit(System.EventArgs e) + { + //Utilities.ApplySkin(this); + base.OnInit(e); + + this.DataTextField = "DisplayName"; + this.DataValueField = "Id"; + + this.DataSource = TimeZoneInfo.GetSystemTimeZones(); + this.DataBind(); + } + } +} + diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneEditControl.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneEditControl.cs new file mode 100644 index 00000000000..ff8978ba33c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTimeZoneEditControl.cs @@ -0,0 +1,114 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using DotNetNuke.UI.WebControls; +using System.Web.UI; +using System.Web.UI.WebControls; +using DotNetNuke.Web.UI.WebControls.Extensions; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnTimeZoneEditControl : TextEditControl + { + + + private DnnTimeZoneComboBox TimeZones; + #region "Constructors" + + public DnnTimeZoneEditControl() + { + } + + #endregion + + protected override void CreateChildControls() + { + TimeZones = new DnnTimeZoneComboBox(); + + Controls.Clear(); + Controls.Add(TimeZones); + + base.CreateChildControls(); + } + + public override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) + { + bool dataChanged = false; + string presentValue = StringValue; + string postedValue = TimeZones.SelectedValue; + if (!presentValue.Equals(postedValue)) + { + Value = postedValue; + dataChanged = true; + } + + return dataChanged; + } + + protected override void OnDataChanged(EventArgs e) + { + var args = new PropertyEditorEventArgs(Name); + args.Value = TimeZoneInfo.FindSystemTimeZoneById(StringValue); + args.OldValue = OldStringValue; + args.StringValue = StringValue; + base.OnValueChanged(args); + } + + protected override void OnInit(System.EventArgs e) + { + this.EnsureChildControls(); + base.OnInit(e); + } + + protected override void OnPreRender(System.EventArgs e) + { + base.OnPreRender(e); + + TimeZones.DataBind(StringValue); + + if ((Page != null) && this.EditMode == PropertyEditorMode.Edit) + { + this.Page.RegisterRequiresPostBack(this); + } + } + + protected override void RenderEditMode(System.Web.UI.HtmlTextWriter writer) + { + this.RenderChildren(writer); + } + + protected override void RenderViewMode(System.Web.UI.HtmlTextWriter writer) + { + string propValue = this.Page.Server.HtmlDecode(Convert.ToString(this.Value)); + ControlStyle.AddAttributesToRender(writer); + writer.RenderBeginTag(HtmlTextWriterTag.Span); + writer.Write(propValue); + writer.RenderEndTag(); + } + + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBar.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBar.cs new file mode 100644 index 00000000000..83a79213587 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBar.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolBar : RadToolBar + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarButton.cs new file mode 100644 index 00000000000..80f0933090c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarButton.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolBarButton : RadToolBarButton + { + public DnnToolBarButton() + { + } + + public DnnToolBarButton(string text) : base(text) + { + } + + public DnnToolBarButton(string text, bool isChecked, string @group) : base(text, isChecked, @group) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarDropDown.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarDropDown.cs new file mode 100644 index 00000000000..8fd69719b6c --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarDropDown.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolBarDropDown : RadToolBarDropDown + { + public DnnToolBarDropDown() + { + } + + public DnnToolBarDropDown(string text) : base(text) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarSplitButton.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarSplitButton.cs new file mode 100644 index 00000000000..29717a89169 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolBarSplitButton.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolBarSplitButton : RadToolBarSplitButton + { + public DnnToolBarSplitButton() + { + } + + public DnnToolBarSplitButton(string text) : base(text) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTip.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTip.cs new file mode 100644 index 00000000000..c45ae69ba54 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTip.cs @@ -0,0 +1,84 @@ +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#region Usings + +using System; +using System.Web.UI; +using DotNetNuke.Web.UI; +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolTip : RadToolTip, ILocalizable + { + private bool _localize = true; + + protected override void Render(HtmlTextWriter writer) + { + LocalizeStrings(); + base.Render(writer); + } + + public string ResourceKey { get; set; } + +#region ILocalizable Implementation + public bool Localize + { + get + { + if (base.DesignMode) + { + return false; + } + return _localize; + } + set + { + _localize = value; + } + } + + public string LocalResourceFile { get; set; } + + public virtual void LocalizeStrings() + { + if ((this.Localize) && (!(String.IsNullOrEmpty(this.ResourceKey)))) + { + if (!(String.IsNullOrEmpty(base.ManualCloseButtonText))) + { + base.ManualCloseButtonText = Utilities.GetLocalizedStringFromParent(String.Format("{0}.ManualCloseButtonText", this.ResourceKey), this); + } + + if (!(String.IsNullOrEmpty(base.Text))) + { + base.Text = Utilities.GetLocalizedStringFromParent(String.Format("{0}.Text", this.ResourceKey), this); + } + + if (!(String.IsNullOrEmpty(base.ToolTip))) + { + base.ToolTip = Utilities.GetLocalizedStringFromParent(String.Format("{0}.ToolTip", this.ResourceKey), this); + } + } + } +#endregion + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTipManager.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTipManager.cs new file mode 100644 index 00000000000..ac20bca5f57 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnToolTipManager.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnToolTipManager : RadToolTipManager + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeList.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeList.cs new file mode 100644 index 00000000000..1455b29d060 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeList.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTreeList : RadTreeList + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeNode.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeNode.cs new file mode 100644 index 00000000000..31cd7ce9145 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeNode.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnTreeNode : RadTreeNode + { + + + } +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeView.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeView.cs new file mode 100644 index 00000000000..7ba7eada588 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeView.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnTreeView : RadTreeView + { + + //public DnnTreeView() + //{ + // Utilities.ApplySkin(this); + //} + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeViewContextMenu.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeViewContextMenu.cs new file mode 100644 index 00000000000..2b00890ff34 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnTreeViewContextMenu.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + + public class DnnTreeViewContextMenu : RadTreeViewContextMenu + { + + //public DnnTreeViewContextMenu() + //{ + // Utilities.ApplySkin(this); + //} + + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedList.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedList.cs new file mode 100644 index 00000000000..f539e314a1a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedList.cs @@ -0,0 +1,63 @@ +using System; +using System.Web.UI; +using System.ComponentModel; +using System.Web.UI.WebControls; + +namespace DotNetNuke.Web.UI.WebControls +{ + /// + /// Creates a control that renders its childs as a bulleted list. + /// + /// + /// Control renders an unordered list HTML contol. + /// Each child control in is rendered as a separate list item. + /// To obtain a control over list item style, add a to a controls list, + /// and tune this object appropriately. + /// + public class DnnUnsortedList : WebControl, INamingContainer + { + private UniformControlCollection _listItems = null; + + public DnnUnsortedList() : base(HtmlTextWriterTag.Ul) + { + } + + protected override sealed ControlCollection CreateControlCollection() + { + return new TypedControlCollection(this); + } + + [PersistenceMode(PersistenceMode.InnerDefaultProperty), MergableProperty(false)] + public virtual UniformControlCollection ListItems + { + get + { + return _listItems ?? (_listItems = new UniformControlCollection(this)); + } + } + + protected override void AddAttributesToRender(HtmlTextWriter writer) + { + writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID); + if (!string.IsNullOrEmpty(CssClass)) + { + writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass); + } + } + + /// + /// A "macro" that adds a set of controls or control as a single list item (li). Use ListItems.Add(UnsortedListItem) method + /// + /// + /// All controls from the list will be rendered as a childs of a single list item. + /// + public void AddListItem(params Control[] listItemControls) + { + var listItem = new DnnUnsortedListItem(); + listItem.AddControls(listItemControls); + ListItems.Add(listItem); + } + + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedListItem.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedListItem.cs new file mode 100644 index 00000000000..42d4617dbf4 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUnsortedListItem.cs @@ -0,0 +1,45 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + + +namespace DotNetNuke.Web.UI.WebControls +{ + /// + /// Creates a control that render one item in a list ($lt;li> control). + /// + /// + public class DnnUnsortedListItem : WebControl + { + + public DnnUnsortedListItem() : base(HtmlTextWriterTag.Li) + { + } + + public void AddControls(params Control[] childControls) + { + foreach (var childControl in childControls) + { + if (childControl != null) + { + Controls.Add(childControl); + } + } + } + + protected override void AddAttributesToRender(HtmlTextWriter writer) + { + writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID); + if (!string.IsNullOrEmpty(CssClass)) + { + writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass); + } + if (!string.IsNullOrEmpty(ToolTip)) + { + writer.AddAttribute(HtmlTextWriterAttribute.Title, ToolTip); + } + } + + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUpload.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUpload.cs new file mode 100644 index 00000000000..4c7f411ac66 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnUpload.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnUpload : RadUpload + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindow.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindow.cs new file mode 100644 index 00000000000..de7ed20af15 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindow.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnWindow : RadWindow + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindowManager.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindowManager.cs new file mode 100644 index 00000000000..4626ded1851 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/DnnWindowManager.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class DnnWindowManager : RadWindowManager + { + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/ListControlExtensions.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/ListControlExtensions.cs new file mode 100644 index 00000000000..5f0c0b260ce --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/ListControlExtensions.cs @@ -0,0 +1,109 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Linq; +using System.Web.UI.WebControls; + +namespace DotNetNuke.Web.UI.WebControls.Extensions +{ + public static class ListControlExtensions + { + public static void AddItem(this ListControl control, string text, string value) + { + control.Items.Add(new ListItem(text, value)); + } + + public static void InsertItem(this ListControl control, int index, string text, string value) + { + control.Items.Insert(index, new ListItem(text, value)); + } + + public static void DataBind(this ListControl control, string initialValue) + { + DataBind(control, initialValue, false); + } + + public static void DataBind(this ListControl control, string initial, bool findByText) + { + control.DataBind(); + + Select(control, initial, findByText); + } + + public static void Select(this ListControl control, string initial) + { + Select(control, initial, false, -1); + } + + public static void Select(this ListControl control, string initial, bool findByText) + { + Select(control, initial, findByText, -1); + } + + public static void Select(this ListControl control, string initial, bool findByText, int fallbackIndex) + { + control.ClearSelection(); + if (findByText) + { + if (control.Items.FindByTextWithIgnoreCase(initial) != null) + { + control.Items.FindByTextWithIgnoreCase(initial).Selected = true; + } + else if (fallbackIndex > -1) + { + control.Items[fallbackIndex].Selected = true; + } + } + else + { + if (control.Items.FindByValueWithIgnoreCase(initial) != null) + { + control.Items.FindByValueWithIgnoreCase(initial).Selected = true; + } + else if (fallbackIndex > -1) + { + control.Items[fallbackIndex].Selected = true; + } + } + } + /// + /// Use this method instead of ListItemCollection.FindByText to find the specific item with case-insensitive. + /// + /// the items. + /// the item with this text want to find. + /// the specific item or null if didn't match the text with any item. + public static ListItem FindByTextWithIgnoreCase(this ListItemCollection listItems, string text) + { + return listItems.Cast().FirstOrDefault(item => item.Text.Equals(text, StringComparison.InvariantCultureIgnoreCase)); + } + + /// + /// Use this method instead of ListItemCollection.FindBValue to find the specific item with case-insensitive. + /// + /// the items. + /// the item with this value want to find. + /// the specific item or null if didn't match the value with any item. + public static ListItem FindByValueWithIgnoreCase(this ListItemCollection listItems, string value) + { + return listItems.Cast().FirstOrDefault(item => item.Value.Equals(value, StringComparison.InvariantCultureIgnoreCase)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/WebControlExtensions.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/WebControlExtensions.cs new file mode 100644 index 00000000000..68ff079b9dd --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/Extensions/WebControlExtensions.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using System.Web.UI.WebControls; + +namespace DotNetNuke.Web.UI.WebControls.Extensions +{ + public static class WebControlExtensions + { + public static void AddCssClass(this WebControl control, string cssClass) + { + if (string.IsNullOrEmpty(control.CssClass)) + { + control.CssClass = cssClass; + } + else + { + var cssClasses = control.CssClass.Split(' '); + var classExists = cssClasses.Any(@class => @class == cssClass); + + if (!classExists) + { + control.CssClass += " " + cssClass; + } + } + } + + public static void RemoveCssClass(this WebControl control, string cssClass) + { + if (!string.IsNullOrEmpty(control.CssClass)) + { + var cssClasses = control.CssClass.Split(' '); + control.CssClass = string.Join(" ", cssClasses.Where(@class => @class != cssClass).ToArray()); + } + } + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/IDnnRibbonBarTool.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/IDnnRibbonBarTool.cs new file mode 100644 index 00000000000..f35a072063a --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/IDnnRibbonBarTool.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.UI.WebControls +{ + public interface IDnnRibbonBarTool + { + string ToolName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/Resources/TermsSelector.js b/DNN Platform/DotNetNuke.Web/UI/WebControls/Resources/TermsSelector.js new file mode 100644 index 00000000000..7e773c209ca --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/Resources/TermsSelector.js @@ -0,0 +1,82 @@ +(function ($, t, sys) { + t.registerNamespace("dnn.controls"); + dnn.controls.termsSelector = {}; + + dnn.controls.termsSelector.OnClientDropDownOpened = function (sender, e) { + dnn.controls.termsSelector.fire(sender); + }; + + dnn.controls.termsSelector.OnClientNodeChecked = function (sender, e) { + dnn.controls.termsSelector.update(sender); + }; + + dnn.controls.termsSelector.update = function (tree) { + var treeDiv = $("#" + tree.get_id()); + var comboBox = treeDiv.data("combo"); + var nodes = tree.get_checkedNodes(); + var text = '', value = ''; + for (var i = 0; i < nodes.length; i++) { + text += nodes[i].get_text() + ", "; + value += nodes[i].get_value() + ", "; + } + if (text != '' && text.substr(text.length - 2, 2) == ', ') { + text = text.substr(0, text.length - 2); + } + if (value != '' && value.substr(value.length - 2, 2) == ', ') { + value = value.substr(0, value.length - 2); + } + + comboBox.trackChanges(); + var valueItem; + if (comboBox.get_items().get_count() == 1) { + valueItem = new Telerik.Web.UI.RadComboBoxItem(); + comboBox.get_items().add(valueItem); + valueItem.set_visible(false); + } else { + valueItem = comboBox.get_items().getItem(1); + } + valueItem.set_text(text); + valueItem.set_value(value); + valueItem.select(); + comboBox.commitChanges(); + }; + + dnn.controls.termsSelector.fire = function(combobox) { + var $this = $("#" + combobox.get_id()); + var treeDiv = $("div[id^=" + combobox.get_id() + "][id$=_TreeView]"); + if (treeDiv.data("combo")) { + return; + } + treeDiv.data("combo", combobox); + + treeDiv.click(function (e) { + if (!$(e.srcElement).is(":checkbox")) { + return false; + } + }); + }; + + var updateTerms = function() { + setTimeout(function() { + $("div[class*=TermsSelector]").each(function() { + var clientId = $(this).attr("id"); + var combo = $find(clientId); + if (combo != null) { + dnn.controls.termsSelector.fire(combo); + var tree = $find($("div[id^=" + clientId + "][id$=_TreeView]").attr("id")); + dnn.controls.termsSelector.update(tree); + } + }); + }, 0); + }; + + $().ready(function () { + updateTerms(); + if (typeof sys != "undefined") { + sys.WebForms.PageRequestManager.getInstance().add_endRequest(function () { + updateTerms(); + }); + } + }); +}(jQuery, Type, window.Sys)); + diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/RibbonBarToolInfo.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/RibbonBarToolInfo.cs new file mode 100644 index 00000000000..c84432bb750 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/RibbonBarToolInfo.cs @@ -0,0 +1,65 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + [Serializable] + public class RibbonBarToolInfo + { + public RibbonBarToolInfo() + { + ControlKey = ""; + ModuleFriendlyName = ""; + LinkWindowTarget = ""; + ToolName = ""; + } + + public RibbonBarToolInfo(string toolName, bool isHostTool, bool useButton, string linkWindowTarget, string moduleFriendlyName, string controlKey, bool showAsPopUp) + { + ToolName = toolName; + IsHostTool = isHostTool; + UseButton = useButton; + LinkWindowTarget = linkWindowTarget; + ModuleFriendlyName = moduleFriendlyName; + ControlKey = controlKey; + ShowAsPopUp = showAsPopUp; + } + + public string ControlKey { get; set; } + + public bool IsHostTool { get; set; } + + public string LinkWindowTarget { get; set; } + + public string ModuleFriendlyName { get; set; } + + public bool ShowAsPopUp { get; set; } + + public string ToolName { get; set; } + + public bool UseButton { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/Tags.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/Tags.cs new file mode 100644 index 00000000000..fe639128319 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/Tags.cs @@ -0,0 +1,400 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Security; +using DotNetNuke.Services.Localization; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class Tags : WebControl, IPostBackEventHandler, IPostBackDataHandler + { + private string _RepeatDirection = "Horizontal"; + private string _Separator = ", "; + + private string _Tags; + + private Vocabulary TagVocabulary + { + get + { + VocabularyController vocabularyController = new VocabularyController(); + return (from v in vocabularyController.GetVocabularies() where v.IsSystem && v.Name == "Tags" select v).SingleOrDefault(); + } + } + + #region "Public Properties" + + public string AddImageUrl { get; set; } + + public bool AllowTagging { get; set; } + + public string CancelImageUrl { get; set; } + + public ContentItem ContentItem { get; set; } + + public bool IsEditMode + { + get + { + bool _IsEditMode = false; + if (ViewState["IsEditMode"] != null) + { + _IsEditMode = Convert.ToBoolean(ViewState["IsEditMode"]); + } + return _IsEditMode; + } + set + { + ViewState["IsEditMode"] = value; + } + } + + public string NavigateUrlFormatString { get; set; } + + public string RepeatDirection + { + get + { + return _RepeatDirection; + } + set + { + _RepeatDirection = value; + } + } + + public string SaveImageUrl { get; set; } + + public string Separator + { + get + { + return _Separator; + } + set + { + _Separator = value; + } + } + + public bool ShowCategories { get; set; } + + public bool ShowTags { get; set; } + + #endregion + + #region "Private Methods" + + private string LocalizeString(string key) + { + string LocalResourceFile = Utilities.GetLocalResourceFile(this); + string localizedString = null; + if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(LocalResourceFile)) + { + localizedString = Localization.GetString(key, LocalResourceFile); + } + else + { + localizedString = Null.NullString; + } + return localizedString; + } + + private void RenderButton(HtmlTextWriter writer, string buttonType, string imageUrl) + { + writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString(string.Format("{0}.ToolTip", buttonType))); + writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, buttonType)); + writer.RenderBeginTag(HtmlTextWriterTag.A); + + //Image + if (!string.IsNullOrEmpty(imageUrl)) + { + writer.AddAttribute(HtmlTextWriterAttribute.Src, ResolveUrl(imageUrl)); + writer.RenderBeginTag(HtmlTextWriterTag.Img); + writer.RenderEndTag(); + } + + writer.Write(LocalizeString(buttonType)); + writer.RenderEndTag(); + } + + private void RenderTerm(HtmlTextWriter writer, Term term, bool renderSeparator) + { + writer.AddAttribute(HtmlTextWriterAttribute.Href, string.Format(NavigateUrlFormatString, term.Name)); + writer.AddAttribute(HtmlTextWriterAttribute.Title, term.Name); + writer.AddAttribute(HtmlTextWriterAttribute.Rel, "tag"); + writer.RenderBeginTag(HtmlTextWriterTag.A); + writer.Write(term.Name); + writer.RenderEndTag(); + + if (renderSeparator) + { + writer.Write(Separator); + } + } + + private void SaveTags() + { + string tags = new PortalSecurity().InputFilter(_Tags, PortalSecurity.FilterFlag.NoMarkup | PortalSecurity.FilterFlag.NoScripting); + tags = HttpContext.Current.Server.HtmlEncode(tags); + if (!string.IsNullOrEmpty(tags)) + { + foreach (string t in tags.Split(',')) + { + if (!string.IsNullOrEmpty(t)) + { + string tagName = t.Trim(' '); + Term existingTerm = (from term in ContentItem.Terms.AsQueryable() where term.Name.Equals(tagName, StringComparison.CurrentCultureIgnoreCase) select term).SingleOrDefault(); + + if (existingTerm == null) + { + //Not tagged + TermController termController = new TermController(); + Term term = + (from te in termController.GetTermsByVocabulary(TagVocabulary.VocabularyId) where te.Name.Equals(tagName, StringComparison.CurrentCultureIgnoreCase) select te). + SingleOrDefault(); + if (term == null) + { + //Add term + term = new Term(TagVocabulary.VocabularyId); + term.Name = tagName; + termController.AddTerm(term); + } + + //Add term to content + ContentItem.Terms.Add(term); + termController.AddTermToContent(term, ContentItem); + } + } + } + } + + IsEditMode = false; + + //Raise the Tags Updated Event + OnTagsUpdate(EventArgs.Empty); + } + + #endregion + + public event EventHandler TagsUpdated; + + protected void OnTagsUpdate(EventArgs e) + { + if (TagsUpdated != null) + { + TagsUpdated(this, e); + } + } + + #region "Public Methods" + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + if ((!Page.ClientScript.IsClientScriptBlockRegistered(UniqueID))) + { + StringBuilder sb = new StringBuilder(); + + sb.Append(""); + + Page.ClientScript.RegisterClientScriptBlock(GetType(), UniqueID, sb.ToString()); + } + } + + + public override void RenderControl(HtmlTextWriter writer) + { + //Render Outer Div + writer.AddAttribute(HtmlTextWriterAttribute.Class, RepeatDirection.ToLower()); + writer.RenderBeginTag(HtmlTextWriterTag.Div); + + //Render Categories + if (ShowCategories) + { + //Render UL + writer.AddAttribute(HtmlTextWriterAttribute.Class, "categories"); + writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString("Category.ToolTip")); + writer.RenderBeginTag(HtmlTextWriterTag.Ul); + + //Render Category Links + var categories = (from cat in ContentItem.Terms where cat.VocabularyId != TagVocabulary.VocabularyId select cat); + + for (int i = 0; i <= categories.Count() - 1; i++) + { + if (i == 0) + { + //First Category + writer.AddAttribute(HtmlTextWriterAttribute.Class, "first_tag"); + } + else if (i == categories.Count() - 1) + { + //Last Category + writer.AddAttribute(HtmlTextWriterAttribute.Class, "last_tag"); + } + writer.RenderBeginTag(HtmlTextWriterTag.Li); + + RenderTerm(writer, categories.ToList()[i], i < categories.Count() - 1 && RepeatDirection.ToLower() == "horizontal"); + + writer.RenderEndTag(); + } + + writer.RenderEndTag(); + } + + if (ShowTags) + { + //Render UL + writer.AddAttribute(HtmlTextWriterAttribute.Class, "tags"); + writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString("Tag.ToolTip")); + writer.RenderBeginTag(HtmlTextWriterTag.Ul); + + //Render Tag Links + var tags = (from cat in ContentItem.Terms where cat.VocabularyId == TagVocabulary.VocabularyId select cat); + + for (int i = 0; i <= tags.Count() - 1; i++) + { + if (i == 0) + { + //First Tag + writer.AddAttribute(HtmlTextWriterAttribute.Class, "first_tag"); + } + else if (i == tags.Count() - 1) + { + //Last Tag + writer.AddAttribute(HtmlTextWriterAttribute.Class, "last_tag"); + } + writer.RenderBeginTag(HtmlTextWriterTag.Li); + + RenderTerm(writer, tags.ToList()[i], i < tags.Count() - 1 && RepeatDirection.ToLower() == "horizontal"); + + writer.RenderEndTag(); + } + + if (AllowTagging) + { + writer.RenderBeginTag(HtmlTextWriterTag.Li); + + if (IsEditMode) + { + writer.Write("  "); + + writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID); + writer.AddAttribute("OnKeyPress", "return disableEnterKey(event)"); + writer.RenderBeginTag(HtmlTextWriterTag.Input); + writer.RenderEndTag(); + + writer.Write("  "); + + //Render Save Button + RenderButton(writer, "Save", SaveImageUrl); + + writer.Write("  "); + + //Render Add Button + RenderButton(writer, "Cancel", CancelImageUrl); + } + else + { + writer.Write("  "); + + //Render Add Button + RenderButton(writer, "Add", AddImageUrl); + } + + writer.RenderEndTag(); + } + + writer.RenderEndTag(); + } + + writer.RenderEndTag(); + } + + #endregion + + #region "IPostBackDataHandler Implementation" + + public bool LoadPostData(string postDataKey, NameValueCollection postCollection) + { + _Tags = postCollection[postDataKey]; + + return true; + } + + + public void RaisePostDataChangedEvent() + { + } + + #endregion + + #region "IPostBackEventHandler Implementation" + + public void RaisePostBackEvent(string eventArgument) + { + switch (eventArgument) + { + case "Add": + IsEditMode = true; + break; + case "Cancel": + IsEditMode = false; + break; + case "Save": + SaveTags(); + break; + default: + IsEditMode = false; + break; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsEventArgs.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsEventArgs.cs new file mode 100644 index 00000000000..da5695bcf11 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsEventArgs.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Entities.Content.Taxonomy; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class TermsEventArgs : EventArgs + { + private readonly Term _SelectedTerm; + + #region "Constructors" + + public TermsEventArgs(Term selectedTerm) + { + _SelectedTerm = selectedTerm; + } + + #endregion + + #region "Public Properties" + + public Term SelectedTerm + { + get + { + return _SelectedTerm; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsList.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsList.cs new file mode 100644 index 00000000000..ce099a9a52d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsList.cs @@ -0,0 +1,213 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Taxonomy; + +using Telerik.Web.UI; + + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class TermsList : WebControl + { + private bool _IsHeirarchical; + private DnnListBox _ListBox; + + private DnnTreeView _TreeView; + + #region "Events" + + public event EventHandler SelectedTermChanged; + + #endregion + + #region "Public Properties" + + public bool IsHeirarchical + { + get + { + return _IsHeirarchical; + } + } + + public Term SelectedTerm + { + get + { + Term _SelectedTerm = null; + if (!string.IsNullOrEmpty(SelectedValue)) + { + int _TermId = int.Parse(SelectedValue); + foreach (Term term in Terms) + { + if (term.TermId == _TermId) + { + _SelectedTerm = term; + break; + } + } + } + return _SelectedTerm; + } + } + + public string SelectedValue + { + get + { + string _SelectedValue = Null.NullString; + if (IsHeirarchical) + { + _SelectedValue = _TreeView.SelectedValue; + } + else + { + _SelectedValue = _ListBox.SelectedValue; + } + return _SelectedValue; + } + } + + public List Terms + { + get + { + object _DataSource = null; + if (IsHeirarchical) + { + _DataSource = _TreeView.DataSource; + } + else + { + _DataSource = _ListBox.DataSource; + } + return _DataSource as List; + } + } + + #endregion + + #region "Protected Methods" + + protected override void CreateChildControls() + { + Controls.Clear(); + + _ListBox = new DnnListBox(); + _ListBox.ID = string.Concat(ID, "_List"); + _ListBox.DataTextField = "Name"; + _ListBox.DataValueField = "TermId"; + _ListBox.AutoPostBack = true; + _ListBox.SelectedIndexChanged += ListBoxSelectedIndexChanged; + + _TreeView = new DnnTreeView(); + _TreeView.ID = string.Concat(ID, "_Tree"); + _TreeView.DataTextField = "Name"; + _TreeView.DataValueField = "TermId"; + _TreeView.DataFieldID = "TermId"; + _TreeView.DataFieldParentID = "ParentTermId"; + _TreeView.NodeClick += TreeViewNodeClick; + + Controls.Add(_ListBox); + Controls.Add(_TreeView); + } + + protected override void OnInit(EventArgs e) + { + EnsureChildControls(); + } + + protected override void OnPreRender(EventArgs e) + { + _ListBox.Visible = !IsHeirarchical; + _TreeView.Visible = IsHeirarchical; + + _ListBox.Height = Height; + _ListBox.Width = Width; + _TreeView.Height = Height; + _TreeView.Width = Width; + + _TreeView.ExpandAllNodes(); + + base.OnPreRender(e); + } + + protected virtual void OnSelectedTermChanged(TermsEventArgs e) + { + //Raise the SelectedTermChanged Event + if (SelectedTermChanged != null) + { + SelectedTermChanged(this, e); + } + } + + #endregion + + #region "Event Handlers" + + private void ListBoxSelectedIndexChanged(object sender, EventArgs e) + { + //Raise the SelectedTermChanged Event + OnSelectedTermChanged(new TermsEventArgs(SelectedTerm)); + } + + private void TreeViewNodeClick(object sender, RadTreeNodeEventArgs e) + { + //Raise the SelectedTermChanged Event + OnSelectedTermChanged(new TermsEventArgs(SelectedTerm)); + } + + #endregion + + #region "Public Methods" + + public void BindTerms(List terms, bool isHeirarchical, bool dataBind) + { + _IsHeirarchical = isHeirarchical; + + _ListBox.DataSource = terms; + _TreeView.DataSource = terms; + + if (dataBind) + { + _ListBox.DataBind(); + _TreeView.DataBind(); + } + } + + public void ClearSelectedTerm() + { + _ListBox.SelectedIndex = Null.NullInteger; + _TreeView.UnselectAllNodes(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsSelector.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsSelector.cs new file mode 100644 index 00000000000..2f82c588c81 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/TermsSelector.cs @@ -0,0 +1,360 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.UI; + +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Framework; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Web.UI.WebControls +{ + public class TermsSelector : DnnComboBox + { + public event EventHandler DataSourceChanged; + public TermsSelector() + { + IncludeSystemVocabularies = false; + IncludeTags = true; + } + + #region "Public Properties" + + public int PortalId + { + get + { + return Convert.ToInt32(ViewState["PortalId"]); + } + set + { + ViewState["PortalId"] = value; + OnDataSourceChanged(); + } + } + + public bool IncludeSystemVocabularies + { + get + { + return Convert.ToBoolean(ViewState["IncludeSystemVocabularies"]); + } + set + { + ViewState["IncludeSystemVocabularies"] = value; + OnDataSourceChanged(); + } + + } + + public bool IncludeTags + { + get + { + return Convert.ToBoolean(ViewState["IncludeTags"]); + } + set + { + ViewState["IncludeTags"] = value; + OnDataSourceChanged(); + } + + } + + public List Terms + { + get + { + return ViewState["Terms"] as List; + } + set + { + ViewState["Terms"] = value; + } + } + + #endregion + + #region "Protected Methods" + + protected override void OnInit(EventArgs e) + { + ItemTemplate = new TreeViewTemplate(); + Items.Add(new RadComboBoxItem()); + base.OnInit(e); + + OnClientDropDownOpened = "dnn.controls.termsSelector.OnClientDropDownOpened"; + if (!string.IsNullOrEmpty(CssClass)) + { + CssClass = string.Format("{0} TermsSelector", CssClass); + } + else + { + CssClass = "TermsSelector"; + } + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if(Page.IsPostBack) + { + if(Terms == null) + { + Terms = new List(); + } + else + { + Terms.Clear(); + } + + if (!string.IsNullOrEmpty(SelectedValue)) + { + foreach (var id in SelectedValue.Split(',')) + { + var termId = Convert.ToInt32(id.Trim()); + var term = Util.GetTermController().GetTerm(termId); + if (term != null) + { + Terms.Add(term); + } + } + + //clear the append item by client side + if(Items.Count > 1) + { + Items.Remove(1); + } + } + } + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + Text = Terms.ToDelimittedString(", "); + ToolTip = Terms.ToDelimittedString(", "); + } + + protected override void LoadViewState(object savedState) + { + base.LoadViewState(savedState); + + OnDataSourceChanged(); + } + + protected override object SaveViewState() + { + Page.ClientScript.RegisterClientScriptResource(GetType(), "DotNetNuke.Web.UI.WebControls.Resources.TermsSelector.js"); + + return base.SaveViewState(); + } + + protected void OnDataSourceChanged() + { + if(DataSourceChanged != null) + { + DataSourceChanged(this, new EventArgs()); + } + } + #endregion + + #region "Private Template Class" + + public class TreeViewTemplate : ITemplate + { + #region Private Fields + + private RadComboBoxItem _container; + private List _terms; + private TermsSelector _termsSelector; + + private DnnTreeView _tree; + + #endregion + + #region Private Properties + + private bool IncludeSystemVocabularies + { + get + { + return _termsSelector.IncludeSystemVocabularies; + } + } + + private bool IncludeTags + { + get + { + return _termsSelector.IncludeTags; + } + } + + private int PortalId + { + get + { + return _termsSelector.PortalId; + } + } + + private List SelectedTerms + { + get + { + return _termsSelector.Terms; + } + } + + private List Terms + { + get + { + if (_terms == null) + { + IVocabularyController vocabRep = Util.GetVocabularyController(); + _terms = new List(); + var vocabularies = from v in vocabRep.GetVocabularies() where v.ScopeType.ScopeType == "Application" || (v.ScopeType.ScopeType == "Portal" && v.ScopeId == PortalId) select v; + + foreach (Vocabulary v in vocabularies) + { + if(v.IsSystem) + { + if (IncludeSystemVocabularies || (IncludeTags && v.Name == "Tags")) + { + AddTerms(v); + } + } + else + { + AddTerms(v); + } + } + } + return _terms; + } + } + + #endregion + + #region Private Methods + + private void AddTerms(Vocabulary v) + { + ITermController termRep = Util.GetTermController(); + + //Add a dummy parent term if simple vocabulary + if (v.Type == VocabularyType.Simple) + { + Term dummyTerm = new Term(v.VocabularyId); + dummyTerm.ParentTermId = null; + dummyTerm.Name = v.Name; + dummyTerm.TermId = -v.VocabularyId; + _terms.Add(dummyTerm); + } + foreach (Term t in termRep.GetTermsByVocabulary(v.VocabularyId)) + { + if (v.Type == VocabularyType.Simple) + { + t.ParentTermId = -v.VocabularyId; + } + _terms.Add(t); + } + + } + + #endregion + + #region ITemplate Members + + public void InstantiateIn(Control container) + { + _container = (RadComboBoxItem) container; + _termsSelector = (TermsSelector) container.Parent; + + _tree = new DnnTreeView(); + _tree.ID = string.Format("{0}_TreeView", _termsSelector.ID); + _tree.DataTextField = "Name"; + _tree.DataValueField = "TermId"; + _tree.DataFieldID = "TermId"; + _tree.DataFieldParentID = "ParentTermId"; + _tree.CheckBoxes = true; + _tree.ExpandAllNodes(); + + //bind client-side events + _tree.OnClientNodeChecked = "dnn.controls.termsSelector.OnClientNodeChecked"; + + _tree.DataSource = Terms; + + _tree.NodeDataBound += TreeNodeDataBound; + _tree.DataBound += TreeDataBound; + + _container.Controls.Add(_tree); + + _termsSelector.DataSourceChanged += TermsSelector_DataSourceChanged; + } + + #endregion + + private void TreeDataBound(object sender, EventArgs e) + { + _tree.ExpandAllNodes(); + } + + private void TreeNodeDataBound(object sender, RadTreeNodeEventArgs e) + { + RadTreeNode node = e.Node; + Term term = node.DataItem as Term; + + if (term.TermId < 0) + { + node.Checkable = false; + } + foreach (Term tag in SelectedTerms) + { + if (tag.TermId == term.TermId) + { + node.Checked = true; + break; + } + } + } + + private void TermsSelector_DataSourceChanged(object sender, EventArgs e) + { + _terms = null; + _tree.DataSource = Terms; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/TypedControlCollection.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/TypedControlCollection.cs new file mode 100644 index 00000000000..6edd53f18b5 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/TypedControlCollection.cs @@ -0,0 +1,37 @@ +using System; +using System.Web.UI; + +namespace DotNetNuke.Web.UI.WebControls +{ + /// + /// Restricts the client to add only controls of specific type into the control collection + /// + /// + public sealed class TypedControlCollection : ControlCollection where T : Control + { + + public TypedControlCollection(Control owner) : base(owner) + { + } + + public override void Add(Control child) + { + if (!(child is T)) + { + throw new InvalidOperationException("Not supported"); + } + base.Add(child); + } + + public override void AddAt(int index, Control child) + { + if (!(child is T)) + { + throw new InvalidOperationException("Not supported"); + } + base.AddAt(index, child); + } + + } + +} diff --git a/DNN Platform/DotNetNuke.Web/UI/WebControls/UniformControlCollection.cs b/DNN Platform/DotNetNuke.Web/UI/WebControls/UniformControlCollection.cs new file mode 100644 index 00000000000..bf30e2b8e49 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/UI/WebControls/UniformControlCollection.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Web.UI; +using System.Threading; + +namespace DotNetNuke.Web.UI.WebControls +{ + + public sealed class UniformControlCollection : IList where TOwner : Control where TChildren : Control + { + + private readonly TOwner _owner; + + internal UniformControlCollection(TOwner owner) + { + _owner = owner; + } + + public void AddAt(int index, TChildren childControl) + { + _owner.Controls.AddAt(index, childControl); + } + + /// + ///Determines the index of a specific item in the . + /// + /// + ///The index of if found in the list; otherwise, -1. + /// + /// + ///The object to locate in the . + /// + public int IndexOf(TChildren item) + { + return _owner.Controls.IndexOf(item); + } + + /// + /// Inserts an item to the at the specified index. + /// + /// + /// The zero-based index at which should be inserted. + /// + /// + /// The object to insert into the . + /// + /// is not a valid index in the . + /// + /// + ///The is read-only. + /// + public void Insert(int index, TChildren item) + { + _owner.Controls.AddAt(index, item); + } + + /// + ///Removes the item at the specified index. + /// + /// + ///The zero-based index of the item to remove. + /// + /// is not a valid index in the . + /// + /// + ///The is read-only. + /// + public void RemoveAt(int index) + { + _owner.Controls.RemoveAt(index); + } + + /// + ///Gets or sets the element at the specified index. + /// + /// + ///The element at the specified index. + /// + /// + ///The zero-based index of the element to get or set. + /// + /// is not a valid index in the . + /// + /// + ///The property is set and the is read-only. + /// + public TChildren this[int index] + { + get + { + return _owner.Controls[index] as TChildren; + } + set + { + RemoveAt(index); + AddAt(index, value); + } + } + + /// + ///Gets the number of elements contained in the . + /// + /// + ///The number of elements contained in the . + /// + public int Count + { + get + { + return _owner.HasControls() ? _owner.Controls.Count : 0; + } + } + + /// + ///Removes the first occurrence of a specific object from the . + /// + /// + ///true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + /// + /// + ///The object to remove from the . + /// + /// + ///The is read-only. + /// + public bool Remove(TChildren item) + { + _owner.Controls.Remove(item); + return true; + } + + /// + ///Gets a value indicating whether the is read-only. + /// + /// + ///true if the is read-only; otherwise, false. + /// + public bool IsReadOnly + { + get + { + return false; + } + } + + /// + ///Returns an enumerator that iterates through the collection. + /// + /// + ///A that can be used to iterate through the collection. + /// + ///1 + public IEnumerator GetEnumerator() + { + var enumerator = _owner.Controls.GetEnumerator(); + while (enumerator.MoveNext()) + { + yield return enumerator.Current as TChildren; + } + } + + /// + ///Removes all items from the . + /// + /// + ///The is read-only. + /// + public void Clear() + { + if (_owner.HasControls()) + { + _owner.Controls.Clear(); + } + } + + /// + ///Adds an item to the . + /// + /// + ///The object to add to the . + /// + /// + ///The is read-only. + /// + public void Add(TChildren item) + { + _owner.Controls.Add(item); + } + + /// + ///Copies the elements of the to an , starting at a particular index. + /// + /// + ///The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. + /// + /// + ///The zero-based index in at which copying begins. + /// + /// is null. + /// + /// is less than 0. + /// + /// is multidimensional. + ///-or- + /// is equal to or greater than the length of . + ///-or- + ///The number of elements in the source is greater than the available space from to the end of the destination . + ///-or- + ///Type paramref name="T" cannot be cast automatically to the type of the destination . + /// + public void CopyTo(TChildren[] array, int arrayIndex) + { + var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + array.SetValue(enumerator.Current, Math.Max(Interlocked.Increment(ref arrayIndex), arrayIndex - 1)); + } + } + + /// + ///Determines whether the contains a specific value. + /// + /// + ///true if is found in the ; otherwise, false. + /// + /// + ///The object to locate in the . + /// + public bool Contains(TChildren item) + { + return _owner.Controls.Contains(item); + } + + /// + ///Returns an enumerator that iterates through a collection. + /// + /// + ///An object that can be used to iterate through the collection. + /// + ///2 + private IEnumerator EnumerableGetEnumerator() + { + return _owner.Controls.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return EnumerableGetEnumerator(); + } + + } +} diff --git a/DNN Platform/DotNetNuke.Web/Validators/AttributeBasedObjectValidator.cs b/DNN Platform/DotNetNuke.Web/Validators/AttributeBasedObjectValidator.cs new file mode 100644 index 00000000000..5a575ce1314 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/AttributeBasedObjectValidator.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Reflection; + +#endregion + +namespace DotNetNuke.Web.Validators +{ + public abstract class AttributeBasedObjectValidator : PropertyBasedObjectValidator where TAttribute : Attribute + { + protected override ValidationResult ValidateProperty(object target, PropertyInfo targetProperty) + { + return targetProperty.GetCustomAttributes(true).OfType().Aggregate(ValidationResult.Successful, + (result, attribute) => + result.CombineWith(ValidateAttribute(target, targetProperty, attribute) ?? ValidationResult.Successful)); + } + + + protected abstract ValidationResult ValidateAttribute(object target, PropertyInfo targetProperty, TAttribute attribute); + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/DataAnnotationsObjectValidator.cs b/DNN Platform/DotNetNuke.Web/Validators/DataAnnotationsObjectValidator.cs new file mode 100644 index 00000000000..7878ec2306f --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/DataAnnotationsObjectValidator.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel.DataAnnotations; +using System.Reflection; + +#endregion + +namespace DotNetNuke.Web.Validators +{ + public class DataAnnotationsObjectValidator : AttributeBasedObjectValidator + { + protected override ValidationResult ValidateAttribute(object target, PropertyInfo targetProperty, ValidationAttribute attribute) + { + return !attribute.IsValid(targetProperty.GetValue(target, new object[] {})) ? new ValidationResult(new[] {CreateError(targetProperty.Name, attribute)}) : ValidationResult.Successful; + } + + + protected virtual ValidationError CreateError(string propertyName, ValidationAttribute attribute) + { + return new ValidationError {ErrorMessage = attribute.FormatErrorMessage(propertyName), PropertyName = propertyName, Validator = attribute}; + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/ObjectValidator.cs b/DNN Platform/DotNetNuke.Web/Validators/ObjectValidator.cs new file mode 100644 index 00000000000..652353e4c47 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/ObjectValidator.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.Validators +{ + public abstract class ObjectValidator + { + public abstract ValidationResult ValidateObject(object target); + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/PropertyBasedObjectValidator.cs b/DNN Platform/DotNetNuke.Web/Validators/PropertyBasedObjectValidator.cs new file mode 100644 index 00000000000..7b4be8aac81 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/PropertyBasedObjectValidator.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Linq; +using System.Reflection; + +#endregion + +namespace DotNetNuke.Web.Validators +{ + public abstract class PropertyBasedObjectValidator : ObjectValidator + { + public override ValidationResult ValidateObject(object target) + { + return target.GetType().GetProperties().Aggregate(ValidationResult.Successful, (result, member) => result.CombineWith(ValidateProperty(target, member) ?? ValidationResult.Successful)); + } + + protected abstract ValidationResult ValidateProperty(object target, PropertyInfo targetProperty); + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/ValidationError.cs b/DNN Platform/DotNetNuke.Web/Validators/ValidationError.cs new file mode 100644 index 00000000000..bacb2bbbabb --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/ValidationError.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Web.Validators +{ + public class ValidationError + { + #region "Public Properties" + + public string ErrorMessage { get; set; } + + public string PropertyName { get; set; } + + public object Validator { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/ValidationResult.cs b/DNN Platform/DotNetNuke.Web/Validators/ValidationResult.cs new file mode 100644 index 00000000000..8859857cc4d --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/ValidationResult.cs @@ -0,0 +1,92 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; + + +#endregion + +namespace DotNetNuke.Web.Validators +{ + public class ValidationResult + { + private readonly IEnumerable _Errors; + + #region "Constructors" + + public ValidationResult() + { + _Errors = Enumerable.Empty(); + } + + public ValidationResult(IEnumerable errors) + { + Requires.NotNull("errors", errors); + _Errors = errors; + } + + #endregion + + #region "Public Properties" + + public IEnumerable Errors + { + get + { + return _Errors; + } + } + + public bool IsValid + { + get + { + return (_Errors.Count() == 0); + } + } + + public static ValidationResult Successful + { + get + { + return new ValidationResult(); + } + } + + #endregion + + #region "Public Methods" + + public ValidationResult CombineWith(ValidationResult other) + { + Requires.NotNull("other", other); + + //Just concatenate the errors collection + return new ValidationResult(_Errors.Concat(other.Errors)); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/Validators/Validator.cs b/DNN Platform/DotNetNuke.Web/Validators/Validator.cs new file mode 100644 index 00000000000..f0d353e21d5 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/Validators/Validator.cs @@ -0,0 +1,57 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; + +#endregion + +namespace DotNetNuke.Web.Validators +{ + public class Validator + { + private readonly IList _Validators; + + public Validator() + { + _Validators = new List(); + } + + public Validator(ObjectValidator validator) : this() + { + _Validators.Add(validator); + } + + public IList Validators + { + get + { + return _Validators; + } + } + + public ValidationResult ValidateObject(object target) + { + return _Validators.Aggregate(ValidationResult.Successful, (result, validator) => result.CombineWith(validator.ValidateObject(target) ?? ValidationResult.Successful)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/DotNetNuke.Web/packages.config b/DNN Platform/DotNetNuke.Web/packages.config new file mode 100644 index 00000000000..9576480c7f5 --- /dev/null +++ b/DNN Platform/DotNetNuke.Web/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Externally Sourced/Class1.cs b/DNN Platform/Externally Sourced/Class1.cs new file mode 100644 index 00000000000..c8fdcaedd67 --- /dev/null +++ b/DNN Platform/Externally Sourced/Class1.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Provider.RadEditor +{ + class Class1 + { + } +} diff --git a/DNN Platform/Externally Sourced/DDRMenu_02.00.03_Install.zip b/DNN Platform/Externally Sourced/DDRMenu_02.00.03_Install.zip new file mode 100644 index 00000000000..06c77c31a31 Binary files /dev/null and b/DNN Platform/Externally Sourced/DDRMenu_02.00.03_Install.zip differ diff --git a/DNN Platform/Externally Sourced/Externally.Sourced.csproj b/DNN Platform/Externally Sourced/Externally.Sourced.csproj new file mode 100644 index 00000000000..41396bee1fc --- /dev/null +++ b/DNN Platform/Externally Sourced/Externally.Sourced.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {9E1E178B-844B-40B8-9665-384220C46C1E} + Library + Properties + Provider.RadEditor + Provider.RadEditor + v4.0 + 512 + SAK + SAK + SAK + SAK + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + default + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + $(MSBuildProjectDirectory)\..\..\Build\BuildScripts + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Externally Sourced/ReadMe.txt b/DNN Platform/Externally Sourced/ReadMe.txt new file mode 100644 index 00000000000..b73e4630221 --- /dev/null +++ b/DNN Platform/Externally Sourced/ReadMe.txt @@ -0,0 +1,4 @@ +This project does not contain any code, all projects here have their sources in an external open source repository. This project is here to extract the required bits from the module zips and copy the zips to the correct locaktions during a release biuld. + +RadEditor Provider source can be found at http://radeditor.codeplex.com +DDRMenu source can be found at http://dnnddrmenu.codeplex.com/ \ No newline at end of file diff --git a/DNN Platform/HttpModules/Analytics/AnalyticsModule.cs b/DNN Platform/HttpModules/Analytics/AnalyticsModule.cs new file mode 100644 index 00000000000..8def7b474b2 --- /dev/null +++ b/DNN Platform/HttpModules/Analytics/AnalyticsModule.cs @@ -0,0 +1,198 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; + +using DotNetNuke.Framework; +using DotNetNuke.HttpModules.Config; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Analytics; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.HttpModules.Analytics +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.HttpModules.Analytics + /// Project: HttpModules + /// Module: AnalyticsModule + /// ----------------------------------------------------------------------------- + /// + /// This module contains functionality for injecting web analytics scripts into the page + /// + /// + /// + /// + /// [cniknet] 05/03/2009 created + /// + /// ----------------------------------------------------------------------------- + public class AnalyticsModule : IHttpModule + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AnalyticsModule)); + public string ModuleName + { + get + { + return "AnalyticsModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + application.PreRequestHandlerExecute += OnPreRequestHandlerExecute; + } + + public void Dispose() + { + } + + #endregion + + private void OnPreRequestHandlerExecute(object sender, EventArgs e) + { + try + { + //First check if we are upgrading/installing or if it is a non-page request + var app = (HttpApplication) sender; + HttpRequest request = app.Request; + + //First check if we are upgrading/installing + if (request.Url.LocalPath.ToLower().EndsWith("install.aspx") + || request.Url.LocalPath.ToLower().Contains("upgradewizard.aspx") + || request.Url.LocalPath.ToLower().Contains("installwizard.aspx")) + { + return; + } + + //exit if a request for a .net mapping that isn't a content page is made i.e. axd + if (request.Url.LocalPath.ToLower().EndsWith(".aspx") == false && request.Url.LocalPath.ToLower().EndsWith(".asmx") == false && + request.Url.LocalPath.ToLower().EndsWith(".ashx") == false) + { + return; + } + if (HttpContext.Current != null) + { + HttpContext context = HttpContext.Current; + if ((context == null)) + { + return; + } + var page = context.Handler as CDefault; + if ((page == null)) + { + return; + } + page.Load += OnPageLoad; + } + } + catch (Exception ex) + { + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("Analytics.AnalyticsModule", "OnPreRequestHandlerExecute"); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(objEventLogInfo); + + } + } + + private void OnPageLoad(object sender, EventArgs e) + { + try + { + AnalyticsEngineCollection analyticsEngines = AnalyticsEngineConfiguration.GetConfig().AnalyticsEngines; + if (analyticsEngines == null || analyticsEngines.Count == 0) + { + return; + } + var page = (Page) sender; + if ((page == null)) + { + return; + } + foreach (AnalyticsEngine engine in analyticsEngines) + { + if ((!String.IsNullOrEmpty(engine.ElementId))) + { + AnalyticsEngineBase objEngine = null; + if ((!String.IsNullOrEmpty(engine.EngineType))) + { + Type engineType = Type.GetType(engine.EngineType); + if (engineType == null) + objEngine = new GenericAnalyticsEngine(); + else + objEngine = (AnalyticsEngineBase) Activator.CreateInstance(engineType); + } + else + { + objEngine = new GenericAnalyticsEngine(); + } + if (objEngine != null) + { + string script = engine.ScriptTemplate; + if ((!String.IsNullOrEmpty(script))) + { + script = objEngine.RenderScript(script); + if ((!String.IsNullOrEmpty(script))) + { + var element = (HtmlContainerControl) page.FindControl(engine.ElementId); + if (element != null) + { + var scriptControl = new LiteralControl(); + scriptControl.Text = script; + if (engine.InjectTop) + { + element.Controls.AddAt(0, scriptControl); + } + else + { + element.Controls.Add(scriptControl); + } + } + } + } + } + } + } + } + catch (Exception ex) + { + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("Analytics.AnalyticsModule", "OnPageLoad"); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(ex); + + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngine.cs b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngine.cs new file mode 100644 index 00000000000..3b3f4babd88 --- /dev/null +++ b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngine.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + [Serializable] + public class AnalyticsEngine + { + private string _elementId; + private string _engineType; + private bool _injectTop; + private string _scriptTemplate; + + public string EngineType + { + get + { + return _engineType; + } + set + { + _engineType = value; + } + } + + public string ScriptTemplate + { + get + { + return _scriptTemplate; + } + set + { + _scriptTemplate = value; + } + } + + public string ElementId + { + get + { + return _elementId; + } + set + { + _elementId = value; + } + } + + public bool InjectTop + { + get + { + return _injectTop; + } + set + { + _injectTop = value; + } + } + } +} diff --git a/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineCollection.cs b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineCollection.cs new file mode 100644 index 00000000000..32080b5a56d --- /dev/null +++ b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineCollection.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + [Serializable] + public class AnalyticsEngineCollection : CollectionBase + { + public virtual AnalyticsEngine this[int index] + { + get + { + return (AnalyticsEngine) base.List[index]; + } + set + { + base.List[index] = value; + } + } + + public void Add(AnalyticsEngine a) + { + InnerList.Add(a); + } + } +} diff --git a/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineConfiguration.cs b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineConfiguration.cs new file mode 100644 index 00000000000..9b93725bd2a --- /dev/null +++ b/DNN Platform/HttpModules/Analytics/Config/AnalyticsEngineConfiguration.cs @@ -0,0 +1,129 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml.Serialization; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.HttpModules.Analytics + /// Project: HttpModules + /// Module: AnalyticsEngineConfiguration + /// ----------------------------------------------------------------------------- + /// + /// Class definition for AnalyticsEngineConfiguration which is used to create + /// an AnalyticsEngineCollection + /// + /// + /// + /// + /// [cniknet] 05/03/2009 created + /// + /// ----------------------------------------------------------------------------- + [Serializable, XmlRoot("AnalyticsEngineConfig")] + public class AnalyticsEngineConfiguration + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AnalyticsEngineConfiguration)); + private AnalyticsEngineCollection _analyticsEngines; + + public AnalyticsEngineCollection AnalyticsEngines + { + get + { + return _analyticsEngines; + } + set + { + _analyticsEngines = value; + } + } + + public static AnalyticsEngineConfiguration GetConfig() + { + var config = new AnalyticsEngineConfiguration {AnalyticsEngines = new AnalyticsEngineCollection()}; + FileStream fileReader = null; + string filePath = ""; + try + { + config = (AnalyticsEngineConfiguration) DataCache.GetCache("AnalyticsEngineConfig"); + if ((config == null)) + { + filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.SiteAnalytics); + + //Create a FileStream for the Config file + fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var doc = new XPathDocument(fileReader); + config = new AnalyticsEngineConfiguration {AnalyticsEngines = new AnalyticsEngineCollection()}; + foreach (XPathNavigator nav in + doc.CreateNavigator().Select("AnalyticsEngineConfig/Engines/AnalyticsEngine")) + { + var analyticsEngine = new AnalyticsEngine + { + EngineType = nav.SelectSingleNode("EngineType").Value, + ElementId = nav.SelectSingleNode("ElementId").Value, + InjectTop = Convert.ToBoolean(nav.SelectSingleNode("InjectTop").Value), + ScriptTemplate = nav.SelectSingleNode("ScriptTemplate").Value + }; + config.AnalyticsEngines.Add(analyticsEngine); + } + if (File.Exists(filePath)) + { + //Set back into Cache + DataCache.SetCache("AnalyticsEngineConfig", config, new DNNCacheDependency(filePath)); + } + } + } + catch (Exception ex) + { + //log it + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("Analytics.AnalyticsEngineConfiguration", "GetConfig Failed"); + objEventLogInfo.AddProperty("FilePath", filePath); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(objEventLogInfo); + + } + finally + { + if (fileReader != null) + { + //Close the Reader + fileReader.Close(); + } + } + return config; + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Compression/CompressionModule.cs b/DNN Platform/HttpModules/Compression/CompressionModule.cs new file mode 100644 index 00000000000..9ca8844b5b0 --- /dev/null +++ b/DNN Platform/HttpModules/Compression/CompressionModule.cs @@ -0,0 +1,66 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + + [Obsolete("Removed in version 6.2 - class still exists but does nothing.")] + public class CompressionModule : IHttpModule + { + #region IHttpModule Members + + /// + /// Init the handler and fulfill + /// + /// + /// This implementation hooks the ReleaseRequestState and PreSendRequestHeaders events to + /// figure out as late as possible if we should install the filter. Previous versions did + /// not do this as well. + /// + /// The this handler is working for. + public void Init(HttpApplication context) + { + } + + /// + /// Implementation of + /// + /// + /// Currently empty. Nothing to really do, as I have no member variables. + /// + public void Dispose() + { + } + + #endregion + } +} diff --git a/DNN Platform/HttpModules/Compression/Config/Enums.cs b/DNN Platform/HttpModules/Compression/Config/Enums.cs new file mode 100644 index 00000000000..24fd8deb3a2 --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Config/Enums.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.HttpModules.Compression +{ + /// + /// The available compression algorithms to use with the HttpCompressionModule + /// + public enum Algorithms + { + Deflate = 2, + GZip = 1, + None = 0, + Default = -1 + } +} diff --git a/DNN Platform/HttpModules/Compression/Config/Settings.cs b/DNN Platform/HttpModules/Compression/Config/Settings.cs new file mode 100644 index 00000000000..05ee72a9c9a --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Config/Settings.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Specialized; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + /// + /// This class encapsulates the settings for an HttpCompressionModule + /// + [Serializable] + public class Settings + { + private readonly StringCollection _excludedPaths; + private Algorithms _preferredAlgorithm; + + private Settings() + { + _preferredAlgorithm = Algorithms.None; + _excludedPaths = new StringCollection(); + } + + /// + /// The default settings. Deflate + normal. + /// + public static Settings Default + { + get + { + return new Settings(); + } + } + + /// + /// The preferred algorithm to use for compression + /// + public Algorithms PreferredAlgorithm + { + get + { + return _preferredAlgorithm; + } + } + + /// + /// Get the current settings from the xml config file + /// + public static Settings GetSettings() + { + var settings = (Settings) DataCache.GetCache("CompressionConfig"); + if (settings == null) + { + settings = Default; + //Place this in a try/catch as during install the host settings will not exist + try + { + settings._preferredAlgorithm = (Algorithms) Host.HttpCompressionAlgorithm; + } + catch (Exception e) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(e); + } + + string filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.Compression); + + //Create a FileStream for the Config file + var fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var doc = new XPathDocument(fileReader); + foreach (XPathNavigator nav in doc.CreateNavigator().Select("compression/excludedPaths/path")) + { + settings._excludedPaths.Add(nav.Value.ToLower()); + } + if ((File.Exists(filePath))) + { + //Set back into Cache + DataCache.SetCache("CompressionConfig", settings, new DNNCacheDependency(filePath)); + } + } + return settings; + } + + /// + /// Looks for a given path in the list of paths excluded from compression + /// + /// the relative url to check + /// true if excluded, false if not + public bool IsExcludedPath(string relUrl) + { + bool match = false; + foreach (string path in _excludedPaths) + { + if (relUrl.ToLower().Contains(path)) + { + match = true; + break; + } + } + return match; + } + } +} diff --git a/DNN Platform/HttpModules/Compression/Filters/CompressingFilter.cs b/DNN Platform/HttpModules/Compression/Filters/CompressingFilter.cs new file mode 100644 index 00000000000..47920c87df6 --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Filters/CompressingFilter.cs @@ -0,0 +1,84 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Web; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + /// + /// Base for any HttpFilter that performing compression + /// + /// + /// When implementing this class, you need to implement a + /// along with a . The latter corresponds to a + /// content coding (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) + /// that your implementation will support. + /// + public abstract class CompressingFilter : HttpOutputFilter + { + private bool _HasWrittenHeaders; + + /// + /// Protected constructor that sets up the underlying stream we're compressing into + /// + /// The stream we're wrapping up + protected CompressingFilter(Stream baseStream) : base(baseStream) + { + } + + /// + /// The name of the content-encoding that's being implemented + /// + /// + /// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5 for more + /// details on content codings. + /// + public abstract string ContentEncoding { get; } + + /// + /// Keeps track of whether or not we're written the compression headers + /// + protected bool HasWrittenHeaders + { + get + { + return _HasWrittenHeaders; + } + } + + /// + /// Writes out the compression-related headers. Subclasses should call this once before writing to the output stream. + /// + internal void WriteHeaders() + { + //this is dangerous. if Response.End is called before the filter is used, directly or indirectly, + //the content will not pass through the filter. However, this header will still be appended. + //Look for handling cases in PreRequestSendHeaders and Pre + HttpContext.Current.Response.AppendHeader("Content-Encoding", ContentEncoding); + HttpContext.Current.Response.AppendHeader("X-Compressed-By", "DotNetNuke-Compression"); + _HasWrittenHeaders = true; + } + } +} diff --git a/DNN Platform/HttpModules/Compression/Filters/DeflateFilter.cs b/DNN Platform/HttpModules/Compression/Filters/DeflateFilter.cs new file mode 100644 index 00000000000..7b551d551e6 --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Filters/DeflateFilter.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.IO.Compression; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + /// + /// Summary description for DeflateFilter. + /// + public class DeflateFilter : CompressingFilter + { + private readonly DeflateStream m_stream; + + public DeflateFilter(Stream baseStream) : base(baseStream) + { + m_stream = new DeflateStream(baseStream, CompressionMode.Compress); + } + + public override string ContentEncoding + { + get + { + return "deflate"; + } + } + + public override void Write(byte[] buffer, int offset, int count) + { + if (!HasWrittenHeaders) + { + WriteHeaders(); + } + m_stream.Write(buffer, offset, count); + } + + public override void Close() + { + m_stream.Close(); + } + + public override void Flush() + { + m_stream.Flush(); + } + } +} diff --git a/DNN Platform/HttpModules/Compression/Filters/GZipFilter.cs b/DNN Platform/HttpModules/Compression/Filters/GZipFilter.cs new file mode 100644 index 00000000000..49d2d3815ca --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Filters/GZipFilter.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.IO.Compression; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + /// + /// This is a little filter to support HTTP compression using GZip + /// + public class GZipFilter : CompressingFilter + { + private readonly GZipStream m_stream; + + public GZipFilter(Stream baseStream) : base(baseStream) + { + m_stream = new GZipStream(baseStream, CompressionMode.Compress); + } + + public override string ContentEncoding + { + get + { + return "gzip"; + } + } + + public override void Write(byte[] buffer, int offset, int count) + { + if (!HasWrittenHeaders) + { + WriteHeaders(); + } + m_stream.Write(buffer, offset, count); + } + + public override void Close() + { + m_stream.Close(); + } + + public override void Flush() + { + m_stream.Flush(); + } + } +} diff --git a/DNN Platform/HttpModules/Compression/Filters/HttpOutputFilter.cs b/DNN Platform/HttpModules/Compression/Filters/HttpOutputFilter.cs new file mode 100644 index 00000000000..162545c2f83 --- /dev/null +++ b/DNN Platform/HttpModules/Compression/Filters/HttpOutputFilter.cs @@ -0,0 +1,116 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; + +#endregion + +namespace DotNetNuke.HttpModules.Compression +{ + public abstract class HttpOutputFilter : Stream + { + private readonly Stream _sink; + + protected HttpOutputFilter(Stream baseStream) + { + _sink = baseStream; + } + + protected Stream BaseStream + { + get + { + return _sink; + } + } + + public override bool CanRead + { + get + { + return false; + } + } + + public override bool CanSeek + { + get + { + return false; + } + } + + public override bool CanWrite + { + get + { + return _sink.CanWrite; + } + } + + public override long Length + { + get + { + throw new NotSupportedException(); + } + } + + public override long Position + { + get + { + throw new NotSupportedException(); + } + set + { + throw new NotSupportedException(); + } + } + + public override long Seek(long offset, SeekOrigin direction) + { + throw new NotSupportedException(); + } + + public override void SetLength(long length) + { + throw new NotSupportedException(); + } + + public override void Close() + { + _sink.Close(); + } + + public override void Flush() + { + _sink.Flush(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +} diff --git a/DNN Platform/HttpModules/DotNetNuke.HttpModules.csproj b/DNN Platform/HttpModules/DotNetNuke.HttpModules.csproj new file mode 100644 index 00000000000..4ce00ab990a --- /dev/null +++ b/DNN Platform/HttpModules/DotNetNuke.HttpModules.csproj @@ -0,0 +1,145 @@ + + + + 9.0.30729 + 2.0 + {3D9C3F5F-1D2D-4D89-995B-438055A5E3A6} + Debug + AnyCPU + DotNetNuke.HttpModules + Library + v4.0 + SAK + SAK + SAK + SAK + DotNetNuke.HttpModules + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + bin\ + DotNetNuke.HttpModules.xml + true + true + 4 + full + AllRules.ruleset + 1591 + default + DEBUG + + + bin\ + DotNetNuke.HttpModules.xml + true + true + 4 + pdbonly + AllRules.ruleset + 1591 + + + + + + 3.5 + + + + + + + + + Code + + + + + + + + + + + + + + {ddf18e36-41a0-4ca7-a098-78ca6e6f41c1} + DotNetNuke.Instrumentation + + + {6b29aded-7b56-4484-bea5-c0e09079535b} + DotNetNuke.Library + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/HttpModules/Exception/ExceptionModule.cs b/DNN Platform/HttpModules/Exception/ExceptionModule.cs new file mode 100644 index 00000000000..aa0b7ead098 --- /dev/null +++ b/DNN Platform/HttpModules/Exception/ExceptionModule.cs @@ -0,0 +1,101 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.HttpModules.Exceptions +{ + public class ExceptionModule : IHttpModule + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ExceptionModule)); + public string ModuleName + { + get + { + return "ExceptionModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + application.Error += OnErrorRequest; + } + + public void Dispose() + { + } + + #endregion + + public void OnErrorRequest(object s, EventArgs e) + { + try + { + if(HttpContext.Current == null) + { + return; + } + + HttpContext Context = HttpContext.Current; + HttpServerUtility Server = Context.Server; + HttpRequest Request = Context.Request; + + //exit if a request for a .net mapping that isn't a content page is made i.e. axd + if (Request.Url.LocalPath.ToLower().EndsWith(".aspx") == false && Request.Url.LocalPath.ToLower().EndsWith(".asmx") == false && + Request.Url.LocalPath.ToLower().EndsWith(".ashx") == false) + { + return; + } + Exception lastException = Server.GetLastError(); + + //HttpExceptions are logged elsewhere + if (!(lastException is HttpException)) + { + var lex = new Exception("Unhandled Error: ", Server.GetLastError()); + var objExceptionLog = new ExceptionLogController(); + try + { + objExceptionLog.AddLog(lex); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + } + catch (Exception exc) + { + //it is possible when terminating the request for the context not to exist + //in this case we just want to exit since there is nothing else we can do + Logger.Error(exc); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Membership/MembershipModule.cs b/DNN Platform/HttpModules/Membership/MembershipModule.cs new file mode 100644 index 00000000000..772a433cfd5 --- /dev/null +++ b/DNN Platform/HttpModules/Membership/MembershipModule.cs @@ -0,0 +1,190 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Security.Principal; +using System.Web; + +using DotNetNuke.Application; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Personalization; +using DotNetNuke.UI.Skins.Controls; +using DotNetNuke.UI.Skins.EventListeners; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.HttpModules.Membership +{ + public class MembershipModule : IHttpModule + { + public string ModuleName + { + get + { + return "DNNMembershipModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + application.AuthenticateRequest += OnAuthenticateRequest; + } + + public void Dispose() + { + } + + #endregion + + private void OnAuthenticateRequest(object sender, EventArgs e) + { + var application = (HttpApplication) sender; + AuthenticateRequest(new HttpContextWrapper(application.Context), false); + } + + public static void OnUnverifiedUserSkinInit(object sender, SkinEventArgs e) + { + var strMessage = Localization.GetString("UnverifiedUser"); + UI.Skins.Skin.AddPageMessage(e.Skin, "", strMessage, ModuleMessage.ModuleMessageType.YellowWarning); + } + + public static void AuthenticateRequest(HttpContextBase context, bool allowUnknownExtensinons) + { + HttpRequestBase request = context.Request; + HttpResponseBase response = context.Response; + + //First check if we are upgrading/installing + if (request == null || request.Url == null + || request.Url.LocalPath.ToLower().EndsWith("install.aspx") + || request.Url.LocalPath.ToLower().Contains("upgradewizard.aspx") + || request.Url.LocalPath.ToLower().Contains("installwizard.aspx")) + { + return; + } + + //exit if a request for a .net mapping that isn't a content page is made i.e. axd + if (allowUnknownExtensinons == false + && request.Url.LocalPath.ToLower().EndsWith(".aspx") == false + && request.Url.LocalPath.ToLower().EndsWith(".asmx") == false + && request.Url.LocalPath.ToLower().EndsWith(".ashx") == false) + { + return; + } + + //Obtain PortalSettings from Current Context + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + + bool isActiveDirectoryAuthHeaderPresent = false; + var auth = request.Headers.Get("Authorization"); + if(!string.IsNullOrEmpty(auth)) + { + if(auth.StartsWith("Negotiate")) + { + isActiveDirectoryAuthHeaderPresent = true; + } + } + + if (request.IsAuthenticated && !isActiveDirectoryAuthHeaderPresent && portalSettings != null) + { + var roleController = new RoleController(); + var user = UserController.GetCachedUser(portalSettings.PortalId, context.User.Identity.Name); + //if current login is from windows authentication, the ignore the process + if (user == null && context.User is WindowsPrincipal) + { + return; + } + + //authenticate user and set last login ( this is necessary for users who have a permanent Auth cookie set ) + if (user == null || user.IsDeleted || user.Membership.LockedOut + || (!user.Membership.Approved && !user.IsInRole("Unverified Users")) + || user.Username.ToLower() != context.User.Identity.Name.ToLower()) + { + var portalSecurity = new PortalSecurity(); + portalSecurity.SignOut(); + + //Remove user from cache + if (user != null) + { + DataCache.ClearUserCache(portalSettings.PortalId, context.User.Identity.Name); + } + + //Redirect browser back to home page + response.Redirect(request.RawUrl, true); + return; + } + + if (!user.IsSuperUser && user.IsInRole("Unverified Users") && !HttpContext.Current.Items.Contains(DotNetNuke.UI.Skins.Skin.OnInitMessage)) + { + HttpContext.Current.Items.Add(DotNetNuke.UI.Skins.Skin.OnInitMessage, Localization.GetString("UnverifiedUser")); + } + + if (!user.IsSuperUser && HttpContext.Current.Request.QueryString.AllKeys.Contains("VerificationSuccess") && !HttpContext.Current.Items.Contains(DotNetNuke.UI.Skins.Skin.OnInitMessage)) + { + HttpContext.Current.Items.Add(DotNetNuke.UI.Skins.Skin.OnInitMessage, Localization.GetString("VerificationSuccess")); + HttpContext.Current.Items.Add(DotNetNuke.UI.Skins.Skin.OnInitMessageType, ModuleMessage.ModuleMessageType.GreenSuccess); + } + + //if users LastActivityDate is outside of the UsersOnlineTimeWindow then record user activity + if (DateTime.Compare(user.Membership.LastActivityDate.AddMinutes(Host.UsersOnlineTimeWindow), DateTime.Now) < 0) + { + //update LastActivityDate and IP Address for user + user.Membership.LastActivityDate = DateTime.Now; + user.LastIPAddress = request.UserHostAddress; + UserController.UpdateUser(portalSettings.PortalId, user, false, false); + } + + //check for RSVP code + if (request.QueryString["rsvp"] != null && !string.IsNullOrEmpty(request.QueryString["rsvp"])) + { + foreach (var role in TestableRoleController.Instance.GetRoles(portalSettings.PortalId, r => (r.SecurityMode != SecurityMode.SocialGroup || r.IsPublic) && r.Status == RoleStatus.Approved)) + { + if (role.RSVPCode == request.QueryString["rsvp"]) + { + roleController.UpdateUserRole(portalSettings.PortalId, user.UserID, role.RoleID); + } + } + } + + //save userinfo object in context + context.Items.Add("UserInfo", user); + + //Localization.SetLanguage also updates the user profile, so this needs to go after the profile is loaded + Localization.SetLanguage(user.Profile.PreferredLocale); + } + + if (context.Items["UserInfo"] == null) + { + context.Items.Add("UserInfo", new UserInfo()); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/MobileRedirect/MobileRedirectModule.cs b/DNN Platform/HttpModules/MobileRedirect/MobileRedirectModule.cs new file mode 100644 index 00000000000..a3b27829261 --- /dev/null +++ b/DNN Platform/HttpModules/MobileRedirect/MobileRedirectModule.cs @@ -0,0 +1,157 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Urls; +using DotNetNuke.HttpModules.Config; +using DotNetNuke.HttpModules.Services; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.EventQueue; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Mobile; + +#endregion + +namespace DotNetNuke.HttpModules +{ + public class MobileRedirectModule : IHttpModule + { + private IRedirectionController _redirectionController; + private IList _specialPages = new List { "/login.aspx", "/register.aspx", "/terms.aspx", "/privacy.aspx", "/login", "/register", "/terms", "/privacy" }; + public string ModuleName + { + get + { + return "MobileRedirectModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + _redirectionController = new RedirectionController(); + application.BeginRequest += OnBeginRequest; + } + + public void Dispose() + { + } + + #endregion + + public void OnBeginRequest(object s, EventArgs e) + { + var app = (HttpApplication)s; + var portalSettings = PortalController.GetCurrentPortalSettings(); + + //First check if we are upgrading/installing + if (app.Request.Url.LocalPath.ToLower().EndsWith("install.aspx") + || app.Request.Url.LocalPath.ToLower().Contains("upgradewizard.aspx") + || app.Request.Url.LocalPath.ToLower().Contains("installwizard.aspx") + || app.Request.Url.LocalPath.ToLower().EndsWith("captcha.aspx") + || app.Request.Url.LocalPath.ToLower().EndsWith("scriptresource.axd") + || app.Request.Url.LocalPath.ToLower().EndsWith("webresource.axd") + || app.Request.Url.LocalPath.ToLower().EndsWith("sitemap.aspx") + || app.Request.Url.LocalPath.ToLower().EndsWith(".asmx") + || app.Request.Url.LocalPath.ToLower().EndsWith(".ashx") + || app.Request.Url.LocalPath.ToLower().EndsWith(".svc") + || app.Request.HttpMethod == "POST" + || ServicesModule.ServiceApi.IsMatch(app.Context.Request.RawUrl) + || IsSpecialPage(app.Request.RawUrl) + || (portalSettings != null && !IsRedirectAllowed(app.Request.RawUrl, app, portalSettings))) + { + return; + } + if (_redirectionController != null) + { + if (portalSettings != null && portalSettings.ActiveTab != null) + { + if (app != null && app.Request != null && !string.IsNullOrEmpty(app.Request.UserAgent)) + { + //Check if redirection has been disabled for the session + //This method inspects cookie and query string. It can also setup / clear cookies. + if (!_redirectionController.IsRedirectAllowedForTheSession(app)) + { + return; + } + + string redirectUrl = _redirectionController.GetRedirectUrl(app.Request.UserAgent); + if (!string.IsNullOrEmpty(redirectUrl)) + { + //append thr query string from original url + var queryString = app.Request.RawUrl.Contains("?") ? app.Request.RawUrl.Substring(app.Request.RawUrl.IndexOf("?") + 1) : string.Empty; + if (!string.IsNullOrEmpty(queryString)) + { + redirectUrl = string.Format("{0}{1}{2}", redirectUrl, redirectUrl.Contains("?") ? "&" : "?", queryString); + } + app.Response.Redirect(redirectUrl); + } + } + } + } + } + + private bool IsRedirectAllowed(string url, HttpApplication app, PortalSettings portalSettings) + { + var urlAction = new UrlAction(app.Request); + urlAction.SetRedirectAllowed(url, new FriendlyUrlSettings(portalSettings.PortalId)); + return urlAction.RedirectAllowed; + } + + private bool IsSpecialPage(string url) + { + var tabPath = url.ToLowerInvariant(); + if (tabPath.Contains("?")) + { + tabPath = tabPath.Substring(0, tabPath.IndexOf("?")); + } + + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings == null) + { + return true; + } + + var alias = PortalController.GetCurrentPortalSettings().PortalAlias.HTTPAlias.ToLowerInvariant(); + if (alias.Contains("/")) + { + tabPath = tabPath.Replace(alias.Substring(alias.IndexOf("/")), string.Empty); + } + return _specialPages.Contains(tabPath); + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Personalization/PersonalizationModule.cs b/DNN Platform/HttpModules/Personalization/PersonalizationModule.cs new file mode 100644 index 00000000000..f6d5c8a5b28 --- /dev/null +++ b/DNN Platform/HttpModules/Personalization/PersonalizationModule.cs @@ -0,0 +1,78 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Personalization; + +#endregion + +namespace DotNetNuke.HttpModules.Personalization +{ + public class PersonalizationModule : IHttpModule + { + public string ModuleName + { + get + { + return "PersonalizationModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + application.EndRequest += OnEndRequest; + } + + public void Dispose() + { + } + + #endregion + + public void OnEndRequest(object s, EventArgs e) + { + HttpContext Context = ((HttpApplication) s).Context; + HttpRequest Request = Context.Request; + //exit if a request for a .net mapping that isn't a content page is made i.e. axd + if (Request.Url.LocalPath.ToLower().EndsWith(".aspx") == false && Request.Url.LocalPath.ToLower().EndsWith(".asmx") == false && Request.Url.LocalPath.ToLower().EndsWith(".ashx") == false) + { + return; + } + + //Obtain PortalSettings from Current Context + var _portalSettings = (PortalSettings) Context.Items["PortalSettings"]; + if (_portalSettings != null) + { + //load the user info object + UserInfo UserInfo = UserController.GetCurrentUserInfo(); + var personalization = new PersonalizationController(); + personalization.SaveProfile(Context, UserInfo.UserID, _portalSettings.PortalId); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Properties/AssemblyInfo.cs b/DNN Platform/HttpModules/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..0f17bdd5a60 --- /dev/null +++ b/DNN Platform/HttpModules/Properties/AssemblyInfo.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#endregion + +[assembly: AssemblyTitle("DotNetNuke.HttpModules")] +[assembly: AssemblyDescription("Open Source Web Application Framework")] +[assembly: AssemblyCompany("DotNetNuke Corporation")] +[assembly: AssemblyProduct("http://www.dotnetnuke.com")] +[assembly: AssemblyCopyright("DotNetNuke is copyright 2002-2013 by DotNetNuke Corporation. All Rights Reserved.")] +[assembly: AssemblyTrademark("DotNetNuke")] +[assembly: CLSCompliant(true)] +[assembly: Guid("7FF35751-D6A3-4DA0-A5E7-2F1AB026832B")] +[assembly: AssemblyVersion("6.2.1.11")] + +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Core")] +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Urls")] diff --git a/DNN Platform/HttpModules/RequestFilter/Config/Enums.cs b/DNN Platform/HttpModules/RequestFilter/Config/Enums.cs new file mode 100644 index 00000000000..ee6c3515211 --- /dev/null +++ b/DNN Platform/HttpModules/RequestFilter/Config/Enums.cs @@ -0,0 +1,36 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.HttpModules.RequestFilter +{ + public enum RequestFilterRuleType + { + Redirect, + PermanentRedirect, + NotFound + } + + public enum RequestFilterOperatorType + { + Equal, + NotEqual, + Regex + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/RequestFilter/Config/RequestFilterSettings.cs b/DNN Platform/HttpModules/RequestFilter/Config/RequestFilterSettings.cs new file mode 100644 index 00000000000..45dbc69e328 --- /dev/null +++ b/DNN Platform/HttpModules/RequestFilter/Config/RequestFilterSettings.cs @@ -0,0 +1,150 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using System.Xml.Serialization; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.HttpModules.RequestFilter +{ + [Serializable, XmlRoot("RewriterConfig")] + public class RequestFilterSettings + { + private const string RequestFilterConfig = "RequestFilter.Config"; + + private List _rules = new List(); + + public bool Enabled + { + get + { + return Host.EnableRequestFilters; + } + } + + public List Rules + { + get + { + return _rules; + } + set + { + _rules = value; + } + } + + /// + /// Get the current settings from the xml config file + /// + public static RequestFilterSettings GetSettings() + { + var settings = (RequestFilterSettings) DataCache.GetCache(RequestFilterConfig); + if (settings == null) + { + settings = new RequestFilterSettings(); + string filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.DotNetNuke); + + //Create a FileStream for the Config file + var fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var doc = new XPathDocument(fileReader); + XPathNodeIterator ruleList = doc.CreateNavigator().Select("/configuration/blockrequests/rule"); + while (ruleList.MoveNext()) + { + try + { + string serverVar = ruleList.Current.GetAttribute("servervar", string.Empty); + string values = ruleList.Current.GetAttribute("values", string.Empty); + var ac = (RequestFilterRuleType) Enum.Parse(typeof (RequestFilterRuleType), ruleList.Current.GetAttribute("action", string.Empty)); + var op = (RequestFilterOperatorType) Enum.Parse(typeof (RequestFilterOperatorType), ruleList.Current.GetAttribute("operator", string.Empty)); + string location = ruleList.Current.GetAttribute("location", string.Empty); + var rule = new RequestFilterRule(serverVar, values, op, ac, location); + settings.Rules.Add(rule); + } + catch (Exception ex) + { + DotNetNuke.Services.Exceptions.Exceptions.LogException(new Exception(string.Format("Unable to read RequestFilter Rule: {0}:", ruleList.Current.OuterXml), ex)); + } + } + if ((File.Exists(filePath))) + { + //Set back into Cache + DataCache.SetCache(RequestFilterConfig, settings, new DNNCacheDependency(filePath)); + } + } + return settings; + } + + public static void Save(List rules) + { + string filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.DotNetNuke); + if (!File.Exists(filePath)) + { + string defaultConfigFile = Globals.ApplicationMapPath + Globals.glbConfigFolder + Globals.glbDotNetNukeConfig; + if ((File.Exists(defaultConfigFile))) + { + File.Copy(defaultConfigFile, filePath, true); + } + } + var doc = new XmlDocument(); + doc.Load(filePath); + XmlNode ruleRoot = doc.SelectSingleNode("/configuration/blockrequests"); + ruleRoot.RemoveAll(); + foreach (RequestFilterRule rule in rules) + { + XmlElement xmlRule = doc.CreateElement("rule"); + XmlAttribute var = doc.CreateAttribute("servervar"); + var.Value = rule.ServerVariable; + xmlRule.Attributes.Append(var); + XmlAttribute val = doc.CreateAttribute("values"); + val.Value = rule.RawValue; + xmlRule.Attributes.Append(val); + XmlAttribute op = doc.CreateAttribute("operator"); + op.Value = rule.Operator.ToString(); + xmlRule.Attributes.Append(op); + XmlAttribute action = doc.CreateAttribute("action"); + action.Value = rule.Action.ToString(); + xmlRule.Attributes.Append(action); + XmlAttribute location = doc.CreateAttribute("location"); + location.Value = rule.Location; + xmlRule.Attributes.Append(location); + ruleRoot.AppendChild(xmlRule); + } + var settings = new XmlWriterSettings(); + settings.Indent = true; + using (XmlWriter writer = XmlWriter.Create(filePath, settings)) + { + doc.WriteContentTo(writer); + } + } + } +} diff --git a/DNN Platform/HttpModules/RequestFilter/RequestFilterModule.cs b/DNN Platform/HttpModules/RequestFilter/RequestFilterModule.cs new file mode 100644 index 00000000000..030de21649f --- /dev/null +++ b/DNN Platform/HttpModules/RequestFilter/RequestFilterModule.cs @@ -0,0 +1,126 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utils; +using DotNetNuke.Entities.Urls; +using DotNetNuke.HttpModules.UrlRewrite; + +#endregion + +namespace DotNetNuke.HttpModules.RequestFilter +{ + public class RequestFilterModule : IHttpModule + { + private const string InstalledKey = "httprequestfilter.attemptedinstall"; + + #region IHttpModule Members + + /// + /// Implementation of + /// + /// + /// Currently empty. Nothing to really do, as I have no member variables. + /// + public void Dispose() + { + } + + public void Init(HttpApplication context) + { + context.BeginRequest += FilterRequest; + } + + #endregion + + private static void FilterRequest(object sender, EventArgs e) + { + var app = (HttpApplication) sender; + if ((app == null) || (app.Context == null) || (app.Context.Items == null)) + { + return; + } + var request = app.Context.Request; + if (RewriterUtils.OmitFromRewriteProcessing(request.Url.LocalPath)) + { + return; + } + + //Carry out first time initialization tasks + Initialize.Init(app); + if (request.Url.LocalPath.ToLower().EndsWith("install.aspx") + || request.Url.LocalPath.ToLower().Contains("upgradewizard.aspx") + || request.Url.LocalPath.ToLower().Contains("installwizard.aspx")) + { + return; + } + + //only do this if we havn't already attempted an install. This prevents PreSendRequestHeaders from + //trying to add this item way to late. We only want the first run through to do anything. + //also, we use the context to store whether or not we've attempted an add, as it's thread-safe and + //scoped to the request. An instance of this module can service multiple requests at the same time, + //so we cannot use a member variable. + if (!app.Context.Items.Contains(InstalledKey)) + { + //log the install attempt in the HttpContext + //must do this first as several IF statements + //below skip full processing of this method + app.Context.Items.Add(InstalledKey, true); + var settings = RequestFilterSettings.GetSettings(); + if ((settings == null || settings.Rules.Count == 0 || !settings.Enabled)) + { + return; + } + foreach (var rule in settings.Rules) + { + //Added ability to determine the specific value types for addresses + //this check was necessary so that your rule could deal with IPv4 or IPv6 + //To use this mode, add ":IPv4" or ":IPv6" to your servervariable name. + var varArray = rule.ServerVariable.Split(':'); + var varVal = request.ServerVariables[varArray[0]]; + if (varArray[0].EndsWith("_ADDR", StringComparison.InvariantCultureIgnoreCase) && varArray.Length > 1) + { + switch (varArray[1]) + { + case "IPv4": + varVal = NetworkUtils.GetAddress(varVal, AddressType.IPv4); + break; + case "IPv6": + varVal = NetworkUtils.GetAddress(varVal, AddressType.IPv4); + break; + } + } + if ((!string.IsNullOrEmpty(varVal))) + { + if ((rule.Matches(varVal))) + { + rule.Execute(); + } + } + } + } + } + } +} diff --git a/DNN Platform/HttpModules/RequestFilter/RequestFilterRule.cs b/DNN Platform/HttpModules/RequestFilter/RequestFilterRule.cs new file mode 100644 index 00000000000..b970c54f7a8 --- /dev/null +++ b/DNN Platform/HttpModules/RequestFilter/RequestFilterRule.cs @@ -0,0 +1,186 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Web; + +#endregion + +namespace DotNetNuke.HttpModules.RequestFilter +{ + [Serializable] + public class RequestFilterRule + { + private RequestFilterRuleType _Action; + private string _Location; + private RequestFilterOperatorType _Operator; + private string _ServerVariable; + private List _Values = new List(); + + /// + /// Initializes a new instance of the RequestFilterRule class. + /// + /// + /// + /// + /// + /// + public RequestFilterRule(string serverVariable, string values, RequestFilterOperatorType op, RequestFilterRuleType action, string location) + { + _ServerVariable = serverVariable; + SetValues(values, op); + _Operator = op; + _Action = action; + _Location = location; + } + + /// + /// Initializes a new instance of the RequestFilterRule class. + /// + public RequestFilterRule() + { + } + + public string ServerVariable + { + get + { + return _ServerVariable; + } + set + { + _ServerVariable = value; + } + } + + public List Values + { + get + { + return _Values; + } + set + { + _Values = value; + } + } + + public string RawValue + { + get + { + return string.Join(" ", _Values.ToArray()); + } + } + + public RequestFilterRuleType Action + { + get + { + return _Action; + } + set + { + _Action = value; + } + } + + public RequestFilterOperatorType Operator + { + get + { + return _Operator; + } + set + { + _Operator = value; + } + } + + public string Location + { + get + { + return _Location; + } + set + { + _Location = value; + } + } + + public void SetValues(string values, RequestFilterOperatorType op) + { + _Values.Clear(); + if ((op != RequestFilterOperatorType.Regex)) + { + string[] vals = values.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); + foreach (string value in vals) + { + _Values.Add(value.ToUpperInvariant()); + } + } + else + { + _Values.Add(values); + } + } + + public bool Matches(string ServerVariableValue) + { + switch (Operator) + { + case RequestFilterOperatorType.Equal: + return Values.Contains(ServerVariableValue.ToUpperInvariant()); + case RequestFilterOperatorType.NotEqual: + return !Values.Contains(ServerVariableValue.ToUpperInvariant()); + case RequestFilterOperatorType.Regex: + return Regex.IsMatch(ServerVariableValue, Values[0], RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + return false; + } + + public void Execute() + { + HttpResponse response = HttpContext.Current.Response; + switch (Action) + { + case RequestFilterRuleType.Redirect: + response.Redirect(Location, true); + break; + case RequestFilterRuleType.PermanentRedirect: + response.StatusCode = 301; + response.Status = "301 Moved Permanently"; + response.RedirectLocation = Location; + response.End(); + break; + case RequestFilterRuleType.NotFound: + response.StatusCode = 404; + response.SuppressContent = true; + response.End(); + break; + } + } + } +} diff --git a/DNN Platform/HttpModules/Services/ServicesModule.cs b/DNN Platform/HttpModules/Services/ServicesModule.cs new file mode 100644 index 00000000000..5fbc577006c --- /dev/null +++ b/DNN Platform/HttpModules/Services/ServicesModule.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Text.RegularExpressions; +using System.Web; +using DotNetNuke.Common; + +namespace DotNetNuke.HttpModules.Services +{ + public class ServicesModule : IHttpModule + { + public static readonly Regex ServiceApi = new Regex(@"DesktopModules/.+/API"); + + public void Init(HttpApplication context) + { + context.BeginRequest += InitDnn; + } + + private void InitDnn(object sender, EventArgs e) + { + var app = sender as HttpApplication; + if (app != null && ServiceApi.IsMatch(app.Context.Request.RawUrl)) + { + Initialize.Init(app); + } + } + + public void Dispose() + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/BasicUrlRewriter.cs b/DNN Platform/HttpModules/UrlRewrite/BasicUrlRewriter.cs new file mode 100644 index 00000000000..fbd6f6cf438 --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/BasicUrlRewriter.cs @@ -0,0 +1,822 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Entities.Urls.Config; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.EventQueue; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.HttpModules.UrlRewrite +{ + internal class BasicUrlRewriter : UrlRewriterBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(BasicUrlRewriter)); + + #region overridden methods + + internal override void RewriteUrl(object sender, EventArgs e) + { + var app = (HttpApplication) sender; + HttpServerUtility server = app.Server; + HttpRequest request = app.Request; + HttpResponse response = app.Response; + HttpContext context = app.Context; + string requestedPath = app.Request.Url.AbsoluteUri; + + if (RewriterUtils.OmitFromRewriteProcessing(request.Url.LocalPath)) + { + return; + } + + //'Carry out first time initialization tasks + Initialize.Init(app); + if (request.Url.LocalPath.ToLower().EndsWith("/install/install.aspx") + || request.Url.LocalPath.ToLower().Contains("/install/upgradewizard.aspx") + || request.Url.LocalPath.ToLower().Contains("/install/installwizard.aspx") + || request.Url.LocalPath.ToLower().EndsWith("captcha.aspx") + || request.Url.LocalPath.ToLower().EndsWith("scriptresource.axd") + || request.Url.LocalPath.ToLower().EndsWith("webresource.axd")) + { + return; + } + + //URL validation + //check for ".." escape characters commonly used by hackers to traverse the folder tree on the server + //the application should always use the exact relative location of the resource it is requesting + string strURL = request.Url.AbsolutePath; + string strDoubleDecodeURL = server.UrlDecode(server.UrlDecode(request.RawUrl)); + if (Regex.Match(strURL, "[\\\\/]\\.\\.[\\\\/]").Success || +// ReSharper disable AssignNullToNotNullAttribute + Regex.Match(strDoubleDecodeURL, "[\\\\/]\\.\\.[\\\\/]").Success) +// ReSharper restore AssignNullToNotNullAttribute + { + DotNetNuke.Services.Exceptions.Exceptions.ProcessHttpException(request); + } + try + { + //fix for ASP.NET canonicalization issues http://support.microsoft.com/?kbid=887459 + if ((request.Path.IndexOf("\\", StringComparison.Ordinal) >= 0 || Path.GetFullPath(request.PhysicalPath) != request.PhysicalPath)) + { + DotNetNuke.Services.Exceptions.Exceptions.ProcessHttpException(request); + } + } + catch (Exception exc) + { + //DNN 5479 + //request.physicalPath throws an exception when the path of the request exceeds 248 chars. + //example to test: http://localhost/dotnetnuke_2/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/default.aspx + Logger.Error(exc); + } + + + String domainName; + RewriteUrl(app, out domainName); + + //blank DomainName indicates RewriteUrl couldn't locate a current portal + //reprocess url for portal alias if auto add is an option + if (domainName == "" && CanAutoAddPortalAlias()) + { + domainName = Globals.GetDomainName(app.Request, true); + } + + //from this point on we are dealing with a "standard" querystring ( ie. http://www.domain.com/default.aspx?tabid=## ) + //if the portal/url was succesfully identified + + int tabId = Null.NullInteger; + int portalId = Null.NullInteger; + string portalAlias = null; + PortalAliasInfo portalAliasInfo = null; + bool parsingError = false; + + // get TabId from querystring ( this is mandatory for maintaining portal context for child portals ) + if (!string.IsNullOrEmpty(request.QueryString["tabid"])) + { + if (!Int32.TryParse(request.QueryString["tabid"], out tabId)) + { + tabId = Null.NullInteger; + parsingError = true; + } + } + + // get PortalId from querystring ( this is used for host menu options as well as child portal navigation ) + if (!string.IsNullOrEmpty(request.QueryString["portalid"])) + { + if (!Int32.TryParse(request.QueryString["portalid"], out portalId)) + { + portalId = Null.NullInteger; + parsingError = true; + } + } + + if (parsingError) + { + //The tabId or PortalId are incorrectly formatted (potential DOS) + DotNetNuke.Services.Exceptions.Exceptions.ProcessHttpException(request); + } + + + try + { + //alias parameter can be used to switch portals + if (request.QueryString["alias"] != null) + { + // check if the alias is valid + string childAlias = request.QueryString["alias"]; + if (!Globals.UsePortNumber()) + { + childAlias = childAlias.Replace(":" + request.Url.Port, ""); + } + + if (PortalAliasController.GetPortalAliasInfo(childAlias) != null) + { + //check if the domain name contains the alias + if (childAlias.IndexOf(domainName, StringComparison.OrdinalIgnoreCase) == -1) + { + //redirect to the url defined in the alias + response.Redirect(Globals.GetPortalDomainName(childAlias, request, true), true); + } + else //the alias is the same as the current domain + { + portalAlias = childAlias; + } + } + } + + //PortalId identifies a portal when set + if (portalAlias == null) + { + if (portalId != Null.NullInteger) + { + portalAlias = PortalAliasController.GetPortalAliasByPortal(portalId, domainName); + } + } + + //TabId uniquely identifies a Portal + if (portalAlias == null) + { + if (tabId != Null.NullInteger) + { + //get the alias from the tabid, but only if it is for a tab in that domain + portalAlias = PortalAliasController.GetPortalAliasByTab(tabId, domainName); + if (String.IsNullOrEmpty(portalAlias)) + { + //if the TabId is not for the correct domain + //see if the correct domain can be found and redirect it + portalAliasInfo = PortalAliasController.GetPortalAliasInfo(domainName); + if (portalAliasInfo != null && !request.Url.LocalPath.ToLower().EndsWith("/linkclick.aspx")) + { + if (app.Request.Url.AbsoluteUri.StartsWith("https://", + StringComparison.InvariantCultureIgnoreCase)) + { + strURL = "https://" + portalAliasInfo.HTTPAlias.Replace("*.", ""); + } + else + { + strURL = "http://" + portalAliasInfo.HTTPAlias.Replace("*.", ""); + } + if (strURL.IndexOf(domainName, StringComparison.InvariantCultureIgnoreCase) == -1) + { + strURL += app.Request.Url.PathAndQuery; + } + response.Redirect(strURL, true); + } + } + } + } + + //else use the domain name + if (String.IsNullOrEmpty(portalAlias)) + { + portalAlias = domainName; + } + //using the DomainName above will find that alias that is the domainname portion of the Url + //ie. dotnetnuke.com will be found even if zzz.dotnetnuke.com was entered on the Url + portalAliasInfo = PortalAliasController.GetPortalAliasInfo(portalAlias); + if (portalAliasInfo != null) + { + portalId = portalAliasInfo.PortalID; + } + + //if the portalid is not known + if (portalId == Null.NullInteger) + { + bool autoAddPortalAlias = CanAutoAddPortalAlias(); + + if (!autoAddPortalAlias && !request.Url.LocalPath.EndsWith(Globals.glbDefaultPage, StringComparison.InvariantCultureIgnoreCase)) + { + // allows requests for aspx pages in custom folder locations to be processed + return; + } + + if (autoAddPortalAlias) + { + AutoAddAlias(context); + } + } + } + catch (ThreadAbortException exc) + { + //Do nothing if Thread is being aborted - there are two response.redirect calls in the Try block + Logger.Debug(exc); + } + catch (Exception ex) + { + //500 Error - Redirect to ErrorPage + Logger.Error(ex); + + strURL = "~/ErrorPage.aspx?status=500&error=" + server.UrlEncode(ex.Message); + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer(strURL); + } + if (portalId != -1) + { + //load the PortalSettings into current context + var portalSettings = new PortalSettings(tabId, portalAliasInfo); + app.Context.Items.Add("PortalSettings", portalSettings); + + // load PortalSettings and HostSettings dictionaries into current context + // specifically for use in DotNetNuke.Web.Client, which can't reference DotNetNuke.dll to get settings the normal way + app.Context.Items.Add("PortalSettingsDictionary", PortalController.GetPortalSettingsDictionary(portalId)); + app.Context.Items.Add("HostSettingsDictionary", HostController.Instance.GetSettingsDictionary()); + + if (portalSettings.PortalAliasMappingMode == PortalSettings.PortalAliasMapping.Redirect && + portalAliasInfo != null && !portalAliasInfo.IsPrimary) + { + //Permanently Redirect + response.StatusCode = 301; + + string redirectAlias = Globals.AddHTTP(portalSettings.DefaultPortalAlias); + string checkAlias = Globals.AddHTTP(portalAliasInfo.HTTPAlias); + string redirectUrl = redirectAlias + request.RawUrl; + if (redirectUrl.StartsWith(checkAlias, StringComparison.InvariantCultureIgnoreCase)) + { + redirectUrl = redirectAlias + redirectUrl.Substring(checkAlias.Length); + } + + response.AppendHeader("Location", redirectUrl); + } + + //manage page URL redirects - that reach here because they bypass the built-in navigation + //ie Spiders, saved favorites, hand-crafted urls etc + if (!String.IsNullOrEmpty(portalSettings.ActiveTab.Url) && request.QueryString["ctl"] == null && + request.QueryString["fileticket"] == null) + { + //Target Url + string redirectUrl = portalSettings.ActiveTab.FullUrl; + if (portalSettings.ActiveTab.PermanentRedirect) + { + //Permanently Redirect + response.StatusCode = 301; + response.AppendHeader("Location", redirectUrl); + } + else + { + //Normal Redirect + response.Redirect(redirectUrl, true); + } + } + + //manage secure connections + if (request.Url.AbsolutePath.EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase)) + { + //request is for a standard page + strURL = ""; + //if SSL is enabled + if (portalSettings.SSLEnabled) + { + //if page is secure and connection is not secure orelse ssloffload is enabled and server value exists + if ((portalSettings.ActiveTab.IsSecure && !request.IsSecureConnection) && + (IsSSLOffloadEnabled(request) == false)) + { + //switch to secure connection + strURL = requestedPath.Replace("http://", "https://"); + strURL = FormatDomain(strURL, portalSettings.STDURL, portalSettings.SSLURL); + } + } + //if SSL is enforced + if (portalSettings.SSLEnforced) + { + //if page is not secure and connection is secure + if ((!portalSettings.ActiveTab.IsSecure && request.IsSecureConnection)) + { + //check if connection has already been forced to secure orelse ssloffload is disabled + if (request.QueryString["ssl"] == null) + { + strURL = requestedPath.Replace("https://", "http://"); + strURL = FormatDomain(strURL, portalSettings.SSLURL, portalSettings.STDURL); + } + } + } + + //if a protocol switch is necessary + if (!String.IsNullOrEmpty(strURL)) + { + if (strURL.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) + { + //redirect to secure connection + response.Redirect(strURL, true); + } + else + //when switching to an unsecure page, use a clientside redirector to avoid the browser security warning + { + response.Clear(); + //add a refresh header to the response + response.AddHeader("Refresh", "0;URL=" + strURL); + //add the clientside javascript redirection script + response.Write(""); + response.Write(""); + response.Write(""); + //send the response + response.End(); + } + } + } + } + else + { + //alias does not exist in database + //and all attempts to find another have failed + //this should only happen if the HostPortal does not have any aliases + //404 Error - Redirect to ErrorPage + strURL = "~/ErrorPage.aspx?status=404&error=" + domainName; + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer(strURL); + } + + if (app.Context.Items["FirstRequest"] != null) + { + app.Context.Items.Remove("FirstRequest"); + + //Process any messages in the EventQueue for the Application_Start_FirstRequest event + EventQueueController.ProcessMessages("Application_Start_FirstRequest"); + } + } + + #endregion + + #region rewriting methods + + //Note these formerly lived in the 'UrlRewriteModule.cs' class + private string FormatDomain(string url, string replaceDomain, string withDomain) + { + if (!String.IsNullOrEmpty(replaceDomain) && !String.IsNullOrEmpty(withDomain)) + { + if (url.IndexOf(replaceDomain, StringComparison.Ordinal) != -1) + { + url = url.Replace(replaceDomain, withDomain); + } + } + return url; + } + + private void RewriteUrl(HttpApplication app, out string portalAlias) + { + HttpRequest request = app.Request; + HttpResponse response = app.Response; + string requestedPath = app.Request.Url.AbsoluteUri; + + + portalAlias = ""; + + //determine portal alias looking for longest possible match + String myAlias = Globals.GetDomainName(app.Request, true); + PortalAliasInfo objPortalAlias; + do + { + objPortalAlias = PortalAliasController.GetPortalAliasInfo(myAlias); + + if (objPortalAlias != null) + { + portalAlias = myAlias; + break; + } + + int slashIndex = myAlias.LastIndexOf('/'); + myAlias = slashIndex > 1 ? myAlias.Substring(0, slashIndex) : ""; + } while (myAlias.Length > 0); + + + app.Context.Items.Add("UrlRewrite:OriginalUrl", app.Request.Url.AbsoluteUri); + + //Friendly URLs are exposed externally using the following format + //http://www.domain.com/tabid/###/mid/###/ctl/xxx/default.aspx + //and processed internally using the following format + //http://www.domain.com/default.aspx?tabid=###&mid=###&ctl=xxx + //The system for accomplishing this is based on an extensible Regex rules definition stored in /SiteUrls.config + string sendTo = ""; + + //save and remove the querystring as it gets added back on later + //path parameter specifications will take precedence over querystring parameters + string strQueryString = ""; + if ((!String.IsNullOrEmpty(app.Request.Url.Query))) + { + strQueryString = request.QueryString.ToString(); + requestedPath = requestedPath.Replace(app.Request.Url.Query, ""); + } + + //get url rewriting rules + RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules; + + //iterate through list of rules + int matchIndex = -1; + for (int ruleIndex = 0; ruleIndex <= rules.Count - 1; ruleIndex++) + { + //check for the existence of the LookFor value + string pattern = "^" + + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[ruleIndex].LookFor) + + "$"; + Match objMatch = Regex.Match(requestedPath, pattern, RegexOptions.IgnoreCase); + + //if there is a match + if ((objMatch.Success)) + { + //create a new URL using the SendTo regex value + sendTo = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, + Regex.Replace(requestedPath, pattern, rules[ruleIndex].SendTo, + RegexOptions.IgnoreCase)); + + string parameters = objMatch.Groups[2].Value; + //process the parameters + if ((parameters.Trim().Length > 0)) + { + //split the value into an array based on "/" ( ie. /tabid/##/ ) + parameters = parameters.Replace("\\", "/"); + string[] splitParameters = parameters.Split('/'); + //icreate a well formed querystring based on the array of parameters + for (int parameterIndex = 0; parameterIndex < splitParameters.Length; parameterIndex++) + { + //ignore the page name + if ( + splitParameters[parameterIndex].IndexOf(".aspx", + StringComparison.InvariantCultureIgnoreCase) == + -1) + { + //get parameter name + string parameterName = splitParameters[parameterIndex].Trim(); + if (parameterName.Length > 0) + { + //add parameter to SendTo if it does not exist already + if ( + sendTo.IndexOf("?" + parameterName + "=", + StringComparison.InvariantCultureIgnoreCase) == -1 && + sendTo.IndexOf("&" + parameterName + "=", + StringComparison.InvariantCultureIgnoreCase) == -1) + { + //get parameter delimiter + string parameterDelimiter = sendTo.IndexOf("?", StringComparison.Ordinal) != -1 ? "&" : "?"; + sendTo = sendTo + parameterDelimiter + parameterName; + //get parameter value + string parameterValue = ""; + if (parameterIndex < splitParameters.Length - 1) + { + parameterIndex += 1; + if (!String.IsNullOrEmpty(splitParameters[parameterIndex].Trim())) + { + parameterValue = splitParameters[parameterIndex].Trim(); + } + } + //add the parameter value + if (parameterValue.Length > 0) + { + sendTo = sendTo + "=" + parameterValue; + } + } + } + } + } + } + matchIndex = ruleIndex; + break; //exit as soon as it processes the first match + } + } + if (!String.IsNullOrEmpty(strQueryString)) + { + //add querystring parameters back to SendTo + string[] parameters = strQueryString.Split('&'); + //iterate through the array of parameters + for (int parameterIndex = 0; parameterIndex <= parameters.Length - 1; parameterIndex++) + { + //get parameter name + string parameterName = parameters[parameterIndex]; + if (parameterName.IndexOf("=", StringComparison.Ordinal) != -1) + { + parameterName = parameterName.Substring(0, parameterName.IndexOf("=", StringComparison.Ordinal)); + } + //check if parameter already exists + if (sendTo.IndexOf("?" + parameterName + "=", StringComparison.InvariantCultureIgnoreCase) == -1 && + sendTo.IndexOf("&" + parameterName + "=", StringComparison.InvariantCultureIgnoreCase) == -1) + { + //add parameter to SendTo value + sendTo = sendTo.IndexOf("?", StringComparison.Ordinal) != -1 + ? sendTo + "&" + parameters[parameterIndex] + : sendTo + "?" + parameters[parameterIndex]; + } + } + } + + //if a match was found to the urlrewrite rules + if (matchIndex != -1) + { + if (rules[matchIndex].SendTo.StartsWith("~")) + { + //rewrite the URL for internal processing + RewriterUtils.RewriteUrl(app.Context, sendTo); + } + else + { + //it is not possible to rewrite the domain portion of the URL so redirect to the new URL + response.Redirect(sendTo, true); + } + } + else + { + //Try to rewrite by TabPath + string url; + if (Globals.UsePortNumber() && + ((app.Request.Url.Port != 80 && !app.Request.IsSecureConnection) || + (app.Request.Url.Port != 443 && app.Request.IsSecureConnection))) + { + url = app.Request.Url.Host + ":" + app.Request.Url.Port + app.Request.Url.LocalPath; + } + else + { + url = app.Request.Url.Host + app.Request.Url.LocalPath; + } + + if (!String.IsNullOrEmpty(myAlias)) + { + if (objPortalAlias != null) + { + int portalID = objPortalAlias.PortalID; + //Identify Tab Name + string tabPath = url; + if (tabPath.StartsWith(myAlias)) + { + tabPath = url.Remove(0, myAlias.Length); + } + //Default Page has been Requested + if ((tabPath == "/" + Globals.glbDefaultPage.ToLower())) + { + return; + } + + //Start of patch + string cultureCode = string.Empty; + + Dictionary dicLocales = LocaleController.Instance.GetLocales(portalID); + if (dicLocales.Count > 1) + { + String[] splitUrl = app.Request.Url.ToString().Split('/'); + + foreach (string culturePart in splitUrl) + { + if (culturePart.IndexOf("-", StringComparison.Ordinal) > -1) + { + foreach (KeyValuePair key in dicLocales) + { + if (key.Key.ToLower().Equals(culturePart.ToLower())) + { + cultureCode = key.Value.Code; + tabPath = tabPath.Replace("/" + culturePart, ""); + break; + } + } + } + } + } + + // Check to see if the tab exists (if localization is enable, check for the specified culture) + int tabID = TabController.GetTabByTabPath(portalID, + tabPath.Replace("/", "//").Replace(".aspx", ""), + cultureCode); + + // Check to see if neutral culture tab exists + if ((tabID == Null.NullInteger && cultureCode.Length > 0)) + { + tabID = TabController.GetTabByTabPath(portalID, + tabPath.Replace("/", "//").Replace(".aspx", ""), ""); + } + //End of patch + + if ((tabID != Null.NullInteger)) + { + string sendToUrl = "~/" + Globals.glbDefaultPage + "?TabID=" + tabID; + if (!cultureCode.Equals(string.Empty)) + { + sendToUrl = sendToUrl + "&language=" + cultureCode; + } + if ((!String.IsNullOrEmpty(app.Request.Url.Query))) + { + sendToUrl = sendToUrl + "&" + app.Request.Url.Query.TrimStart('?'); + } + RewriterUtils.RewriteUrl(app.Context, sendToUrl); + return; + } + tabPath = tabPath.ToLower(); + if ((tabPath.IndexOf('?') != -1)) + { + tabPath = tabPath.Substring(0, tabPath.IndexOf('?')); + } + + //Get the Portal + PortalInfo portal = new PortalController().GetPortal(portalID); + string requestQuery = app.Request.Url.Query; + if (!string.IsNullOrEmpty(requestQuery)) + { + requestQuery = Regex.Replace(requestQuery, "&?tabid=\\d+", string.Empty, + RegexOptions.IgnoreCase); + requestQuery = Regex.Replace(requestQuery, "&?portalid=\\d+", string.Empty, + RegexOptions.IgnoreCase); + requestQuery = requestQuery.TrimStart('?', '&'); + } + if (tabPath == "/login.aspx") + { + if (portal.LoginTabId > Null.NullInteger && Globals.ValidateLoginTabID(portal.LoginTabId)) + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.LoginTabId + "&" + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.LoginTabId); + } + } + else + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.HomeTabId + "&portalid=" + portalID + "&ctl=login&" + + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.HomeTabId + "&portalid=" + portalID + "&ctl=login"); + } + } + return; + } + if (tabPath == "/register.aspx") + { + if (portal.RegisterTabId > Null.NullInteger) + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.RegisterTabId + "&portalid=" + portalID + "&" + + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.RegisterTabId + "&portalid=" + portalID); + } + } + else + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.HomeTabId + "&portalid=" + portalID + + "&ctl=Register&" + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + + portal.HomeTabId + "&portalid=" + portalID + + "&ctl=Register"); + } + } + return; + } + if (tabPath == "/terms.aspx") + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + portal.HomeTabId + + "&portalid=" + portalID + "&ctl=Terms&" + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + portal.HomeTabId + + "&portalid=" + portalID + "&ctl=Terms"); + } + return; + } + if (tabPath == "/privacy.aspx") + { + if (!string.IsNullOrEmpty(requestQuery)) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + portal.HomeTabId + + "&portalid=" + portalID + "&ctl=Privacy&" + requestQuery); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + portal.HomeTabId + + "&portalid=" + portalID + "&ctl=Privacy"); + } + return; + } + tabPath = tabPath.Replace("/", "//"); + tabPath = tabPath.Replace(".aspx", ""); + var objTabController = new TabController(); + TabCollection objTabs = objTabController.GetTabsByPortal(tabPath.StartsWith("//host") ? Null.NullInteger : portalID); + foreach (KeyValuePair kvp in objTabs) + { + if ((kvp.Value.IsDeleted == false && kvp.Value.TabPath.ToLower() == tabPath)) + { + if ((!String.IsNullOrEmpty(app.Request.Url.Query))) + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + kvp.Value.TabID + + "&" + app.Request.Url.Query.TrimStart('?')); + } + else + { + RewriterUtils.RewriteUrl(app.Context, + "~/" + Globals.glbDefaultPage + "?TabID=" + kvp.Value.TabID); + } + return; + } + } + } + } + } + } + + + private bool IsSSLOffloadEnabled(HttpRequest request) + { + string ssloffloadheader = HostController.Instance.GetString("SSLOffloadHeader", ""); + //if the ssloffloadheader variable has been set check to see if a request header with that type exists + if (!string.IsNullOrEmpty(ssloffloadheader)) + { + string ssloffload = request.Headers[ssloffloadheader]; + if (!string.IsNullOrEmpty(ssloffload)) + { + return true; + } + return false; + } + return false; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/Config/RewriterConfiguration.cs b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterConfiguration.cs new file mode 100644 index 00000000000..8242a83bf64 --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterConfiguration.cs @@ -0,0 +1,141 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml.Serialization; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + [Serializable, XmlRoot("RewriterConfig")] + public class RewriterConfiguration + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (RewriterConfiguration)); + private RewriterRuleCollection _rules; + + public RewriterRuleCollection Rules + { + get + { + return _rules; + } + set + { + _rules = value; + } + } + + public static RewriterConfiguration GetConfig() + { + var config = new RewriterConfiguration {Rules = new RewriterRuleCollection()}; + FileStream fileReader = null; + string filePath = ""; + try + { + config = (RewriterConfiguration) DataCache.GetCache("RewriterConfig"); + if ((config == null)) + { + filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.SiteUrls); + + //Create a FileStream for the Config file + fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var doc = new XPathDocument(fileReader); + config = new RewriterConfiguration {Rules = new RewriterRuleCollection()}; + foreach (XPathNavigator nav in doc.CreateNavigator().Select("RewriterConfig/Rules/RewriterRule")) + { + var rule = new RewriterRule {LookFor = nav.SelectSingleNode("LookFor").Value, SendTo = nav.SelectSingleNode("SendTo").Value}; + config.Rules.Add(rule); + } + if (File.Exists(filePath)) + { + //Set back into Cache + DataCache.SetCache("RewriterConfig", config, new DNNCacheDependency(filePath)); + } + } + } + catch (Exception ex) + { + //log it + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("UrlRewriter.RewriterConfiguration", "GetConfig Failed"); + objEventLogInfo.AddProperty("FilePath", filePath); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(objEventLogInfo); + + } + finally + { + if (fileReader != null) + { + //Close the Reader + fileReader.Close(); + } + } + return config; + } + + public static void SaveConfig(RewriterRuleCollection rules) + { + if (rules != null) + { + var config = new RewriterConfiguration {Rules = rules}; + + //Create a new Xml Serializer + var ser = new XmlSerializer(typeof (RewriterConfiguration)); + + //Create a FileStream for the Config file + string filePath = Globals.ApplicationMapPath + "\\SiteUrls.config"; + if (File.Exists(filePath)) + { + //make sure file is not read-only + File.SetAttributes(filePath, FileAttributes.Normal); + } + var fileWriter = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write); + + //Open up the file to serialize + var writer = new StreamWriter(fileWriter); + + //Serialize the RewriterConfiguration + ser.Serialize(writer, config); + + //Close the Writers + writer.Close(); + fileWriter.Close(); + + //Set Cache + DataCache.SetCache("RewriterConfig", config, new DNNCacheDependency(filePath)); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRule.cs b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRule.cs new file mode 100644 index 00000000000..89aefe26f6a --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRule.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + [Serializable] + public class RewriterRule + { + private string _lookFor; + private string _sendTo; + + public string LookFor + { + get + { + return _lookFor; + } + set + { + _lookFor = value; + } + } + + public string SendTo + { + get + { + return _sendTo; + } + set + { + _sendTo = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRuleCollection.cs b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRuleCollection.cs new file mode 100644 index 00000000000..f33429916c7 --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/Config/RewriterRuleCollection.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.HttpModules.Config +{ + [Serializable] + public class RewriterRuleCollection : CollectionBase + { + public virtual RewriterRule this[int index] + { + get + { + return (RewriterRule) List[index]; + } + set + { + List[index] = value; + } + } + + public void Add(RewriterRule r) + { + InnerList.Add(r); + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/FriendlyUrlProvider.cs b/DNN Platform/HttpModules/UrlRewrite/FriendlyUrlProvider.cs new file mode 100644 index 00000000000..8bf30b0f99e --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/FriendlyUrlProvider.cs @@ -0,0 +1,120 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Framework.Providers; +using DotNetNuke.HttpModules.UrlRewrite; + +#endregion + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Services.Url.FriendlyUrl +// ReSharper restore CheckNamespace +{ + public class DNNFriendlyUrlProvider : FriendlyUrlProvider + { + internal const string ProviderType = "friendlyUrl"; + + private readonly ProviderConfiguration _providerConfiguration = ProviderConfiguration.GetProviderConfiguration(ProviderType); + + private readonly FriendlyUrlProviderBase _providerInstance; + private readonly UrlFormatType _urlFormat = UrlFormatType.SearchFriendly; + private readonly string[] _validExtensions; + + public DNNFriendlyUrlProvider() + { + //Read the configuration specific information for this provider + var objProvider = (Provider) _providerConfiguration.Providers[_providerConfiguration.DefaultProvider]; + + if (!String.IsNullOrEmpty(objProvider.Attributes["urlFormat"])) + { + switch (objProvider.Attributes["urlFormat"].ToLower()) + { + case "searchfriendly": + _urlFormat = UrlFormatType.SearchFriendly; + break; + case "humanfriendly": + _urlFormat = UrlFormatType.HumanFriendly; + break; + case "advanced": + case "customonly": + _urlFormat = UrlFormatType.Advanced; + break; + default: + _urlFormat = UrlFormatType.SearchFriendly; + break; + } + } + //instance the correct provider implementation + switch (_urlFormat) + { + case UrlFormatType.Advanced: + _providerInstance = new AdvancedFriendlyUrlProvider(objProvider.Attributes); + break; + case UrlFormatType.HumanFriendly: + case UrlFormatType.SearchFriendly: + _providerInstance = new BasicFriendlyUrlProvider(objProvider.Attributes); + break; + } + + string extensions = !String.IsNullOrEmpty(objProvider.Attributes["validExtensions"]) ? objProvider.Attributes["validExtensions"] : ".aspx"; + _validExtensions = extensions.Split(','); + } + + public string[] ValidExtensions + { + get { return _validExtensions; } + } + + public UrlFormatType UrlFormat + { + get { return _urlFormat; } + } + + public override string FriendlyUrl(TabInfo tab, string path) + { + return _providerInstance.FriendlyUrl(tab, path); + } + + public override string FriendlyUrl(TabInfo tab, string path, string pageName) + { + return _providerInstance.FriendlyUrl(tab, path, pageName); + } + + public override string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings settings) + { + return _providerInstance.FriendlyUrl(tab, path, pageName, settings); + } + + public override string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias) + { + return _providerInstance.FriendlyUrl(tab, path, pageName, portalAlias); + } + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/UrlRewrite/UrlRewriteModule.cs b/DNN Platform/HttpModules/UrlRewrite/UrlRewriteModule.cs new file mode 100644 index 00000000000..6fa5f9996d0 --- /dev/null +++ b/DNN Platform/HttpModules/UrlRewrite/UrlRewriteModule.cs @@ -0,0 +1,78 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System.Web; + +using DotNetNuke.Entities.Urls; +using DotNetNuke.Framework.Providers; +using DotNetNuke.HttpModules.UrlRewrite; + +#endregion + +namespace DotNetNuke.HttpModules +{ + public class UrlRewriteModule : IHttpModule + { + private string _providerToUse; + private UrlRewriterBase _urlRewriter; + + public string ModuleName + { + get { return "UrlRewriteModule"; } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + _providerToUse = DotNetNuke.Common.Utilities.Config.GetFriendlyUrlProvider(); + + //bind events depending on currently configured friendly url provider + //note that the current configured friendly url provider determines what type + //of url rewriting is required. + + switch (_providerToUse) + { + case "advanced": + var advancedRewriter = new AdvancedUrlRewriter(); + _urlRewriter = advancedRewriter; + //bind the rewrite event to the begin request event + application.BeginRequest += _urlRewriter.RewriteUrl; + break; + default: + var basicRewriter = new BasicUrlRewriter(); + _urlRewriter = basicRewriter; + application.BeginRequest += _urlRewriter.RewriteUrl; + break; + } + } + + public void Dispose() + { + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/HttpModules/Users Online/UsersOnlineModule.cs b/DNN Platform/HttpModules/Users Online/UsersOnlineModule.cs new file mode 100644 index 00000000000..76431f00e5f --- /dev/null +++ b/DNN Platform/HttpModules/Users Online/UsersOnlineModule.cs @@ -0,0 +1,81 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.HttpModules.UsersOnline +{ + public class UsersOnlineModule : IHttpModule + { + public string ModuleName + { + get + { + return "UsersOnlineModule"; + } + } + + #region IHttpModule Members + + public void Init(HttpApplication application) + { + application.AuthorizeRequest += OnAuthorizeRequest; + } + + public void Dispose() + { + } + + #endregion + + public void OnAuthorizeRequest(object s, EventArgs e) + { + //First check if we are upgrading/installing + var app = (HttpApplication) s; + HttpRequest request = app.Request; + + //check if we are upgrading/installing or if this is a captcha request + if (request.Url.LocalPath.ToLower().EndsWith("/install/install.aspx") + || request.Url.LocalPath.ToLower().Contains("/install/installwizard.aspx") + || request.Url.LocalPath.ToLower().Contains("/install/upgradewizard.aspx") + || request.Url.LocalPath.ToLower().EndsWith("captcha.aspx") + || request.Url.LocalPath.ToLower().EndsWith("scriptresource.axd") + || request.Url.LocalPath.ToLower().EndsWith("webresource.axd")) + { + return; + } + //Create a Users Online Controller + var objUserOnlineController = new UserOnlineController(); + + //Is Users Online Enabled? + if ((objUserOnlineController.IsEnabled())) + { + objUserOnlineController.TrackUsers(); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Application/Application.cs b/DNN Platform/Library/Application/Application.cs new file mode 100644 index 00000000000..d7a03b49b0a --- /dev/null +++ b/DNN Platform/Library/Application/Application.cs @@ -0,0 +1,248 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Application +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Application + /// Project: DotNetNuke + /// Module: Application + /// ----------------------------------------------------------------------------- + /// + /// The Application class contains properties that describe the DotNetNuke Application. + /// + /// + /// + /// + /// [cnurse] 09/10/2009 created + /// + /// ----------------------------------------------------------------------------- + public class Application + { + private static ReleaseMode _status = ReleaseMode.None; + + protected internal Application() + { + } + + /// + /// Gets the company to which the DotNetNuke application is related. + /// + /// Fixed result: DotNetNuke Corporation + public string Company + { + get + { + return "DNN Corporation"; + } + } + + /// + /// Gets the description of the application + /// + /// Fixed result: DotNetNuke Community Edition + public virtual string Description + { + get + { + return "DNN Platform"; + } + } + + /// + /// Gets the help URL related to the DotNetNuke application + /// + /// Fixed result: http://www.dotnetnuke.com/default.aspx?tabid=787 + public string HelpUrl + { + get + { + return "http://www.dotnetnuke.com/default.aspx?tabid=787"; + } + } + + /// + /// Gets the legal copyright. + /// + /// Dynamic: DotNetNuke is copyright 2002-todays year by DotNetNuke Corporation" + public string LegalCopyright + { + get + { + return "DotNetNuke is copyright 2002-" + DateTime.Today.ToString("yyyy") + " by DotNetNuke Corporation"; + } + } + + /// + /// Gets the name of the application + /// + /// Fixed result: DNNCORP.CE + public virtual string Name + { + get + { + return "DNNCORP.CE"; + } + } + + /// + /// Gets the SKU (Stock Keeping Unit) + /// + /// Fixed result: DNN + public virtual string SKU + { + get + { + return "DNN"; + } + } + + /// + /// Gets the status of the DotnetNuke application + /// + /// + /// If the value is not be Stable, you will see the exactly status and version in page's title if allow display beta message in host setting. + /// + /// + /// The value can be: None, Alpha, Beta, RC, Stable + /// + public ReleaseMode Status + { + get + { + if (_status == ReleaseMode.None) + { + Assembly assy = Assembly.GetExecutingAssembly(); + if (Attribute.IsDefined(assy, typeof (AssemblyStatusAttribute))) + { + Attribute attr = Attribute.GetCustomAttribute(assy, typeof (AssemblyStatusAttribute)); + if (attr != null) + { + _status = ((AssemblyStatusAttribute) attr).Status; + } + } + } + return _status; + } + } + + /// + /// Gets the title of the application + /// + /// Fixed value: DotNetNuke. + public string Title + { + get + { + return "DotNetNuke"; + } + } + + /// + /// Gets the trademark. + /// + /// Fixed value: DotNetNuke,DNN + public string Trademark + { + get + { + return "DotNetNuke,DNN"; + } + } + + /// + /// Gets the type of the application + /// + /// Fixed value: Framework + public string Type + { + get + { + return "Framework"; + } + } + + /// + /// Gets the upgrade URL. + /// + /// Fixed value: http://update.dotnetnuke.com + public string UpgradeUrl + { + get + { + var url = Config.GetSetting("UpdateServiceUrl"); + if (string.IsNullOrEmpty(url)) + { + return "http://update.dotnetnuke.com"; + } + return url; + } + } + + /// + /// Gets the URL of the application + /// + /// Fixed value: http://www.dotnetnuke.com + public string Url + { + get + { + return "http://www.dotnetnuke.com"; + } + } + + /// + /// Gets the version of the DotNetNuke framework/application + /// + /// The version as retreieved from the Executing assembly. + public Version Version + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version; + } + } + + #region "Public Functions" + + /// + /// Determine whether a product specific change is to be applied + /// + /// list of product names + /// true if product is within list of names + /// + /// + public virtual bool ApplyToProduct(string productNames) + { + return productNames.Contains(Name); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Application/AssemblyStatusAttribute.cs b/DNN Platform/Library/Application/AssemblyStatusAttribute.cs new file mode 100644 index 00000000000..9106a1cc3d9 --- /dev/null +++ b/DNN Platform/Library/Application/AssemblyStatusAttribute.cs @@ -0,0 +1,101 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Application +{ + /// + /// The enumeration of release mode. + /// + /// + /// + /// None: Not specified for the current release. + /// Alpha:Alpha release is an opportunity for customers to get an early look at a particular software feature. + /// Beta: Beta release is a mostly completed release, + /// At this point we will have implemented most of the major features planned for a specific release. + /// RC: RC relase will be the Stable release if there is none major show-stopping bugs, + /// We have gone through all the major test scenarios and are just running through a final set of regression + /// tests and verifying the packaging. + /// Stable: Stable release is believed to be ready for use, + /// remember that only stable release can be used in production environment. + /// + /// + public enum ReleaseMode + { + /// + /// Not asssigned + /// + None, + /// + /// Alpha release + /// + Alpha, + /// + /// Beta release + /// + Beta, + /// + /// Release candidate + /// + RC, + /// + /// Stable release version + /// + Stable + } + + /// + /// The status of current assembly. + /// + /// + /// [assembly: AssemblyStatus(ReleaseMode.Stable)] + /// + [AttributeUsage(AttributeTargets.Assembly)] + public class AssemblyStatusAttribute : Attribute + { + private readonly ReleaseMode _releaseMode; + + /// + /// Initializes a new instance of the class. + /// + /// The release mode. + public AssemblyStatusAttribute(ReleaseMode releaseMode) + { + _releaseMode = releaseMode; + } + + + /// + /// Status of current assembly. + /// + public ReleaseMode Status + { + get + { + return _releaseMode; + } + } + } +} diff --git a/DNN Platform/Library/Application/DotNetNukeContext.cs b/DNN Platform/Library/Application/DotNetNukeContext.cs new file mode 100644 index 00000000000..a64587cc9c8 --- /dev/null +++ b/DNN Platform/Library/Application/DotNetNukeContext.cs @@ -0,0 +1,123 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.UI.Containers.EventListeners; +using DotNetNuke.UI.Skins.EventListeners; + +#endregion + +namespace DotNetNuke.Application +{ + /// + /// Defines the context for the environment of the DotNetNuke application + /// + public class DotNetNukeContext + { + private static DotNetNukeContext _current; + private readonly Application _application; + private readonly IList _containerEventListeners; + private readonly IList _skinEventListeners; + + /// + /// Initializes a new instance of the class. + /// + protected DotNetNukeContext() : this(new Application()) + { + } + + /// + /// Initializes a new instance of the class using the provided application as base. + /// + /// The application. + protected DotNetNukeContext(Application application) + { + _application = application; + _containerEventListeners = new NaiveLockingList(); + _skinEventListeners = new NaiveLockingList(); + } + + /// + /// Get the application. + /// + public Application Application + { + get + { + return _application; + } + } + + /// + /// Gets the container event listeners. The listeners will be called in each life cycle of load container. + /// + /// + /// + /// + /// + /// + public IList ContainerEventListeners + { + get + { + return _containerEventListeners; + } + } + + /// + /// Gets the skin event listeners. The listeners will be called in each life cycle of load skin. + /// + /// + /// + /// + /// + /// + public IList SkinEventListeners + { + get + { + return _skinEventListeners; + } + } + + /// + /// Gets or sets the current app context. + /// + public static DotNetNukeContext Current + { + get + { + if (_current == null) + { + _current = new DotNetNukeContext(); + } + return _current; + } + set + { + _current = value; + } + } + } +} diff --git a/DNN Platform/Library/AssemblyInfo.cs b/DNN Platform/Library/AssemblyInfo.cs new file mode 100644 index 00000000000..ece195fad72 --- /dev/null +++ b/DNN Platform/Library/AssemblyInfo.cs @@ -0,0 +1,66 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +using DotNetNuke.Application; +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +// Review the values of the assembly attributes + +[assembly: AssemblyTitle("DotNetNuke")] +[assembly: AssemblyDescription("Open Source Web Application Framework")] +[assembly: AssemblyCompany("DotNetNuke Corporation")] +[assembly: AssemblyProduct("http://www.dotnetnuke.com")] +[assembly: AssemblyCopyright("DotNetNuke is copyright 2002-2013 by DotNetNuke Corporation. All Rights Reserved.")] +[assembly: AssemblyTrademark("DotNetNuke")] +[assembly: CLSCompliant(true)] +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("7.1.2.0")] +[assembly: AssemblyFileVersion("7.1.2.0")] +[assembly: AssemblyStatus(ReleaseMode.Alpha)] +// Allow internal variables to be visible to testing projects +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Core")] +// This assembly is the default dynamic assembly generated Castle DynamicProxy, +// used by Moq. Paste in a single line. +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] +[assembly: InternalsVisibleTo("DotNetNuke.Web")] +[assembly: InternalsVisibleTo("DotNetNuke.HttpModules")] +[assembly: InternalsVisibleTo("DotNetNuke.Modules.MemberDirectory")] +[assembly: InternalsVisibleTo("DotNetNuke.Provider.AspNetProvider")] +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Content")] +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Web")] +[assembly: InternalsVisibleTo("DotNetNuke.Tests.Urls")] diff --git a/DNN Platform/Library/Collections/CollectionExtensions.cs b/DNN Platform/Library/Collections/CollectionExtensions.cs new file mode 100644 index 00000000000..9a0a632c2f3 --- /dev/null +++ b/DNN Platform/Library/Collections/CollectionExtensions.cs @@ -0,0 +1,936 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.Linq; +using System.Xml.Linq; +using System.Xml.XPath; + +using DotNetNuke.Common; + +namespace DotNetNuke.Collections +{ + public static class CollectionExtensions + { + /// + /// This method is extracted from the FriendlyUrlSettings class + /// + public static Dictionary CreateDictionaryFromString(string stringOfPairs, char pairsSeparator, char pairSeparator) + { + var dictionary = new Dictionary(); + if (!string.IsNullOrEmpty(stringOfPairs)) + { + var pairs = stringOfPairs.Split(pairsSeparator); + foreach (var pair in pairs) + { + var keyValues = pair.Split(pairSeparator); + string key = null; + string value = null; + if (keyValues.GetUpperBound(0) >= 0) + { + key = keyValues[0]; + } + if (keyValues.GetUpperBound(0) >= 1) + { + value = keyValues[1]; + } + if (!string.IsNullOrEmpty(key) && value != null && !dictionary.ContainsKey(key)) + { + dictionary.Add(key, value); + } + } + } + return dictionary; + } + + public static string DictionaryToString(this Dictionary dictionary, string pairsSeparator, string pairSeparator) + { + return String.Join(pairsSeparator, dictionary.Select(pair => pair.Key + pairSeparator + pair.Value)); + } + + /// + /// Gets a converter function which parses a value into a . + /// Considers the value true if it is one of the following (case-insensitive): + /// + /// true + /// on + /// 1 + /// yes + /// + /// + /// A instance. + public static Func GetFlexibleBooleanParsingFunction() + { + return GetFlexibleBooleanParsingFunction(new[] { "true", "on", "1", "yes" }); + } + + /// Gets a converter function which parses a value into a . + /// The values (case-insensitive) which should be parsed as true. + /// A instance. + public static Func GetFlexibleBooleanParsingFunction(params string[] trueValues) + { + return value => trueValues.Contains(value, StringComparer.OrdinalIgnoreCase); + } + + #region GetValue Extension Methods + + /// Gets the value from the dictionary. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// does not contain a value for + public static T GetValue(this IDictionary dictionary, string key) + { + return dictionary.GetValue(key, ConvertValue); + } + + /// Gets the value from the lookup. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this ILookup lookup, string key) + { + return lookup.ToDictionary(key).GetValue(key); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// does not contain a value for + public static T GetValue(this IXPathNavigable node, string key) + { + return node.ToDictionary().GetValue(key); + } + + /// Gets the value from the collection. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this NameValueCollection collection, string key) + { + return collection.ToLookup().GetValue(key); + } + + /// Gets the value from the XML node's child elements. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// does not contain a value for + public static T GetValue(this XContainer node, string key) + { + return node.ToDictionary().GetValue(key); + } + + /// Gets the value from the dictionary. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// or is null + /// does not contain a value for + public static T GetValue(this IDictionary dictionary, string key, Func converter) + { + Requires.NotNull("dictionary", dictionary); + Requires.NotNull("converter", converter); + + if (!dictionary.Contains(key)) + { + throw new ArgumentException("dictionary does not contain a value for the given key", "key"); + } + + return converter(dictionary[key]); + } + + /// Gets the value from the lookup. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this ILookup lookup, string key, Func converter) + { + return lookup.ToDictionary(key).GetValue(key, converter); + } + + /// Gets the value from the XML node's child elements. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// does not contain a value for + public static T GetValue(this IXPathNavigable node, string key, Func converter) + { + return node.ToDictionary().GetValue(key, converter); + } + + /// Gets the value from the collection. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this NameValueCollection collection, string key, Func converter) + { + return collection.ToLookup().GetValue(key, converter); + } + + /// Gets the value from the XML node's child elements. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// does not contain a value for + public static T GetValue(this XContainer node, string key, Func converter) + { + return node.ToDictionary().GetValue(key, converter); + } + + /// Gets the value from the dictionary. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// does not contain a value for + public static T GetValue(this IDictionary dictionary, string key, Func converter) + { + return dictionary.GetValue(key, (object value) => ConvertValue(value, converter)); + } + + /// Gets the value from the lookup. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this ILookup lookup, string key, Func converter) + { + return lookup.ToDictionary(key).GetValue(key, converter); + } + + /// Gets the value from the XML node's child elements. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// does not contain a value for + public static T GetValue(this IXPathNavigable node, string key, Func converter) + { + return node.ToDictionary().GetValue(key, converter); + } + + /// Gets the value from the collection. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + /// does not contain a value for + public static T GetValue(this NameValueCollection collection, string key, Func converter) + { + return collection.ToLookup().GetValue(key, converter); + } + + /// Gets the value from the XML node's child elements. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// does not contain a value for + public static T GetValue(this XContainer node, string key, Func converter) + { + return node.ToDictionary().GetValue(key, converter); + } + + #endregion + + #region GetValueOrDefault Extension Methods + + /// Gets the value from the dictionary, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this IDictionary dictionary, string key) + { + return dictionary.GetValueOrDefault(key, default(T)); + } + + /// Gets the value from the lookup, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key) + { + return lookup.ToDictionary(key).GetValueOrDefault(key); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key) + { + return node.ToDictionary().GetValueOrDefault(key); + } + + /// Gets the value from the collection, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key) + { + return collection.ToLookup().GetValueOrDefault(key); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this XContainer node, string key) + { + return node.ToDictionary().GetValueOrDefault(key); + } + + /// Gets the value from the dictionary, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// The default value to return if the dictionary doesn't have a value for the given . + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this IDictionary dictionary, string key, T defaultValue) + { + return dictionary.GetValueOrDefault(key, defaultValue, ConvertValue); + } + + /// Gets the value from the lookup, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// The default value to return if the lookup doesn't have a value for the given . + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key, T defaultValue) + { + return lookup.ToDictionary(key).GetValueOrDefault(key, defaultValue); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key, T defaultValue) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue); + } + + /// Gets the value from the collection, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// The default value to return if the collection doesn't have a value for the given . + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key, T defaultValue) + { + return collection.ToLookup().GetValueOrDefault(key, defaultValue); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + /// is null + public static T GetValueOrDefault(this XContainer node, string key, T defaultValue) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue); + } + + /// Gets the value from the dictionary, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IDictionary dictionary, string key, Func converter) + { + return dictionary.GetValueOrDefault(key, default(T), converter); + } + + /// Gets the value from the lookup, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key, Func converter) + { + return lookup.ToDictionary(key).GetValueOrDefault(key, converter); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, converter); + } + + /// Gets the value from the collection, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key, Func converter) + { + return collection.ToLookup().GetValueOrDefault(key, converter); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this XContainer node, string key, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, converter); + } + + /// Gets the value from the dictionary, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IDictionary dictionary, string key, Func converter) + { + return dictionary.GetValueOrDefault(key, default(T), (object value) => ConvertValue(value, converter)); + } + + /// Gets the value from the lookup, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key, Func converter) + { + return lookup.ToDictionary(key).GetValueOrDefault(key, converter); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, converter); + } + + /// Gets the value from the collection, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key, Func converter) + { + return collection.ToLookup().GetValueOrDefault(key, converter); + } + + /// Gets the value from the XML node's child elements, returning the default value of if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this XContainer node, string key, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, converter); + } + + /// Gets the value from the dictionary, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// The default value to return if the dictionary doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IDictionary dictionary, string key, T defaultValue, Func converter) + { + return dictionary.GetValueOrDefault(key, defaultValue, (object value) => ConvertValue(value, converter)); + } + + /// Gets the value from the lookup, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// The default value to return if the lookup doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key, T defaultValue, Func converter) + { + return lookup.ToDictionary(key).GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A function to convert the value as a to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key, T defaultValue, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the collection, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// The default value to return if the collection doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key, T defaultValue, Func converter) + { + return collection.ToLookup().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A function to convert the value as a to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this XContainer node, string key, T defaultValue, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the lookup, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The lookup. + /// The key by which to get the value. + /// The default value to return if the lookup doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this ILookup lookup, string key, T defaultValue, Func converter) + { + return lookup.ToDictionary(key).GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this IXPathNavigable node, string key, T defaultValue, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the collection, returning if the value doesn't exist. + /// The type of the value to retrieve + /// The collection. + /// The key by which to get the value. + /// The default value to return if the collection doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + /// has multiple values for the given + public static T GetValueOrDefault(this NameValueCollection collection, string key, T defaultValue, Func converter) + { + return collection.ToLookup().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the XML node's child elements, returning if the value doesn't exist. + /// The type of the value to retrieve + /// An XML node which containers other elements. + /// The name of the element from which to get the value. + /// The default value to return if the node doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// is null + public static T GetValueOrDefault(this XContainer node, string key, T defaultValue, Func converter) + { + return node.ToDictionary().GetValueOrDefault(key, defaultValue, converter); + } + + /// Gets the value from the dictionary, returning the if the value doesn't exist. + /// The type of the value to retrieve + /// The dictionary. + /// The key by which to get the value. + /// The default value to return if the dictionary doesn't have a value for the given . + /// A function to convert the value as an to a instance. + /// A instance. + /// or is null + public static T GetValueOrDefault(this IDictionary dictionary, string key, T defaultValue, Func converter) + { + Requires.NotNull("dictionary", dictionary); + Requires.NotNull("converter", converter); + + return dictionary.Contains(key) ? converter(dictionary[key]) : defaultValue; + } + + #endregion + + #region GetValues Extension Methods + + /// Gets the values from the lookup. + /// The type of the values to retrieve + /// The lookup. + /// The key by which to get the values. + /// A sequence of instances. + /// is null + public static IEnumerable GetValues(this ILookup lookup, string key) + { + return lookup.GetValues(key, ConvertValue); + } + + /// Gets the values from the collection. + /// The type of the values to retrieve + /// The collection. + /// The key by which to get the values. + /// A sequence of instances. + /// is null + public static IEnumerable GetValues(this NameValueCollection collection, string key) + { + return collection.ToLookup().GetValues(key); + } + + /// Gets the values from the lookup. + /// The type of the values to retrieve + /// The lookup. + /// The key by which to get the values. + /// A function to convert a value as an to a instance. + /// A sequence of instances. + /// or is null + public static IEnumerable GetValues(this ILookup lookup, string key, Func converter) + { + Requires.NotNull("lookup", lookup); + Requires.NotNull("converter", converter); + + return lookup[key].Select(converter); + } + + /// Gets the values from the collection. + /// The type of the values to retrieve + /// The collection. + /// The key by which to get the values. + /// A function to convert a value as an to a instance. + /// A sequence of instances. + /// or is null + public static IEnumerable GetValues(this NameValueCollection collection, string key, Func converter) + { + return collection.ToLookup().GetValues(key, converter); + } + + #endregion + + /// Converts the to an . + /// The collection. + /// An instance. + /// is null + public static ILookup ToLookup(this NameValueCollection collection) + { + Requires.NotNull("collection", collection); + return collection.AllKeys + .SelectMany(key => ParseValues(key, collection.GetValues(key))) + .ToLookup(pair => pair.Key, pair => pair.Value); + } + + #region Private Methods + + /// Converts the into a instance. + /// The type of the value to return + /// The value to convert. + /// A instance. + /// + /// the value is null and is a value type, or + /// the value does not implement the interface and + /// no cast is defined from the value to + /// + private static T ConvertValue(object value) + { + if (value is T) + { + return (T)value; + } + + if (value is IConvertible) + { + return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture); + } + + if (value == null) + { + if (typeof(T).IsValueType) + { + // TODO: this should probably return the default value if called from GetOrDefault... + throw new InvalidCastException(); + } + + return (T)value; // null + } + + if (typeof(T) == typeof(string)) + { + return (T)(object)value.ToString(); + } + + return (T)value; + } + + /// Converts the into a instance. + /// The type of the value to return + /// The value to convert. + /// A function to convert a to a instance. + /// A instance. + private static T ConvertValue(object value, Func converter) + { + var formattable = value as IFormattable; + return converter(value == null ? null : formattable == null ? value.ToString() : formattable.ToString(null, CultureInfo.InvariantCulture)); + } + + /// Wraps the into instances. + /// The key. + /// The values. + /// A sequence of instances. + private static IEnumerable> ParseValues(string key, string[] values) + { + return (values.Length == 1 + ? values[0].Split(',') + : values).Select(value => new KeyValuePair(key, value)); + } + + /// Converts the to a . + /// The node. + /// A instance. + /// is null + private static Dictionary ToDictionary(this XContainer node) + { + Requires.NotNull("node", node); + return node.Descendants().ToDictionary(n => n.Name.ToString(), n => n.Value); + } + + /// Converts the to a . + /// The node. + /// A instance. + /// is null + private static Dictionary ToDictionary(this IXPathNavigable node) + { + Requires.NotNull("node", node); + return node.CreateNavigator().SelectChildren(XPathNodeType.Element).Cast().ToDictionary(n => n.Name, n => n.Value); + } + + /// Converts the to a for the specific . + /// The lookup. + /// The key. + /// A instance with zero or one key/value. + /// is null + /// There were multiple values for the given key + private static Dictionary ToDictionary(this ILookup lookup, string key) + { + Requires.NotNull("lookup", lookup); + try + { + return lookup[key].ToDictionary(v => key); + } + catch (ArgumentException exc) + { + // TODO: Localize this + throw new InvalidOperationException("There were multiple values for the given key", exc); + } + } + + #endregion + } + +} diff --git a/DNN Platform/Library/Collections/ExclusiveLockStrategy.cs b/DNN Platform/Library/Collections/ExclusiveLockStrategy.cs new file mode 100644 index 00000000000..8d9a37b7c03 --- /dev/null +++ b/DNN Platform/Library/Collections/ExclusiveLockStrategy.cs @@ -0,0 +1,145 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Threading; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public class ExclusiveLockStrategy : ILockStrategy + { + private readonly object _lock = new object(); + + private bool _isDisposed; + private Thread _lockedThread; + + #region ILockStrategy Members + + public ISharedCollectionLock GetReadLock() + { + return GetLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetReadLock(TimeSpan timeout) + { + return GetLock(timeout); + } + + public ISharedCollectionLock GetWriteLock() + { + return GetLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetWriteLock(TimeSpan timeout) + { + return GetLock(timeout); + } + + public bool ThreadCanRead + { + get + { + EnsureNotDisposed(); + return IsThreadLocked(); + } + } + + public bool ThreadCanWrite + { + get + { + EnsureNotDisposed(); + return IsThreadLocked(); + } + } + + public bool SupportsConcurrentReads + { + get + { + return false; + } + } + + public void Dispose() + { + _isDisposed = true; + //todo remove disposable from interface? + } + + #endregion + + private ISharedCollectionLock GetLock(TimeSpan timeout) + { + EnsureNotDisposed(); + if (IsThreadLocked()) + { + throw new LockRecursionException(); + } + + if (Monitor.TryEnter(_lock, timeout)) + { + _lockedThread = Thread.CurrentThread; + return new MonitorLock(this); + } + else + { + throw new ApplicationException("ExclusiveLockStrategy.GetLock timed out"); + } + } + + private ISharedCollectionLock GetLock() + { + EnsureNotDisposed(); + if (IsThreadLocked()) + { + throw new LockRecursionException(); + } + + Monitor.Enter(_lock); + _lockedThread = Thread.CurrentThread; + return new MonitorLock(this); + } + + private bool IsThreadLocked() + { + return Thread.CurrentThread.Equals(_lockedThread); + } + + public void Exit() + { + EnsureNotDisposed(); + Monitor.Exit(_lock); + _lockedThread = null; + } + + private void EnsureNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("ExclusiveLockStrategy"); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/IIndexable.cs b/DNN Platform/Library/Collections/IIndexable.cs new file mode 100644 index 00000000000..5eb3c2f1b08 --- /dev/null +++ b/DNN Platform/Library/Collections/IIndexable.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +namespace DotNetNuke.Collections +{ + /// + /// This interface used to make a class can have index declaration. + /// + internal interface IIndexable + { + object this[string name] { get; set; } + } +} diff --git a/DNN Platform/Library/Collections/ILockStrategy.cs b/DNN Platform/Library/Collections/ILockStrategy.cs new file mode 100644 index 00000000000..799a541c96c --- /dev/null +++ b/DNN Platform/Library/Collections/ILockStrategy.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public interface ILockStrategy : IDisposable + { + bool ThreadCanRead { get; } + bool ThreadCanWrite { get; } + bool SupportsConcurrentReads { get; } + + ISharedCollectionLock GetReadLock(); + + ISharedCollectionLock GetReadLock(TimeSpan timeout); + + ISharedCollectionLock GetWriteLock(); + + ISharedCollectionLock GetWriteLock(TimeSpan timeout); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/IPagedList.cs b/DNN Platform/Library/Collections/IPagedList.cs new file mode 100644 index 00000000000..60f99ef82c1 --- /dev/null +++ b/DNN Platform/Library/Collections/IPagedList.cs @@ -0,0 +1,82 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Collections +{ + // Taken from Rob Conery's Blog post on the ASP.Net MVC PagedList Helper + // http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/ + + /// + /// Provides an interface to a paged list, which contains a snapshot + /// of a single page of data from the data store + /// + /// The type of objects stored in the list + public interface IPagedList : IList + { + /// + /// Gets a boolean indicating if there is a next page available + /// + bool HasNextPage { get; } + + /// + /// Gets a boolean indicating if there is a previous page available + /// + bool HasPreviousPage { get; } + + /// + /// Gets a boolean indicating if this is the first page + /// + bool IsFirstPage { get; } + + /// + /// Gets a boolean indicating if this is the last page + /// + bool IsLastPage { get; } + + /// + /// The no of pages in this list + /// + int PageCount { get; set; } + + /// + /// The index of the page contained in this list + /// + int PageIndex { get; set; } + + /// + /// The size of the page in this list + /// + int PageSize { get; set; } + + /// + /// The total number of objects in the data store + /// + int TotalCount { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/ISharedCollectionLock.cs b/DNN Platform/Library/Collections/ISharedCollectionLock.cs new file mode 100644 index 00000000000..a171dae3141 --- /dev/null +++ b/DNN Platform/Library/Collections/ISharedCollectionLock.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public interface ISharedCollectionLock : IDisposable + { + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/LockingStrategy.cs b/DNN Platform/Library/Collections/LockingStrategy.cs new file mode 100644 index 00000000000..02861584c88 --- /dev/null +++ b/DNN Platform/Library/Collections/LockingStrategy.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Collections.Internal +{ + public enum LockingStrategy + { + ReaderWriter = 0, + Exclusive + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/LockingStrategyFactory.cs b/DNN Platform/Library/Collections/LockingStrategyFactory.cs new file mode 100644 index 00000000000..a66a428f39d --- /dev/null +++ b/DNN Platform/Library/Collections/LockingStrategyFactory.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + internal class LockingStrategyFactory + { + public static ILockStrategy Create(LockingStrategy strategy) + { + switch (strategy) + { + case LockingStrategy.ReaderWriter: + + return new ReaderWriterLockStrategy(); + case LockingStrategy.Exclusive: + + return new ExclusiveLockStrategy(); + default: + + throw new ArgumentOutOfRangeException(); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/MonitorLock.cs b/DNN Platform/Library/Collections/MonitorLock.cs new file mode 100644 index 00000000000..e7a6bd7c2b3 --- /dev/null +++ b/DNN Platform/Library/Collections/MonitorLock.cs @@ -0,0 +1,78 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + internal class MonitorLock : IDisposable, ISharedCollectionLock + { + private ExclusiveLockStrategy _lockStrategy; + + public MonitorLock(ExclusiveLockStrategy lockStrategy) + { + _lockStrategy = lockStrategy; + } + + #region "IDisposable Support" + + // To detect redundant calls + private bool _isDisposed; + + // IDisposable + + //override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources. + //Protected Overrides Sub Finalize() + // ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. + // Dispose(False) + // MyBase.Finalize() + //End Sub + + // This code added by Visual Basic to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _lockStrategy.Exit(); + _lockStrategy = null; + } + + // TODO: free unmanaged resources (unmanaged objects) and override Finalize() below. + // TODO: set large fields to null. + } + _isDisposed = true; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/NaiveLockingList.cs b/DNN Platform/Library/Collections/NaiveLockingList.cs new file mode 100644 index 00000000000..6b16c103adb --- /dev/null +++ b/DNN Platform/Library/Collections/NaiveLockingList.cs @@ -0,0 +1,221 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections; +using System.Collections.Generic; + +namespace DotNetNuke.Collections.Internal +{ + public class NaiveLockingList : IList + { + private readonly SharedList _list = new SharedList(); + //TODO is no recursion the correct policy + + void DoInReadLock(Action action) + { + DoInReadLock(() =>{ action.Invoke(); return true; }); + } + + TRet DoInReadLock(Func func) + { + using (_list.GetReadLock()) + { + return func.Invoke(); + } + } + + void DoInWriteLock(Action action) + { + DoInWriteLock(() => { action.Invoke(); return true; }); + } + + private TRet DoInWriteLock(Func func) + { + using (_list.GetWriteLock()) + { + return func.Invoke(); + } + } + + /// + /// Access to the underlying SharedList + /// + /// Allows locking to be explicitly managed for the sake of effeciency + /// + /// + public SharedList SharedList + { + get + { + return _list; + } + } + + public IEnumerator GetEnumerator() + { + //disposal of enumerator will release read lock + //TODO is there a need for some sort of timed release? the timmer must release from the correct thread + //if using RWLS + var readLock = _list.GetReadLock(); + return new NaiveLockingEnumerator(_list.GetEnumerator(), readLock); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T item) + { + DoInWriteLock(() => _list.Add(item)); + } + + public void Clear() + { + DoInWriteLock(() => _list.Clear()); + } + + public bool Contains(T item) + { + return DoInReadLock(() => _list.Contains(item)); + } + + public void CopyTo(T[] array, int arrayIndex) + { + DoInReadLock(() => _list.CopyTo(array, arrayIndex)); + } + + public bool Remove(T item) + { + return DoInWriteLock(() => _list.Remove(item)); + } + + public int Count + { + get + { + return DoInReadLock(() => _list.Count); + } + } + + public bool IsReadOnly + { + get + { + return false; + } + } + + public int IndexOf(T item) + { + return DoInReadLock(() => _list.IndexOf(item)); + } + + public void Insert(int index, T item) + { + DoInWriteLock(() => _list.Insert(index, item)); + } + + public void RemoveAt(int index) + { + DoInWriteLock(() => _list.RemoveAt(index)); + } + + public T this[int index] + { + get + { + return DoInReadLock(() => _list[index]); + } + set + { + DoInWriteLock(() => _list[index] = value); + } + } + + public class NaiveLockingEnumerator : IEnumerator + { + private readonly IEnumerator _enumerator; + private bool _isDisposed; + private readonly ISharedCollectionLock _readLock; + + public NaiveLockingEnumerator(IEnumerator enumerator, ISharedCollectionLock readLock) + { + _enumerator = enumerator; + _readLock = readLock; + } + + public bool MoveNext() + { + return _enumerator.MoveNext(); + } + + public void Reset() + { + _enumerator.Reset(); + } + + public T Current + { + get + { + return _enumerator.Current; + } + } + + object IEnumerator.Current + { + get + { + return Current; + } + } + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + //dispose managed resrources here + _enumerator.Dispose(); + _readLock.Dispose(); + } + + //dispose unmanaged resrources here + _isDisposed = true; + } + } + + ~NaiveLockingEnumerator() + { + Dispose(false); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/PagedList.cs b/DNN Platform/Library/Collections/PagedList.cs new file mode 100644 index 00000000000..c88dba31455 --- /dev/null +++ b/DNN Platform/Library/Collections/PagedList.cs @@ -0,0 +1,152 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; + +#endregion + +namespace DotNetNuke.Collections +{ + // Taken from Rob Conery's Blog post on the ASP.Net MVC PagedList Helper + // http://blog.wekeroad.com/2007/12/10/aspnet-mvc-pagedlistt/ + + /// + /// Represents a snapshot of a single page of objects from a data store + /// + /// The type of objects contained in this list + public class PagedList : List, IPagedList + { + #region Constructors + + /// + /// Creates a paged list containing objects from the selected enumerable source + /// + /// The data store containing objects to be retrieved + /// The index of the page to retrieve + /// The size of the page to retrieve + public PagedList(IEnumerable source, int pageIndex, int pageSize) + { + var enumerable = source as T[] ?? source.ToArray(); + CommonConstruct(enumerable.Skip(pageIndex * pageSize).Take(pageSize).ToList(), enumerable.Count(), pageIndex, pageSize); + } + + /// + /// Creates a paged list containing objects from a collection of items + /// + /// The items that constitute the page + /// The total number of items in the original source + /// The index of the page to retrieve + /// The size of the page to retrieve + public PagedList(IEnumerable items, int totalCount, int pageIndex, int pageSize) + { + CommonConstruct(items, totalCount, pageIndex, pageSize); + } + + #endregion + + #region Private Methods + + private void CommonConstruct(IEnumerable items, int totalCount, int pageIndex, int pageSize) + { + PageCount = (int)Math.Ceiling(totalCount / (double)pageSize); + + if (PageCount == 0) + { + if (pageIndex > 0) + { + throw new IndexOutOfRangeException("Invalid Page Index"); + } + } + else + { + if (pageIndex < 0) + { + throw new IndexOutOfRangeException("Index cannot be negative"); + } + if (pageIndex >= PageCount) + { + throw new IndexOutOfRangeException("Invalid Page Index"); + } + } + TotalCount = totalCount; + PageSize = pageSize; + PageIndex = pageIndex; + AddRange(items); + + HasNextPage = (PageIndex < (PageCount - 1)); + HasPreviousPage = (PageIndex > 0); + IsFirstPage = (PageIndex <= 0); + IsLastPage = (PageIndex >= (PageCount - 1)); + } + + #endregion + + #region IPagedList Members + + /// + /// Gets a boolean indicating if there is a next page available + /// + public bool HasNextPage { get; private set; } + + /// + /// Gets a boolean indicating if there is a previous page available + /// + public bool HasPreviousPage { get; private set; } + + /// + /// Gets a boolean indicating if this is the first page + /// + public bool IsFirstPage { get; private set; } + + /// + /// Gets a boolean indicating if this is the last page + /// + public bool IsLastPage { get; private set; } + + /// + /// The no of pages in this list + /// + public int PageCount { get; set; } + + /// + /// The index of the page contained in this list + /// + public int PageIndex { get; set; } + + /// + /// The size of the page in this list + /// + public int PageSize { get; set; } + + /// + /// The total number of objects in the data store + /// + public int TotalCount { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/PagedSelector.cs b/DNN Platform/Library/Collections/PagedSelector.cs new file mode 100644 index 00000000000..035afc04e30 --- /dev/null +++ b/DNN Platform/Library/Collections/PagedSelector.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DotNetNuke.Collections +{ + /// + /// Provides options to allow the consumer to select a page of data from a paged data store + /// + /// The type of object in the data store + public class PageSelector + { + private readonly int _pageSize; + private readonly IEnumerable _source; + + #region Constructors + + /// + /// Constructs a new PageSelector for use on the specified data store + /// + /// The data store to page + /// The size of each page + public PageSelector(IEnumerable source, int pageSize) + { + _source = source; + _pageSize = pageSize; + } + + #endregion + + #region Public Methods + + /// + /// Retrieves the specified page as a + /// + /// The index (zero-based) of the page to retrieve + /// + /// An containing the page of data, or an + /// empty list if the page does not exist + /// + public IPagedList GetPage(int pageIndex) + { + return new PagedList(_source, pageIndex, _pageSize); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Collections/PagingExtensions.cs b/DNN Platform/Library/Collections/PagingExtensions.cs new file mode 100644 index 00000000000..c6328b211b1 --- /dev/null +++ b/DNN Platform/Library/Collections/PagingExtensions.cs @@ -0,0 +1,68 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Collections +{ + /// + /// Contains filters that can be applied to stores + /// + public static class PagingExtensions + { + #region Public Extension Methods + + /// + /// Filters the incoming store to retrieve pages of a specified size. + /// + /// The type of the object being filtered + /// The source object being filtered + /// The page size to use + /// + /// A object that is used to select a single + /// page of data from the data source. + /// + public static PageSelector InPagesOf(this IEnumerable source, int pageSize) + { + return new PageSelector(source, pageSize); + } + + /// + /// + /// + /// + /// + /// + /// + public static IPagedList ToPagedList(this IEnumerable source, int pageIndex, int pageSize) + { + return new PagedList(source, pageIndex, pageSize); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/ReadLockRequiredException.cs b/DNN Platform/Library/Collections/ReadLockRequiredException.cs new file mode 100644 index 00000000000..e05cc7e6ad5 --- /dev/null +++ b/DNN Platform/Library/Collections/ReadLockRequiredException.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public class ReadLockRequiredException : Exception + { + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/ReaderWriterLockStrategy.cs b/DNN Platform/Library/Collections/ReaderWriterLockStrategy.cs new file mode 100644 index 00000000000..9427bb3b665 --- /dev/null +++ b/DNN Platform/Library/Collections/ReaderWriterLockStrategy.cs @@ -0,0 +1,186 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; +using System.Threading; + +namespace DotNetNuke.Collections.Internal +{ + [Serializable] + public class ReaderWriterLockStrategy : IDisposable, ILockStrategy + { + [NonSerialized] + private ReaderWriterLockSlim _lock; + + private LockRecursionPolicy _lockRecursionPolicy; + + private ReaderWriterLockSlim Lock + { + get + { + return _lock ?? (_lock = new ReaderWriterLockSlim(_lockRecursionPolicy)); + } + } + + // Implement this method to serialize data. The method is called + // on serialization. + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + // Use the AddValue method to specify serialized values. + info.AddValue("_lockRecursionPolicy", _lockRecursionPolicy, typeof(LockRecursionPolicy)); + } + + public ReaderWriterLockStrategy() + : this(LockRecursionPolicy.NoRecursion) + { + } + + public ReaderWriterLockStrategy(LockRecursionPolicy recursionPolicy) + { + _lockRecursionPolicy = recursionPolicy; + _lock = new ReaderWriterLockSlim(recursionPolicy); + } + + // The special constructor is used to deserialize values. + public ReaderWriterLockStrategy(SerializationInfo info, StreamingContext context) + { + _lockRecursionPolicy = (LockRecursionPolicy)info.GetValue("_lockRecursionPolicy", typeof(LockRecursionPolicy)); + _lock = new ReaderWriterLockSlim(_lockRecursionPolicy); + } + + #region ILockStrategy Members + + public ISharedCollectionLock GetReadLock() + { + return GetReadLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetReadLock(TimeSpan timeout) + { + EnsureNotDisposed(); + if (Lock.TryEnterReadLock(timeout)) + { + return new ReaderWriterSlimLock(Lock); + } + else + { + throw new ApplicationException("ReaderWriterLockStrategy.GetReadLock timed out"); + } + } + + public ISharedCollectionLock GetWriteLock() + { + return GetWriteLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetWriteLock(TimeSpan timeout) + { + EnsureNotDisposed(); + if (Lock.TryEnterWriteLock(timeout)) + { + return new ReaderWriterSlimLock(Lock); + } + else + { + throw new ApplicationException("ReaderWriterLockStrategy.GetWriteLock timed out"); + } + } + + public bool ThreadCanRead + { + get + { + EnsureNotDisposed(); + return Lock.IsReadLockHeld || Lock.IsWriteLockHeld; + //todo uncomment if upgradelock is used OrElse _lock.IsUpgradeableReadLockHeld + } + } + + public bool ThreadCanWrite + { + get + { + EnsureNotDisposed(); + return Lock.IsWriteLockHeld; + } + } + + public bool SupportsConcurrentReads + { + get + { + return true; + } + } + + #endregion + + #region "IDisposable Support" + + private bool _isDisposed; + + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. + Dispose(true); + GC.SuppressFinalize(this); + } + + private void EnsureNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("ReaderWriterLockStrategy"); + } + } + + // To detect redundant calls + + // IDisposable + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + //dispose managed state (managed objects). + } + + if (_lock != null) + { + _lock.Dispose(); + _lock = null; + } + } + _isDisposed = true; + } + + ~ReaderWriterLockStrategy() + { + // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. + Dispose(false); + } + + // This code added by Visual Basic to correctly implement the disposable pattern. + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/ReaderWriterSlimLock.cs b/DNN Platform/Library/Collections/ReaderWriterSlimLock.cs new file mode 100644 index 00000000000..18dd13af9f7 --- /dev/null +++ b/DNN Platform/Library/Collections/ReaderWriterSlimLock.cs @@ -0,0 +1,92 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Threading; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + internal class ReaderWriterSlimLock : ISharedCollectionLock + { + private bool _disposed; + private ReaderWriterLockSlim _lock; + + public ReaderWriterSlimLock(ReaderWriterLockSlim @lock) + { + _lock = @lock; + } + + #region ISharedCollectionLock Members + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + #endregion + + private void EnsureNotDisposed() + { + if (_disposed) + { + throw new ObjectDisposedException("ReaderWriterSlimLock"); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + //free managed resources here + } + + //free unmanaged resrources here + if (_lock.IsReadLockHeld) + { + _lock.ExitReadLock(); + } + else if (_lock.IsWriteLockHeld) + { + _lock.ExitWriteLock(); + } + else if (_lock.IsUpgradeableReadLockHeld) + { + _lock.ExitUpgradeableReadLock(); + } + + _lock = null; + _disposed = true; + } + } + + ~ReaderWriterSlimLock() + { + Dispose(false); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/SharedDictionary.cs b/DNN Platform/Library/Collections/SharedDictionary.cs new file mode 100644 index 00000000000..f3c9d714e2a --- /dev/null +++ b/DNN Platform/Library/Collections/SharedDictionary.cs @@ -0,0 +1,293 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + [Serializable] + public class SharedDictionary : IDictionary, IDisposable + { + private IDictionary _dict; + + private bool _isDisposed; + private ILockStrategy _lockController; + + public SharedDictionary() : this(LockingStrategy.ReaderWriter) + { + } + + public SharedDictionary(ILockStrategy lockStrategy) + { + _dict = new Dictionary(); + _lockController = lockStrategy; + } + + public SharedDictionary(LockingStrategy strategy) : this(LockingStrategyFactory.Create(strategy)) + { + } + + internal IDictionary BackingDictionary + { + get + { + return _dict; + } + } + + #region IDictionary Members + + IEnumerator> IEnumerable>.GetEnumerator() + { + return IEnumerable_GetEnumerator(); + } + + public IEnumerator GetEnumerator() + { + return IEnumerable_GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _dict.Add(item); + } + + public void Clear() + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _dict.Clear(); + } + + public bool Contains(KeyValuePair item) + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + EnsureNotDisposed(); + EnsureReadAccess(); + _dict.CopyTo(array, arrayIndex); + } + + public bool Remove(KeyValuePair item) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + return _dict.Remove(item); + } + + public int Count + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.Count; + } + } + + public bool IsReadOnly + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.IsReadOnly; + } + } + + public bool ContainsKey(TKey key) + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.ContainsKey(key); + } + + public void Add(TKey key, TValue value) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _dict.Add(key, value); + } + + public bool Remove(TKey key) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + return _dict.Remove(key); + } + + public bool TryGetValue(TKey key, out TValue value) + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.TryGetValue(key, out value); + } + + public TValue this[TKey key] + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict[key]; + } + set + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _dict[key] = value; + } + } + + public ICollection Keys + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.Keys; + } + } + + public ICollection Values + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _dict.Values; + } + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + #endregion + + public ISharedCollectionLock GetReadLock() + { + return GetReadLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetReadLock(TimeSpan timeOut) + { + EnsureNotDisposed(); + return _lockController.GetReadLock(timeOut); + } + + public ISharedCollectionLock GetReadLock(int millisecondTimeout) + { + return GetReadLock(TimeSpan.FromMilliseconds(millisecondTimeout)); + } + + public ISharedCollectionLock GetWriteLock() + { + return GetWriteLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetWriteLock(TimeSpan timeOut) + { + EnsureNotDisposed(); + return _lockController.GetWriteLock(timeOut); + } + + public ISharedCollectionLock GetWriteLock(int millisecondTimeout) + { + return GetWriteLock(TimeSpan.FromMilliseconds(millisecondTimeout)); + } + + + private void EnsureReadAccess() + { + if (!(_lockController.ThreadCanRead)) + { + throw new ReadLockRequiredException(); + } + } + + private void EnsureWriteAccess() + { + if (!_lockController.ThreadCanWrite) + { + throw new WriteLockRequiredException(); + } + } + + public IEnumerator> IEnumerable_GetEnumerator() + { + EnsureNotDisposed(); + EnsureReadAccess(); + + //todo nothing ensures read lock is held for life of enumerator + return _dict.GetEnumerator(); + } + + private void EnsureNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("SharedDictionary"); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + //dispose managed resrources here + _dict = null; + } + + //dispose unmanaged resrources here + _lockController.Dispose(); + _lockController = null; + _isDisposed = true; + } + } + + ~SharedDictionary() + { + Dispose(false); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/SharedList.cs b/DNN Platform/Library/Collections/SharedList.cs new file mode 100644 index 00000000000..7d94e3eb838 --- /dev/null +++ b/DNN Platform/Library/Collections/SharedList.cs @@ -0,0 +1,261 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public class SharedList : IList, IDisposable + { + private readonly List _list = new List(); + private ILockStrategy _lockStrategy; + + public SharedList() : this(LockingStrategy.ReaderWriter) + { + } + + public SharedList(ILockStrategy lockStrategy) + { + _lockStrategy = lockStrategy; + } + + public SharedList(LockingStrategy strategy) : this(LockingStrategyFactory.Create(strategy)) + { + } + + internal IList BackingList + { + get + { + return _list; + } + } + + #region IList Members + + public void Add(T item) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _list.Add(item); + } + + public void Clear() + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _list.Clear(); + } + + public bool Contains(T item) + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _list.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + EnsureNotDisposed(); + EnsureReadAccess(); + _list.CopyTo(array, arrayIndex); + } + + public int Count + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _list.Count; + } + } + + public bool IsReadOnly + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return ((ICollection) _list).IsReadOnly; + } + } + + public bool Remove(T item) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + return _list.Remove(item); + } + + public IEnumerator GetEnumerator() + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _list.GetEnumerator(); + } + + public int IndexOf(T item) + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _list.IndexOf(item); + } + + public void Insert(int index, T item) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _list.Insert(index, item); + } + + public T this[int index] + { + get + { + EnsureNotDisposed(); + EnsureReadAccess(); + return _list[index]; + } + set + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _list[index] = value; + } + } + + public void RemoveAt(int index) + { + EnsureNotDisposed(); + EnsureWriteAccess(); + _list.RemoveAt(index); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator1(); + } + + #endregion + + #region "IDisposable Support" + + private bool _isDisposed; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // To detect redundant calls + + public void EnsureNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("SharedList"); + } + } + + // IDisposable + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + // dispose managed state (managed objects). + } + + _lockStrategy.Dispose(); + _lockStrategy = null; + } + _isDisposed = true; + } + + ~SharedList() + { + Dispose(false); + } + + #endregion + + public ISharedCollectionLock GetReadLock() + { + return GetReadLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetReadLock(TimeSpan timeOut) + { + EnsureNotDisposed(); + return _lockStrategy.GetReadLock(timeOut); + } + + public ISharedCollectionLock GetReadLock(int millisecondTimeout) + { + return GetReadLock(TimeSpan.FromMilliseconds(millisecondTimeout)); + } + + public ISharedCollectionLock GetWriteLock() + { + return GetWriteLock(TimeSpan.FromMilliseconds(-1)); + } + + public ISharedCollectionLock GetWriteLock(TimeSpan timeOut) + { + EnsureNotDisposed(); + return _lockStrategy.GetWriteLock(timeOut); + } + + public ISharedCollectionLock GetWriteLock(int millisecondTimeout) + { + return GetWriteLock(TimeSpan.FromMilliseconds(millisecondTimeout)); + } + + private void EnsureReadAccess() + { + if (!(_lockStrategy.ThreadCanRead)) + { + throw new ReadLockRequiredException(); + } + } + + private void EnsureWriteAccess() + { + if (!_lockStrategy.ThreadCanWrite) + { + throw new WriteLockRequiredException(); + } + } + + public IEnumerator GetEnumerator1() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Collections/WriteLockRequiredException.cs b/DNN Platform/Library/Collections/WriteLockRequiredException.cs new file mode 100644 index 00000000000..019fca2d80d --- /dev/null +++ b/DNN Platform/Library/Collections/WriteLockRequiredException.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Collections.Internal +{ + public class WriteLockRequiredException : Exception + { + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Assembly.cs b/DNN Platform/Library/Common/Assembly.cs new file mode 100644 index 00000000000..157ac596bae --- /dev/null +++ b/DNN Platform/Library/Common/Assembly.cs @@ -0,0 +1,81 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using Microsoft.VisualBasic.CompilerServices; + +#endregion + +namespace DotNetNuke.Common +{ + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + [StandardModule] + public sealed class Assembly + { + #region Public Constants + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppType = "Framework"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppVersion = "05.01.00"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppName = "DNNCORP.PE"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppTitle = "DotNetNuke"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppDescription = "DotNetNuke Professional Edition"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppCompany = "DotNetNuke Corporation"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbAppUrl = "http://www.dotnetnuke.com"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbUpgradeUrl = "http://update.dotnetnuke.com"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbLegalCopyright = "DotNetNuke® is copyright 2002-YYYY by DotNetNuke Corporation"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbTrademark = "DotNetNuke,DNN"; + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public const string glbHelpUrl = "http://www.dotnetnuke.com/default.aspx?tabid=787"; + + #endregion + + [Obsolete("Deprecated in DNN 5.1. Use DotNetNukeContext.Current.Application properties.")] + public static Version ApplicationVersion + { + get + { + return new Version("05.01.00"); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Controls/ActionLessForm.cs b/DNN Platform/Library/Common/Controls/ActionLessForm.cs new file mode 100644 index 00000000000..78fcfb478b7 --- /dev/null +++ b/DNN Platform/Library/Common/Controls/ActionLessForm.cs @@ -0,0 +1,65 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; + +#endregion + +namespace DotNetNuke.Common.Controls +{ + /// + /// The Form will reset action to raw url instead of rewrite url. + /// + public class Form : HtmlForm + { + protected override void RenderAttributes(HtmlTextWriter writer) + { + var stringWriter = new StringWriter(); + var htmlWriter = new HtmlTextWriter(stringWriter); + base.RenderAttributes(htmlWriter); + string html = stringWriter.ToString(); + // Locate and replace action attribute + int StartPoint = html.IndexOf("action=\""); + if (StartPoint >= 0) + { + int EndPoint = html.IndexOf("\"", StartPoint + 8) + 1; + html = html.Remove(StartPoint, EndPoint - StartPoint); + html = html.Insert(StartPoint, "action=\"" + HttpUtility.HtmlEncode(HttpContext.Current.Request.RawUrl) + "\""); + } + if (base.ID != null) + { + // Locate and replace id attribute + StartPoint = html.IndexOf("id=\""); + if (StartPoint >= 0) + { + int EndPoint = html.IndexOf("\"", StartPoint + 4) + 1; + html = html.Remove(StartPoint, EndPoint - StartPoint); + html = html.Insert(StartPoint, "id=\"" + base.ClientID + "\""); + } + } + writer.Write(html); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/FileItem.cs b/DNN Platform/Library/Common/FileItem.cs new file mode 100644 index 00000000000..e986e64eaec --- /dev/null +++ b/DNN Platform/Library/Common/FileItem.cs @@ -0,0 +1,51 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Common +{ + /// + /// This class handles basic elements about File Items. Is is a basic Get/Set for Value and Text + /// + public class FileItem + { + /// + /// Initializes a new instance of the class. + /// + /// The value. + /// The text. + public FileItem(string value, string text) + { + Value = value; + Text = text; + } + + /// + /// Gets the text. + /// + /// The text. + public string Text { get; private set; } + + /// + /// Gets the value. + /// + /// The value. + public string Value { get; private set; } + } +} diff --git a/DNN Platform/Library/Common/Globals.cs b/DNN Platform/Library/Common/Globals.cs new file mode 100644 index 00000000000..e0e0a99c7ef --- /dev/null +++ b/DNN Platform/Library/Common/Globals.cs @@ -0,0 +1,4287 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.Caching; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Xml; + +using DotNetNuke.Application; +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework.Providers; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Url.FriendlyUrl; +using DotNetNuke.UI.Skins; +using DotNetNuke.UI.Utilities; + +using Microsoft.VisualBasic.CompilerServices; + +using DataCache = DotNetNuke.UI.Utilities.DataCache; +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; + +#endregion + +namespace DotNetNuke.Common +{ + /// + /// The global instance of DotNetNuke. all basic functions and properties are defined in this instance. + /// + [StandardModule] + public sealed class Globals + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Globals)); + #region PerformanceSettings enum + + /// + /// Enumeration of site performance setting, say by another way that means how to set the cache. + /// + /// + /// Using cache will speed up the application to a great degree, we recommend to use cache for whole modules, + /// but sometimes cache also make confuse for user, if we didn't take care of how to make cache expired when needed, + /// such as if a data has already been deleted but the cache arn't clear, it will cause un expected errors. + /// so you should choose a correct performance setting type when you trying to cache some stuff, and always remember + /// update cache immediately after the data changed. + /// default cache policy in core api will use cache timeout muitple Host Performance setting's value as cache time(unit: minutes): + /// + /// HostSettingsCacheTimeOut: 20 + /// PortalAliasCacheTimeOut: 200 + /// PortalSettingsCacheTimeOut: 20 + /// More cache timeout definitions see + /// + /// + public enum PerformanceSettings + { + /// + /// No Caching + /// + NoCaching = 0, + /// + /// Caching for a short time + /// + LightCaching = 1, + /// + /// Caching for moderate + /// + ModerateCaching = 3, + /// + /// Caching for a long time + /// + HeavyCaching = 6 + } + + #endregion + + #region PortalRegistrationType enum + + /// + /// Enumeration Of Registration Type for portal. + /// + /// + /// NoRegistration: Disabled registration in portal. + /// PrivateRegistration: Once user's account information has been submitted, + /// the portal Administrator will be notified and user's application will be subjected to a screening procedure. + /// If user's application is authorized, the user will receive notification of access to the portal environment. + /// PublicRegistration: Once user's account information has been submitted, + /// user will be immediately granted access to the portal environment. + /// VerifiedRegistration: Once user's account information has been submitted, + /// user will receive an email containing unique Verification Code. + /// The Verification Code will be required the first time when user attempt to sign in to the portal environment. + /// + public enum PortalRegistrationType + { + /// + /// Disabled Registration + /// + NoRegistration = 0, + /// + /// Account need be approved by portal's administrator. + /// + PrivateRegistration = 1, + /// + /// Account will be available after post registration data successful. + /// + PublicRegistration = 2, + /// + /// Account will be available by verify code. + /// + VerifiedRegistration = 3 + } + + #endregion + + #region UpgradeStatus enum + + /// + /// Enumeration Of Application upgrade status. + /// + public enum UpgradeStatus + { + /// + /// The application need update to a higher version. + /// + Upgrade, + /// + /// The application need to install itself. + /// + Install, + /// + /// The application is normal running. + /// + None, + /// + /// The application occur error when running. + /// + Error, + /// + /// The application status is unknown, + /// + /// This status should never be returned. its is only used as a flag that Status hasn't been determined. + Unknown + } + + #endregion + + /// + /// Global role id for all users + /// + /// -1 + public const string glbRoleAllUsers = "-1"; + + /// + /// Global role id for super user + /// + /// -2 + public const string glbRoleSuperUser = "-2"; + + /// + /// Global role id for unauthenticated users + /// + /// -3 + public const string glbRoleUnauthUser = "-3"; + + /// + /// Global role id by default + /// + /// -4 + public const string glbRoleNothing = "-4"; + + /// + /// Global role name for all users + /// + /// All Users + public const string glbRoleAllUsersName = "All Users"; + + /// + /// Global ro name for super user + /// + /// Superuser + public const string glbRoleSuperUserName = "Superuser"; + + /// + /// Global role name for unauthenticated users + /// + /// Unauthenticated Users + public const string glbRoleUnauthUserName = "Unauthenticated Users"; + + /// + /// Default page name + /// + /// Default.aspx + public const string glbDefaultPage = "Default.aspx"; + + /// + /// Default host skin folder + /// + /// _default + public const string glbHostSkinFolder = "_default"; + + /// + /// Default control panel + /// + /// Admin/ControlPanel/IconBar.ascx + public const string glbDefaultControlPanel = "Admin/ControlPanel/IconBar.ascx"; + + /// + /// Default pane name + /// + /// ContentPane + public const string glbDefaultPane = "ContentPane"; + + /// + /// Image file types + /// + /// jpg,jpeg,jpe,gif,bmp,png,swf + public const string glbImageFileTypes = "jpg,jpeg,jpe,gif,bmp,png"; + + /// + /// Config files folder + /// + /// \Config\ + public const string glbConfigFolder = "\\Config\\"; + + /// + /// About page name + /// + /// about.htm + public const string glbAboutPage = "about.htm"; + + /// + /// DotNetNuke config file + /// + /// DotNetNuke.config + public const string glbDotNetNukeConfig = "DotNetNuke.config"; + + /// + /// Default portal id for super user + /// + /// -1 + public const int glbSuperUserAppName = -1; + + /// + /// extension of protected files + /// + /// .resources + public const string glbProtectedExtension = ".resources"; + + /// + /// Default container folder + /// + /// Portals/_default/Containers/ + public const string glbContainersPath = "Portals/_default/Containers/"; + + /// + /// Default skin folder + /// + /// Portals/_default/Skins/ + public const string glbSkinsPath = "Portals/_default/Skins/"; + + /// + /// Email address regex pattern + /// + /// + public const string glbEmailRegEx = + @"^\s*[a-zA-Z0-9_%+#&'*/=^`{|}~-](?:\.?[a-zA-Z0-9_%+#&'*/=^`{|}~-])*@(?:[a-zA-Z0-9_](?:(?:\.?|-*)[a-zA-Z0-9_])*\.[a-zA-Z]{2,9}|\[(?:2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?:2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?:2[0-4]\d|25[0-5]|[01]?\d\d?)\.(?:2[0-4]\d|25[0-5]|[01]?\d\d?)])\s*$"; + + /// + /// User Name regex pattern + /// + /// + public const string glbUserNameRegEx = @""; + + /// + /// format of a script tag + /// + /// ]]> + public const string glbScriptFormat = ""; + + // global constants for the life of the application ( set in Application_Start ) + private static string _applicationPath; + private static string _applicationMapPath; + private static string _desktopModulePath; + private static string _imagePath; + private static string _hostMapPath; + private static string _hostPath; + private static string _installMapPath; + private static string _installPath; + private static Version _dataBaseVersion; + private static UpgradeStatus _status = UpgradeStatus.Unknown; + + /// + /// Gets the application path. + /// + public static string ApplicationPath + { + get + { + if (_applicationPath == null && (HttpContext.Current != null)) + { + if (HttpContext.Current.Request.ApplicationPath == "/") + { + _applicationPath = string.IsNullOrEmpty(Config.GetSetting("InstallationSubfolder")) ? "" : (Config.GetSetting("InstallationSubfolder") + "/").ToLowerInvariant(); + } + else + { + _applicationPath = HttpContext.Current.Request.ApplicationPath.ToLowerInvariant(); + } + } + + return _applicationPath; + } + } + + /// + /// Gets or sets the application map path. + /// + /// + /// The application map path. + /// + public static string ApplicationMapPath + { + get + { + return _applicationMapPath ?? (_applicationMapPath = GetCurrentDomainDirectory()); + } + } + + private static string GetCurrentDomainDirectory() + { + var dir = AppDomain.CurrentDomain.BaseDirectory.Replace("/", "\\"); + if (dir.Length > 3 && dir.EndsWith("\\")) + { + dir = dir.Substring(0, dir.Length - 1); + } + return dir; + } + + /// + /// Gets the desktop module path. + /// + /// ApplicationPath + "/DesktopModules/" + public static string DesktopModulePath + { + get + { + if (_desktopModulePath == null) + { + _desktopModulePath = ApplicationPath + "/DesktopModules/"; + } + return _desktopModulePath; + } + } + + /// + /// Gets the image path. + /// + /// ApplicationPath + "/Images/" + public static string ImagePath + { + get + { + if (_imagePath == null) + { + _imagePath = ApplicationPath + "/Images/"; + } + return _imagePath; + } + } + + /// + /// Gets the database version. + /// + public static Version DataBaseVersion + { + get + { + return _dataBaseVersion; + } + } + + /// + /// Gets or sets the host map path. + /// + /// ApplicationMapPath + "Portals\_default\" + public static string HostMapPath + { + get + { + if (_hostMapPath == null) + { + _hostMapPath = Path.Combine(ApplicationMapPath, @"Portals\_default\"); + } + return _hostMapPath; + } + } + + /// + /// Gets or sets the host path. + /// + /// ApplicationPath + "/Portals/_default/" + public static string HostPath + { + get + { + if (_hostPath == null) + { + _hostPath = ApplicationPath + "/Portals/_default/"; + } + return _hostPath; + } + } + + /// + /// Gets or sets the install map path. + /// + /// server map path of InstallPath. + public static string InstallMapPath + { + get + { + if (_installMapPath == null) + { + _installMapPath = HttpContext.Current.Server.MapPath(InstallPath); + } + return _installMapPath; + } + } + + /// + /// Gets or sets the install path. + /// + /// ApplicationPath + "/Install/" + public static string InstallPath + { + get + { + if (_installPath == null) + { + _installPath = ApplicationPath + "/Install/"; + } + return _installPath; + } + } + + /// + /// Gets or sets the name of the IIS app. + /// + /// + /// request.ServerVariables["APPL_MD_PATH"] + /// + public static string IISAppName { get; set; } + + /// + /// Gets or sets the name of the server. + /// + /// + /// server name in config file or the server's marchine name. + /// + public static string ServerName { get; set; } + + /// + /// Gets or sets the operating system version. + /// + /// + /// The operating system version. + /// + public static Version OperatingSystemVersion { get; set; } + + /// + /// Gets or sets the NET framework version. + /// + /// + /// The NET framework version. + /// + public static Version NETFrameworkVersion { get; set; } + + /// + /// Gets or sets the database engine version. + /// + /// + /// The database engine version. + /// + public static Version DatabaseEngineVersion { get; set; } + + /// + /// Redirects the specified URL. + /// + /// The URL. + /// if set to true [end response]. + public static void Redirect(string url, bool endResponse) + { + try + { + HttpContext.Current.Response.Redirect(url, endResponse); + } + catch (ThreadAbortException) + { + //we are ignoreing this error simply because there is no graceful way to redirect the user, wihtout the threadabort exception. + //RobC + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + /// + /// Gets the status of application. + /// + /// + public static UpgradeStatus Status + { + get + { + if (_status == UpgradeStatus.Unknown) + { + var tempStatus = UpgradeStatus.Unknown; + + Logger.Trace("Getting application status"); + tempStatus = UpgradeStatus.None; + //first call GetProviderPath - this insures that the Database is Initialised correctly + //and also generates the appropriate error message if it cannot be initialised correctly + string strMessage = DataProvider.Instance().GetProviderPath(); + //get current database version from DB + if (!strMessage.StartsWith("ERROR:")) + { + try + { + _dataBaseVersion = DataProvider.Instance().GetVersion(); + } + catch (Exception ex) + { + Logger.Error(ex); + strMessage = "ERROR:" + ex.Message; + } + } + if (strMessage.StartsWith("ERROR")) + { + if (IsInstalled()) + { + //Errors connecting to the database after an initial installation should be treated as errors. + tempStatus = UpgradeStatus.Error; + } + else + { + //An error that occurs before the database has been installed should be treated as a new install + tempStatus = UpgradeStatus.Install; + } + } + else if (DataBaseVersion == null) + { + //No Db Version so Install + tempStatus = UpgradeStatus.Install; + } + else + { + if (DotNetNukeContext.Current.Application.Version.Major > DataBaseVersion.Major) + { + //Upgrade Required (Major Version Upgrade) + tempStatus = UpgradeStatus.Upgrade; + } + else if (DotNetNukeContext.Current.Application.Version.Major == DataBaseVersion.Major && DotNetNukeContext.Current.Application.Version.Minor > DataBaseVersion.Minor) + { + //Upgrade Required (Minor Version Upgrade) + tempStatus = UpgradeStatus.Upgrade; + } + else if (DotNetNukeContext.Current.Application.Version.Major == DataBaseVersion.Major && DotNetNukeContext.Current.Application.Version.Minor == DataBaseVersion.Minor && + DotNetNukeContext.Current.Application.Version.Build > DataBaseVersion.Build) + { + //Upgrade Required (Build Version Upgrade) + tempStatus = UpgradeStatus.Upgrade; + } + } + + _status = tempStatus; + + Logger.Trace(string.Format("result of getting providerpath: {0}",strMessage)); + Logger.Trace("Application status is " + _status); + } + return _status; + } + + } + + + /// + /// IsInstalled looks at various file artifacts to determine if DotNetNuke has already been installed. + /// + /// + /// + /// If DotNetNuke has been installed, then we should treat database connection errors as real errors. + /// If DotNetNuke has not been installed, then we should expect to have database connection problems + /// since the connection string may not have been configured yet, which can occur during the installation + /// wizard. + /// + internal static bool IsInstalled() + { + const int c_PassingScore = 4; + int installationdatefactor = Convert.ToInt32(HasInstallationDate() ? 1 : 0); + int dataproviderfactor = Convert.ToInt32(HasDataProviderLogFiles() ? 3 : 0); + int htmlmodulefactor = Convert.ToInt32(ModuleDirectoryExists("html") ? 2 : 0); + int portaldirectoryfactor = Convert.ToInt32(HasNonDefaultPortalDirectory() ? 2 : 0); + int localexecutionfactor = Convert.ToInt32(HttpContext.Current.Request.IsLocal ? c_PassingScore - 1 : 0); + //This calculation ensures that you have a more than one item that indicates you have already installed DNN. + //While it is possible that you might not have an installation date or that you have deleted log files + //it is unlikely that you have removed every trace of an installation and yet still have a working install + + bool isInstalled = (!IsInstallationURL()) && ((installationdatefactor + dataproviderfactor + htmlmodulefactor + portaldirectoryfactor + localexecutionfactor) >= c_PassingScore); + + // we need to tighten this check. We now are enforcing the existence of the InstallVersion value in web.config. If + // this value exists, then DNN was previously installed, and we should never try to re-install it + return isInstalled || HasInstallVersion(); + } + + /// + /// Determines whether has data provider log files. + /// + /// + /// true if has data provider log files; otherwise, false. + /// + private static bool HasDataProviderLogFiles() + { + Provider currentdataprovider = Config.GetDefaultProvider("data"); + string providerpath = currentdataprovider.Attributes["providerPath"]; + //If the provider path does not exist, then there can't be any log files + if (!string.IsNullOrEmpty(providerpath)) + { + providerpath = HttpContext.Current.Server.MapPath(providerpath); + if (Directory.Exists(providerpath)) + { + return Directory.GetFiles(providerpath, "*.log.resources").Length > 0; + } + } + return false; + } + + /// + /// Determines whether has installation date. + /// + /// + /// true if has installation date; otherwise, false. + /// + private static bool HasInstallationDate() + { + return Config.GetSetting("InstallationDate") != null; + } + + /// + /// Determines whether has InstallVersion set. + /// + /// + /// true if has installation date; otherwise, false. + /// + private static bool HasInstallVersion() + { + return Config.GetSetting("InstallVersion") != null; + } + + /// + /// Check whether the modules directory is exists. + /// + /// Name of the module. + /// + /// true if the module directory exist, otherwise, false. + /// + private static bool ModuleDirectoryExists(string moduleName) + { + string dir = ApplicationMapPath + "\\desktopmodules\\" + moduleName; + return Directory.Exists(dir); + } + + /// + /// Determines whether has portal directory except default portal directory in portal path. + /// + /// + /// true if has portal directory except default portal directory in portal path; otherwise, false. + /// + private static bool HasNonDefaultPortalDirectory() + { + string dir = ApplicationMapPath + "\\portals"; + if (Directory.Exists(dir)) + { + return Directory.GetDirectories(dir).Length > 1; + } + return false; + } + + /// + /// Determines whether current request is for install. + /// + /// + /// true if current request is for install; otherwise, false. + /// + private static bool IsInstallationURL() + { + string requestURL = HttpContext.Current.Request.RawUrl.ToLowerInvariant(); + return requestURL.Contains("\\install.aspx") || requestURL.Contains("\\installwizard.aspx"); + } + + /// + /// Gets the culture code of the tab. + /// + /// The tab ID. + /// if set to true [is super tab]. + /// The settings. + /// return the tab's culture code, if ths tab doesn't exist, it will return current culture name. + internal static string GetCultureCode(int TabID, bool IsSuperTab, PortalSettings settings) + { + string cultureCode = Null.NullString; + if (settings != null) + { + TabInfo linkTab = default(TabInfo); + var controller = new TabController(); + if (IsSuperTab) + { + linkTab = controller.GetTab(TabID, Null.NullInteger, false); + } + else + { + linkTab = controller.GetTab(TabID, settings.PortalId, false); + } + if (linkTab != null) + { + cultureCode = linkTab.CultureCode; + } + if (string.IsNullOrEmpty(cultureCode)) + { + cultureCode = Thread.CurrentThread.CurrentCulture.Name; + } + } + + return cultureCode; + } + + /// + /// Builds the cross tab dataset. + /// + /// Name of the data set. + /// The result. + /// The fixed columns. + /// The variable columns. + /// The key column. + /// The field column. + /// The field type column. + /// The string value column. + /// The numeric value column. + /// the dataset instance + public static DataSet BuildCrossTabDataSet(string DataSetName, IDataReader result, string FixedColumns, string VariableColumns, string KeyColumn, string FieldColumn, string FieldTypeColumn, + string StringValueColumn, string NumericValueColumn) + { + return BuildCrossTabDataSet(DataSetName, result, FixedColumns, VariableColumns, KeyColumn, FieldColumn, FieldTypeColumn, StringValueColumn, NumericValueColumn, CultureInfo.CurrentCulture); + } + + /// ----------------------------------------------------------------------------- + /// + /// converts a data reader with serialized fields into a typed data set + /// + /// Name of the dataset to be created + /// Data reader that contains all field values serialized + /// List of fixed columns, delimited by commas. Columns must be contained in DataReader + /// List of variable columns, delimited by commas. Columns must be contained in DataReader + /// Name of the column, that contains the row ID. Column must be contained in DataReader + /// Name of the column, that contains the field name. Column must be contained in DataReader + /// Name of the column, that contains the field type name. Column must be contained in DataReader + /// Name of the column, that contains the field value, if stored as string. Column must be contained in DataReader + /// Name of the column, that contains the field value, if stored as number. Column must be contained in DataReader + /// culture of the field values in data reader's string value column + /// The generated DataSet + /// + /// [sleupold] 08/24/2006 Created temporary clone of core function and added support for culture based parsing of numeric values + /// + /// ----------------------------------------------------------------------------- + public static DataSet BuildCrossTabDataSet(string DataSetName, IDataReader result, string FixedColumns, string VariableColumns, string KeyColumn, string FieldColumn, string FieldTypeColumn, + string StringValueColumn, string NumericValueColumn, CultureInfo Culture) + { + string[] arrFixedColumns = null; + string[] arrVariableColumns = null; + string[] arrField; + string FieldType; + int intColumn; + int intKeyColumn; + // create dataset + var crosstab = new DataSet(DataSetName); + crosstab.Namespace = "NetFrameWork"; + // create table + var tab = new DataTable(DataSetName); + // split fixed columns + arrFixedColumns = FixedColumns.Split(','); + // add fixed columns to table + for (intColumn = 0; intColumn < arrFixedColumns.Length; intColumn++) + { + arrField = arrFixedColumns[intColumn].Split('|'); + var col = new DataColumn(arrField[0], Type.GetType("System." + arrField[1])); + tab.Columns.Add(col); + } + + // split variable columns + if (!String.IsNullOrEmpty(VariableColumns)) + { + arrVariableColumns = VariableColumns.Split(','); + //add varible columns to table + for (intColumn = 0; intColumn < arrVariableColumns.Length; intColumn++) + { + arrField = arrVariableColumns[intColumn].Split('|'); + var col = new DataColumn(arrField[0], Type.GetType("System." + arrField[1])); + col.AllowDBNull = true; + tab.Columns.Add(col); + } + } + // add table to dataset + crosstab.Tables.Add(tab); + // add rows to table + intKeyColumn = -1; + DataRow row = null; + while (result.Read()) + { + //loop using KeyColumn as control break + if (Convert.ToInt32(result[KeyColumn]) != intKeyColumn) + { + //add row + if (intKeyColumn != -1) + { + tab.Rows.Add(row); + } + // create new row + row = tab.NewRow(); + // assign fixed column values + for (intColumn = 0; intColumn < arrFixedColumns.Length; intColumn++) + { + arrField = arrFixedColumns[intColumn].Split('|'); + row[arrField[0]] = result[arrField[0]]; + } + //initialize variable column values + if (!String.IsNullOrEmpty(VariableColumns)) + { + for (intColumn = 0; intColumn < arrVariableColumns.Length; intColumn++) + { + arrField = arrVariableColumns[intColumn].Split('|'); + switch (arrField[1]) + { + case "Decimal": + row[arrField[0]] = 0; + break; + case "String": + row[arrField[0]] = ""; + break; + } + } + } + intKeyColumn = Convert.ToInt32(result[KeyColumn]); + } + //assign pivot column value + if (!String.IsNullOrEmpty(FieldTypeColumn)) + { + FieldType = result[FieldTypeColumn].ToString(); + } + else + { + FieldType = "String"; + } + switch (FieldType) + { + case "Decimal": + row[Convert.ToInt32(result[FieldColumn])] = result[NumericValueColumn]; + break; + case "String": + if (ReferenceEquals(Culture, CultureInfo.CurrentCulture)) + { + row[result[FieldColumn].ToString()] = result[StringValueColumn]; + } + else + { + switch (tab.Columns[result[FieldColumn].ToString()].DataType.ToString()) + { + case "System.Decimal": + case "System.Currency": + row[result[FieldColumn].ToString()] = decimal.Parse(result[StringValueColumn].ToString(), Culture); + break; + case "System.Int32": + row[result[FieldColumn].ToString()] = Int32.Parse(result[StringValueColumn].ToString(), Culture); + break; + default: + row[result[FieldColumn].ToString()] = result[StringValueColumn]; + break; + } + } + break; + } + } + result.Close(); + // add row + if (intKeyColumn != -1) + { + tab.Rows.Add(row); + } + // finalize dataset + crosstab.AcceptChanges(); + // return the dataset + return crosstab; + } + + /// + /// Converts the datareader to dataset. + /// + /// The reader. + /// the dataset instance + public static DataSet ConvertDataReaderToDataSet(IDataReader reader) + { + // add datatable to dataset + var objDataSet = new DataSet(); + + do + { + objDataSet.Tables.Add(ConvertDataReaderToDataTable(reader, false)); + } while (reader.NextResult()); + + reader.Close(); + + return objDataSet; + } + + /// + /// Converts the datareader to datatable. + /// + /// The reader. + /// the datatable instance + public static DataTable ConvertDataReaderToDataTable(IDataReader reader) + { + return ConvertDataReaderToDataTable(reader, true); + } + + /// + /// Converts the datareader to datatable. + /// + /// The reader. + /// Whether close reader. + /// the datatable instance + public static DataTable ConvertDataReaderToDataTable(IDataReader reader, bool closeReader) + { + // create datatable from datareader + var objDataTable = new DataTable(); + int intFieldCount = reader.FieldCount; + int intCounter; + for (intCounter = 0; intCounter <= intFieldCount - 1; intCounter++) + { + objDataTable.Columns.Add(reader.GetName(intCounter), reader.GetFieldType(intCounter)); + } + // populate datatable + objDataTable.BeginLoadData(); + var objValues = new object[intFieldCount]; + while (reader.Read()) + { + reader.GetValues(objValues); + objDataTable.LoadDataRow(objValues, true); + } + + if (closeReader) + { + reader.Close(); + } + objDataTable.EndLoadData(); + return objDataTable; + } + + /// + /// Gets the absolute server path. + /// + /// The request. + /// absolute server path + public static string GetAbsoluteServerPath(HttpRequest Request) + { + string strServerPath; + strServerPath = Request.MapPath(Request.ApplicationPath); + if (!strServerPath.EndsWith("\\")) + { + strServerPath += "\\"; + } + return strServerPath; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ApplicationName for the MemberRole API. + /// + /// + /// This overload is used to get the current ApplcationName. The Application + /// Name is in the form Prefix_Id, where Prefix is the object qualifier + /// for this instance of DotNetNuke, and Id is the current PortalId for normal + /// users or glbSuperUserAppName for SuperUsers. + /// + /// + /// [cnurse] 01/18/2005 documented and modifeid to handle a Prefix + /// + /// ----------------------------------------------------------------------------- + public static string GetApplicationName() + { + string appName; + if (HttpContext.Current.Items["ApplicationName"] == null || String.IsNullOrEmpty(HttpContext.Current.Items["ApplicationName"].ToString())) + { + PortalSettings _PortalSettings = PortalController.GetCurrentPortalSettings(); + if (_PortalSettings == null) + { + appName = "/"; + } + else + { + appName = GetApplicationName(_PortalSettings.PortalId); + } + } + else + { + appName = Convert.ToString(HttpContext.Current.Items["ApplicationName"]); + } + return appName; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ApplicationName for the MemberRole API. + /// + /// + /// This overload is used to build the Application Name from the Portal Id + /// + /// + /// [cnurse] 01/18/2005 documented and modifeid to handle a Prefix + /// + /// ----------------------------------------------------------------------------- + public static string GetApplicationName(int PortalID) + { + string appName; + //Get the Data Provider Configuration + ProviderConfiguration _providerConfiguration = ProviderConfiguration.GetProviderConfiguration("data"); + //Read the configuration specific information for the current Provider + var objProvider = (Provider)_providerConfiguration.Providers[_providerConfiguration.DefaultProvider]; + //Get the Object Qualifier frm the Provider Configuration + string _objectQualifier = objProvider.Attributes["objectQualifier"]; + if (!String.IsNullOrEmpty(_objectQualifier) && _objectQualifier.EndsWith("_") == false) + { + _objectQualifier += "_"; + } + appName = _objectQualifier + Convert.ToString(PortalID); + return appName; + } + + /// + /// Finds the database version. + /// + /// The major. + /// The minor. + /// The build. + /// return true if can find the specific version, otherwise will retur false. + public static bool FindDatabaseVersion(int Major, int Minor, int Build) + { + bool version = false; + IDataReader dr = null; + try + { + dr = DataProvider.Instance().FindDatabaseVersion(Major, Minor, Build); + if (dr.Read()) + { + version = true; + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return version; + } + + /// + /// Updates the database version. + /// + /// The version. + public static void UpdateDataBaseVersion(Version version) + { + //update the version + DataProvider.Instance().UpdateDatabaseVersion(version.Major, version.Minor, version.Build, DotNetNukeContext.Current.Application.Name); + _dataBaseVersion = version; + } + + /// + /// Adds the port. + /// + /// The HTTP alias. + /// The original URL. + /// url with port if the post number is not 80 + public static string AddPort(string httpAlias, string originalUrl) + { + var uri = new Uri(originalUrl); + var aliasUri = new Uri(httpAlias); + + if (!uri.IsDefaultPort) + { + httpAlias = AddHTTP(aliasUri.Host + ":" + uri.Port + aliasUri.LocalPath); + } + + return httpAlias; + } + + /// + /// Gets the name of the domain. + /// + /// The request. + /// domain name + public static string GetDomainName(HttpRequest request) + { + return GetDomainName(new HttpRequestWrapper(request), false); + } + + /// + /// Gets the name of the domain. + /// + /// The request. + /// domain name + public static string GetDomainName(HttpRequestBase request) + { + return GetDomainName(request, false); + } + + /// + /// returns the domain name of the current request ( ie. www.domain.com or 207.132.12.123 or www.domain.com/directory if subhost ) + /// + /// The request. + /// if set to true [parse port number]. + /// domain name + public static string GetDomainName(HttpRequest request, bool parsePortNumber) + { + return GetDomainName(new HttpRequestWrapper(request), parsePortNumber); + } + + /// + /// returns the domain name of the current request ( ie. www.domain.com or 207.132.12.123 or www.domain.com/directory if subhost ) + /// + /// The request. + /// if set to true [parse port number]. + /// domain name + public static string GetDomainName(HttpRequestBase request, bool parsePortNumber) + { + return TestableGlobals.Instance.GetDomainName(request.Url, parsePortNumber); + } + + /// + /// Determin whether use port number by the value in config file. + /// + /// + /// true if use port number, otherwise, return false. + /// + public static bool UsePortNumber() + { + bool usePort = true; + if ((Config.GetSetting("UsePortNumber") != null)) + { + usePort = bool.Parse(Config.GetSetting("UsePortNumber")); + } + return usePort; + } + + /// + /// Gets the file list. + /// + /// file list. + public static ArrayList GetFileList() + { + return GetFileList(-1, "", true, "", false); + } + + /// + /// Gets the file list. + /// + /// The portal id. + /// file list + public static ArrayList GetFileList(int portalId) + { + return GetFileList(portalId, "", true, "", false); + } + + /// + /// Gets the file list. + /// + /// The portal id. + /// The STR extensions. + /// file list + public static ArrayList GetFileList(int portalId, string strExtensions) + { + return GetFileList(portalId, strExtensions, true, "", false); + } + + /// + /// Gets the file list. + /// + /// The portal id. + /// The STR extensions. + /// if set to true [none specified]. + /// file list + public static ArrayList GetFileList(int portalId, string strExtensions, bool noneSpecified) + { + return GetFileList(portalId, strExtensions, noneSpecified, "", false); + } + + /// + /// Gets the file list. + /// + /// The portal id. + /// The STR extensions. + /// if set to true [none specified]. + /// The folder. + /// file list + public static ArrayList GetFileList(int PortalId, string strExtensions, bool NoneSpecified, string Folder) + { + return GetFileList(PortalId, strExtensions, NoneSpecified, Folder, false); + } + + /// + /// Gets the file list. + /// + /// The portal id. + /// The STR extensions. + /// if set to true [none specified]. + /// The folder. + /// if set to true [include hidden]. + /// file list + public static ArrayList GetFileList(int PortalId, string strExtensions, bool NoneSpecified, string Folder, bool includeHidden) + { + var arrFileList = new ArrayList(); + if (NoneSpecified) + { + arrFileList.Add(new FileItem("", "<" + Localization.GetString("None_Specified") + ">")); + } + + var objFolder = FolderManager.Instance.GetFolder(PortalId, Folder); + + if (objFolder != null) + { + try + { + var files = FolderManager.Instance.GetFiles(objFolder); + var fileManager = FileManager.Instance; + + foreach (var file in files) + { + if (FilenameMatchesExtensions(file.FileName, strExtensions)) + { + if (file.SupportsFileAttributes) + { + if (fileManager.FileExists(objFolder, file.FileName)) + { + if (includeHidden) + { + arrFileList.Add(new FileItem(file.FileId.ToString(), file.FileName)); + } + else + { + var attributes = file.FileAttributes; + + if ((attributes & FileAttributes.Hidden) != FileAttributes.Hidden) + { + arrFileList.Add(new FileItem(file.FileId.ToString(), file.FileName)); + } + } + } + } + else + { + //File is stored in DB - Just add to arraylist + arrFileList.Add(new FileItem(file.FileId.ToString(), file.FileName)); + } + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + } + return arrFileList; + } + + /// + /// Gets the host portal settings. + /// + /// Host portal settings + public static PortalSettings GetHostPortalSettings() + { + int TabId = -1; + int PortalId = -1; + PortalAliasInfo objPortalAliasInfo = null; + //if the portal alias exists + if (Host.HostPortalID > Null.NullInteger) + { + PortalId = Host.HostPortalID; + // use the host portal + objPortalAliasInfo = new PortalAliasInfo(); + objPortalAliasInfo.PortalID = PortalId; + } + // load the PortalSettings into current context + return new PortalSettings(TabId, objPortalAliasInfo); + } + + /// + /// Gets the portal domain name. + /// + /// The STR portal alias. + /// The request. + /// if set to true [BLN add HTTP]. + /// domain name + public static string GetPortalDomainName(string strPortalAlias, HttpRequest Request, bool blnAddHTTP) + { + string strDomainName = ""; + string strURL = ""; + int intAlias; + if (Request != null) + { + strURL = GetDomainName(Request); + } + string[] arrPortalAlias = strPortalAlias.Split(','); + for (intAlias = 0; intAlias <= arrPortalAlias.Length - 1; intAlias++) + { + if (arrPortalAlias[intAlias] == strURL) + { + strDomainName = arrPortalAlias[intAlias]; + } + } + if (String.IsNullOrEmpty(strDomainName)) + { + strDomainName = arrPortalAlias[0]; + } + if (blnAddHTTP) + { + strDomainName = AddHTTP(strDomainName); + } + return strDomainName; + } + + /// + /// Gets the portal settings. + /// + /// Portal settings + public static PortalSettings GetPortalSettings() + { + PortalSettings portalSettings = null; + //Try getting the settings from the Context + if (HttpContext.Current != null) + { + portalSettings = (PortalSettings)HttpContext.Current.Items["PortalSettings"]; + } + //If nothing then try getting the Host Settings + if (portalSettings == null) + { + portalSettings = GetHostPortalSettings(); + } + return portalSettings; + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns the folder path under the root for the portal + /// + /// The folder the absolute path + /// Portal Id. + /// + /// + /// + /// [cnurse] 16/9/2004 Updated for localization, Help and 508 + /// [Philip Beadle] 6 October 2004 Moved to Globals from WebUpload.ascx.vb so can be accessed by URLControl.ascx + /// + /// ----------------------------------------------------------------------------- + public static string GetSubFolderPath(string strFileNamePath, int portalId) + { + string ParentFolderName; + if (portalId == Null.NullInteger) + { + ParentFolderName = HostMapPath.Replace("/", "\\"); + } + else + { + var objPortals = new PortalController(); + PortalInfo objPortal = objPortals.GetPortal(portalId); + ParentFolderName = objPortal.HomeDirectoryMapPath.Replace("/", "\\"); + } + string strFolderpath = strFileNamePath.Substring(0, strFileNamePath.LastIndexOf("\\") + 1); + return strFolderpath.Substring(ParentFolderName.Length).Replace("\\", "/"); + } + + /// ----------------------------------------------------------------------------- + /// + /// The GetTotalRecords method gets the number of Records returned. + /// + /// An containing the Total no of records + /// An Integer + /// + /// [cnurse] 02/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static int GetTotalRecords(ref IDataReader dr) + { + int total = 0; + if (dr.Read()) + { + try + { + total = Convert.ToInt32(dr["TotalRecords"]); + } + catch (Exception exc) + { + Logger.Error(exc); + total = -1; + } + } + return total; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetStatus - determines whether an upgrade/install is required and sest the + /// Database Version and Status accordingly + /// + /// + /// + /// + /// [cnurse] 02/12/2008 created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Replaced in DotNetNuke 6.0 by Globals.Status Property")] + public static void GetStatus() + { + //There is no need to do anything here since the backing propery (Globals.Status) is now lazy loaded. + } + + /// + /// Sets the status. + /// + /// The status. + public static void SetStatus(UpgradeStatus status) + { + _status = status; + } + + /// ----------------------------------------------------------------------------- + /// + /// ImportFile - converts a file url (/Portals/0/somefile.gif) to the appropriate + /// FileID=xx identification for use in importing portals, tabs and modules + /// + /// + /// + /// An UpgradeStatus enum Upgrade/Install/None + /// + /// [cnurse] 10/11/2007 moved from PortalController so the same + /// logic can be used by Module and Tab templates + /// + /// ----------------------------------------------------------------------------- + public static string ImportFile(int PortalId, string url) + { + string strUrl = url; + if (GetURLType(url) == TabType.File) + { + var fileName = Path.GetFileName(url); + + var folderPath = url.Substring(0, url.LastIndexOf(fileName)); + var folder = FolderManager.Instance.GetFolder(PortalId, folderPath); + + if (folder != null) + { + var file = FileManager.Instance.GetFile(folder, fileName); + if (file != null) + { + strUrl = "FileID=" + file.FileId; + } + } + } + + return strUrl; + } + + /// + /// Encode the post url + /// + /// The post url. + /// encoded value + public static string HTTPPOSTEncode(string strPost) + { + strPost = strPost.Replace("\\", ""); + strPost = HttpUtility.UrlEncode(strPost); + strPost = strPost.Replace("%2f", "/"); + return strPost; + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets the ApplicationName for the MemberRole API + /// + /// + /// This overload takes a the PortalId + /// + /// The Portal Id + /// + /// [cnurse] 01/18/2005 documented + /// + /// ----------------------------------------------------------------------------- + public static void SetApplicationName(int PortalID) + { + HttpContext.Current.Items["ApplicationName"] = GetApplicationName(PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets the ApplicationName for the MemberRole API + /// + /// + /// This overload takes a the PortalId + /// + /// The Application Name to set + /// + /// [cnurse] 01/18/2005 documented + /// + /// ----------------------------------------------------------------------------- + public static void SetApplicationName(string ApplicationName) + { + HttpContext.Current.Items["ApplicationName"] = ApplicationName; + } + + /// + /// Formats the address on a single line ( ie. Unit, Street, City, Region, Country, PostalCode ) + /// + /// The unit. + /// The street. + /// The city. + /// The region. + /// The country. + /// The postal code. + /// + public static string FormatAddress(object Unit, object Street, object City, object Region, object Country, object PostalCode) + { + string strAddress = ""; + if (Unit != null) + { + if (!String.IsNullOrEmpty(Unit.ToString().Trim())) + { + strAddress += ", " + Unit; + } + } + if (Street != null) + { + if (!String.IsNullOrEmpty(Street.ToString().Trim())) + { + strAddress += ", " + Street; + } + } + if (City != null) + { + if (!String.IsNullOrEmpty(City.ToString().Trim())) + { + strAddress += ", " + City; + } + } + if (Region != null) + { + if (!String.IsNullOrEmpty(Region.ToString().Trim())) + { + strAddress += ", " + Region; + } + } + if (Country != null) + { + if (!String.IsNullOrEmpty(Country.ToString().Trim())) + { + strAddress += ", " + Country; + } + } + if (PostalCode != null) + { + if (!String.IsNullOrEmpty(PostalCode.ToString().Trim())) + { + strAddress += ", " + PostalCode; + } + } + if (!String.IsNullOrEmpty(strAddress.Trim())) + { + strAddress = strAddress.Substring(2); + } + return strAddress; + } + + /// + /// Formats the system.version into the standard format nn.nn.nn + /// + /// The version. + /// Formatted version as string + public static string FormatVersion(Version version) + { + return FormatVersion(version, false); + } + + /// + /// Formats the version. + /// + /// The version. + /// if set to true [include build]. + /// Formatted version as string + /// + /// + /// var version = new Version(6, 0, 0, 147); + /// string formattedVersion = FormatVersion(version, true); // formattedVersion's value will be: 06.00.00(147) + /// + /// + public static string FormatVersion(Version version, bool includeBuild) + { + string strVersion = version.Major.ToString("00") + "." + version.Minor.ToString("00") + "." + version.Build.ToString("00"); + if (includeBuild) + { + strVersion += " (" + version.Revision + ")"; + } + return strVersion; + } + + /// + /// Formats a version into the standard format nn.nn.nn + /// + /// The version to be formatted. + /// The field format. + /// The field count. + /// The delimiter character. + /// Formatted version as a string + public static string FormatVersion(Version version, string fieldFormat, int fieldCount, string delimiterCharacter) + { + string strVersion = ""; + int intZero = 0; + if (version != null) + { + if (fieldCount > 0) + { + if (version.Major >= 0) + { + strVersion += version.Major.ToString(fieldFormat); + } + else + { + strVersion += intZero.ToString(fieldFormat); + } + } + if (fieldCount > 1) + { + strVersion += delimiterCharacter; + if (version.Minor >= 0) + { + strVersion += version.Minor.ToString(fieldFormat); + } + else + { + strVersion += intZero.ToString(fieldFormat); + } + } + if (fieldCount > 2) + { + strVersion += delimiterCharacter; + if (version.Build >= 0) + { + strVersion += version.Build.ToString(fieldFormat); + } + else + { + strVersion += intZero.ToString(fieldFormat); + } + } + if (fieldCount > 3) + { + strVersion += delimiterCharacter; + if (version.Revision >= 0) + { + strVersion += version.Revision.ToString(fieldFormat); + } + else + { + strVersion += intZero.ToString(fieldFormat); + } + } + } + return strVersion; + } + + /// + /// Cloaks the text, obfuscate sensitive data to prevent collection by robots and spiders and crawlers + /// + /// The personal info. + /// obfuscated sensitive data by hustling ASCII characters + public static string CloakText(string PersonalInfo) + { + if (PersonalInfo == null) + { + return Null.NullString; + } + + const string Script = @" + + "; + + var characterCodes = PersonalInfo.Select(ch => ((int)ch).ToString(CultureInfo.InvariantCulture)); + return string.Format(Script, string.Join(",", characterCodes.ToArray())); + } + + /// + /// Gets the medium date by current culture. + /// + /// The date. + /// return formatted content of the date if paramter isn't empty, else return the parameter. + /// + /// + /// var mediumDate = GetMediumDate("6/1/2011"); + /// + /// + public static string GetMediumDate(string strDate) + { + if (!String.IsNullOrEmpty(strDate)) + { + DateTime datDate = Convert.ToDateTime(strDate); + string strYear = datDate.Year.ToString(); + string strMonth = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(datDate.Month); + string strDay = datDate.Day.ToString(); + strDate = strDay + "-" + strMonth + "-" + strYear; + } + return strDate; + } + + /// + /// Gets the short date. + /// + /// The date. + /// short date content of the input. + public static string GetShortDate(string strDate) + { + if (!String.IsNullOrEmpty(strDate)) + { + DateTime datDate = Convert.ToDateTime(strDate); + string strYear = datDate.Year.ToString(); + string strMonth = datDate.Month.ToString(); + string strDay = datDate.Day.ToString(); + strDate = strMonth + "/" + strDay + "/" + strYear; + } + return strDate; + } + + /// + /// Determines whether current request contains admin control information. + /// + /// + /// true if current request contains admin control information; otherwise, false. + /// + public static bool IsAdminControl() + { + // This is needed to avoid an exception if there is no Context. This will occur if code is called from the Scheduler + if (HttpContext.Current == null) + { + return false; + } + return (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["mid"])) || (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["ctl"])); + } + + /// + /// Determines whether current request use admin skin. + /// + /// + /// true if current request use admin skin; otherwise, false. + /// + public static bool IsAdminSkin() + { + bool _IsAdminSkin = Null.NullBoolean; + if (HttpContext.Current != null) + { + string AdminKeys = "tab,module,importmodule,exportmodule,help"; + string ControlKey = ""; + if (HttpContext.Current.Request.QueryString["ctl"] != null) + { + ControlKey = HttpContext.Current.Request.QueryString["ctl"].ToLower(); + } + int ModuleID = -1; + if (HttpContext.Current.Request.QueryString["mid"] != null) + { + Int32.TryParse(HttpContext.Current.Request.QueryString["mid"], out ModuleID); + } + _IsAdminSkin = (!String.IsNullOrEmpty(ControlKey) && ControlKey != "view" && ModuleID != -1) || + (!String.IsNullOrEmpty(ControlKey) && AdminKeys.IndexOf(ControlKey) != -1 && ModuleID == -1); + } + return _IsAdminSkin; + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns whether the current tab is in EditMode + /// + /// true if the tab is in Edit mode; otherwise false + /// + /// + /// + /// [cnurse] 06/04/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static bool IsEditMode() + { + return (TabPermissionController.CanAddContentToPage() && PortalController.GetCurrentPortalSettings().UserMode == PortalSettings.Mode.Edit); + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns whether the current tab is in LayoutMode + /// + /// true if the current tab is in layout mode; otherwise false + /// + /// + /// + /// [Jon Henning] 9/16/2004 Created + /// + /// ----------------------------------------------------------------------------- + public static bool IsLayoutMode() + { + return (TabPermissionController.CanAddContentToPage() && PortalController.GetCurrentPortalSettings().UserMode == PortalSettings.Mode.Layout); + } + + /// + /// Creates the RSS. + /// + /// The dr. + /// The title field. + /// The URL field. + /// The created date field. + /// The syndicate field. + /// Name of the domain. + /// Name of the file. + public static void CreateRSS(IDataReader dr, string TitleField, string URLField, string CreatedDateField, string SyndicateField, string DomainName, string FileName) + { + // Obtain PortalSettings from Current Context + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + string strRSS = ""; + string strRelativePath = DomainName + FileName.Substring(FileName.IndexOf("\\Portals")).Replace("\\", "/"); + strRelativePath = strRelativePath.Substring(0, strRelativePath.LastIndexOf("/")); + try + { + while (dr.Read()) + { + if (Convert.ToInt32(dr[SyndicateField]) > 0) + { + strRSS += " " + Environment.NewLine; + strRSS += " " + dr[TitleField] + "" + Environment.NewLine; + if (dr["URL"].ToString().IndexOf("://") == -1) + { + if (Regex.IsMatch(dr["URL"].ToString(), "^\\d+$")) + { + strRSS += " " + DomainName + "/" + glbDefaultPage + "?tabid=" + dr[URLField] + "" + Environment.NewLine; + } + else + { + strRSS += " " + strRelativePath + dr[URLField] + "" + Environment.NewLine; + } + } + else + { + strRSS += " " + dr[URLField] + "" + Environment.NewLine; + } + strRSS += " " + _portalSettings.PortalName + " " + GetMediumDate(dr[CreatedDateField].ToString()) + "" + Environment.NewLine; + strRSS += " " + Environment.NewLine; + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + if (!String.IsNullOrEmpty(strRSS)) + { + strRSS = "" + Environment.NewLine + "" + Environment.NewLine + " " + Environment.NewLine + " " + + _portalSettings.PortalName + "" + Environment.NewLine + " " + DomainName + "" + Environment.NewLine + " " + + _portalSettings.PortalName + "" + Environment.NewLine + " en-us" + Environment.NewLine + " " + + (!string.IsNullOrEmpty(_portalSettings.FooterText) ? _portalSettings.FooterText.Replace("[year]", DateTime.Now.Year.ToString()) : string.Empty) + + "" + Environment.NewLine + " " + _portalSettings.Email + "" + Environment.NewLine + strRSS + " " + Environment.NewLine + + ""; + StreamWriter objStream; + objStream = File.CreateText(FileName); + objStream.WriteLine(strRSS); + objStream.Close(); + } + else + { + if (File.Exists(FileName)) + { + File.Delete(FileName); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// injects the upload directory into raw HTML for src and background tags + /// + /// raw HTML text + /// path of portal image directory + /// HTML with paths for images and background corrected + /// + /// + /// + /// [sleupold] 8/18/2007 corrected and refactored + /// + /// ----------------------------------------------------------------------------- + public static string ManageUploadDirectory(string strHTML, string strUploadDirectory) + { + strHTML = ManageTokenUploadDirectory(strHTML, strUploadDirectory, "src"); + return ManageTokenUploadDirectory(strHTML, strUploadDirectory, "background"); + } + + /// ----------------------------------------------------------------------------- + /// + /// injects the upload directory into raw HTML for a single token + /// + /// raw HTML text + /// path of portal image directory + /// token to be replaced + /// HTML with paths for images and background corrected + /// + /// called by ManageUploadDirectory for each token. + /// + /// + /// [sleupold] 8/18/2007 created as refactoring of ManageUploadDirectory + /// added proper handling of subdirectory installations. + /// [sleupold] 11/03/2007 case insensitivity added + /// + /// ----------------------------------------------------------------------------- + public static string ManageTokenUploadDirectory(string strHTML, string strUploadDirectory, string strToken) + { + int P; + int R; + int S = 0; + int tLen; + string strURL; + var sbBuff = new StringBuilder(""); + if (!String.IsNullOrEmpty(strHTML)) + { + tLen = strToken.Length + 2; + string _UploadDirectory = strUploadDirectory.ToLower(); + //find position of first occurrance: + P = strHTML.IndexOf(strToken + "=\"", StringComparison.InvariantCultureIgnoreCase); + while (P != -1) + { + sbBuff.Append(strHTML.Substring(S, P - S + tLen)); //keep charactes left of URL + S = P + tLen; //save startpos of URL + R = strHTML.IndexOf("\"", S); //end of URL + if (R >= 0) + { + strURL = strHTML.Substring(S, R - S).ToLower(); + } + else + { + strURL = strHTML.Substring(S).ToLower(); + } + // add uploaddirectory if we are linking internally and the uploaddirectory is not already included + if (!strURL.Contains("://") && !strURL.StartsWith("/") && !strURL.StartsWith(_UploadDirectory)) + { + sbBuff.Append(strUploadDirectory); + } + //find position of next occurrance: + P = strHTML.IndexOf(strToken + "=\"", S + strURL.Length + 2, StringComparison.InvariantCultureIgnoreCase); + } + if (S > -1) + { + sbBuff.Append(strHTML.Substring(S)); + } + } + return sbBuff.ToString(); + } + + /// + /// Finds the control recursive from child to parent. + /// + /// current control. + /// the control name which want to find out. + /// control which'name is strControlName, or else return null if didn't match any control. + public static Control FindControlRecursive(Control objControl, string strControlName) + { + if (objControl.Parent == null) + { + return null; + } + else + { + if (objControl.Parent.FindControl(strControlName) != null) + { + return objControl.Parent.FindControl(strControlName); + } + else + { + return FindControlRecursive(objControl.Parent, strControlName); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Searches control hierarchy from top down to find a control matching the passed in name + /// + /// Root control to begin searching + /// Name of control to look for + /// + /// + /// This differs from FindControlRecursive in that it looks down the control hierarchy, whereas, the + /// FindControlRecursive starts at the passed in control and walks the tree up. Therefore, this function is + /// more a expensive task. + /// + /// + /// [Jon Henning] 9/17/2004 Created + /// + /// ----------------------------------------------------------------------------- + public static Control FindControlRecursiveDown(Control objParent, string strControlName) + { + Control objCtl; + objCtl = objParent.FindControl(strControlName); + if (objCtl == null) + { + foreach (Control objChild in objParent.Controls) + { + objCtl = FindControlRecursiveDown(objChild, strControlName); + if (objCtl != null) + { + break; + } + } + } + return objCtl; + } + + /// + /// Sets the form focus. + /// + /// The control. + public static void SetFormFocus(Control control) + { + if (control.Page != null && control.Visible) + { + if (control.Page.Request.Browser.EcmaScriptVersion.Major >= 1) + { + //JH dnn.js mod + if (ClientAPI.ClientAPIDisabled() == false) + { + ClientAPI.RegisterClientReference(control.Page, ClientAPI.ClientNamespaceReferences.dnn); + DNNClientAPI.SetInitialFocus(control.Page, control); + } + else + { + //Create JavaScript + var sb = new StringBuilder(); + sb.Append(""); + // Register Client Script + ClientAPI.RegisterClientScriptBlock(control.Page, "InitialFocus", sb.ToString()); + } + } + } + } + + /// + /// Gets the external request. + /// + /// The address. + /// Web request + public static HttpWebRequest GetExternalRequest(string Address) + { + //Obtain PortalSettings from Current Context + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + //Create the request object + var objRequest = (HttpWebRequest)WebRequest.Create(Address); + //Set a time out to the request ... 10 seconds + objRequest.Timeout = Host.WebRequestTimeout; + //Attach a User Agent to the request + objRequest.UserAgent = "DotNetNuke"; + //If there is Proxy info, apply it to the request + if (!string.IsNullOrEmpty(Host.ProxyServer)) + { + //Create a new Proxy + WebProxy Proxy; + //Create a new Network Credentials item + NetworkCredential ProxyCredentials; + //Fill Proxy info from host settings + Proxy = new WebProxy(Host.ProxyServer, Host.ProxyPort); + if (!string.IsNullOrEmpty(Host.ProxyUsername)) + { + //Fill the credential info from host settings + ProxyCredentials = new NetworkCredential(Host.ProxyUsername, Host.ProxyPassword); + //Apply credentials to proxy + Proxy.Credentials = ProxyCredentials; + } + //Apply Proxy to request + objRequest.Proxy = Proxy; + } + return objRequest; + } + + /// + /// Gets the external request. + /// + /// The address. + /// The credentials. + /// Web request + public static HttpWebRequest GetExternalRequest(string Address, NetworkCredential Credentials) + { + //Create the request object + var objRequest = (HttpWebRequest)WebRequest.Create(Address); + // Set a time out to the request ... 10 seconds + objRequest.Timeout = Host.WebRequestTimeout; + // Attach a User Agent to the request + objRequest.UserAgent = "DotNetNuke"; + // Attach supplied credentials + if (Credentials.UserName != null) + { + objRequest.Credentials = Credentials; + } + // If there is Proxy info, apply it to the request + if (!string.IsNullOrEmpty(Host.ProxyServer)) + { + // Create a new Proxy + WebProxy Proxy; + // Create a new Network Credentials item + NetworkCredential ProxyCredentials; + // Fill Proxy info from host settings + Proxy = new WebProxy(Host.ProxyServer, Host.ProxyPort); + if (!string.IsNullOrEmpty(Host.ProxyUsername)) + { + // Fill the credential info from host settings + ProxyCredentials = new NetworkCredential(Host.ProxyUsername, Host.ProxyPassword); + //Apply credentials to proxy + Proxy.Credentials = ProxyCredentials; + } + objRequest.Proxy = Proxy; + } + return objRequest; + } + + /// + /// Deletes the folder recursive, include the folder itself will be deleted. + /// + /// The root. + public static void DeleteFolderRecursive(string strRoot) + { + if (!String.IsNullOrEmpty(strRoot)) + { + if (Directory.Exists(strRoot)) + { + foreach (string strFolder in Directory.GetDirectories(strRoot)) + { + DeleteFolderRecursive(strFolder); + } + foreach (string strFile in Directory.GetFiles(strRoot)) + { + try + { + FileSystemUtils.DeleteFile(strFile); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + try + { + Directory.Delete(strRoot); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + } + } + + /// + /// Deletes the files recursive which match the filter, will not delete folders and will ignore folder which is hidden or system. + /// + /// The root. + /// The filter. + public static void DeleteFilesRecursive(string strRoot, string filter) + { + if (!String.IsNullOrEmpty(strRoot)) + { + if (Directory.Exists(strRoot)) + { + foreach (string strFolder in Directory.GetDirectories(strRoot)) + { + var directory = new DirectoryInfo(strFolder); + if ((directory.Attributes & FileAttributes.Hidden) == 0 && (directory.Attributes & FileAttributes.System) == 0) + { + DeleteFilesRecursive(strFolder, filter); + } + } + foreach (string strFile in Directory.GetFiles(strRoot, "*" + filter)) + { + try + { + FileSystemUtils.DeleteFile(strFile); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + } + } + } + + /// + /// Cleans the name of the file. + /// + /// Name of the file. + /// clean name + public static string CleanFileName(string FileName) + { + return CleanFileName(FileName, "", ""); + } + + /// + /// Cleans the name of the file. + /// + /// Name of the file. + /// The bad chars. + /// clean name + public static string CleanFileName(string FileName, string BadChars) + { + return CleanFileName(FileName, BadChars, ""); + } + + /// + /// Cleans the name of the file. + /// + /// Name of the file. + /// The bad chars. + /// The replace char. + /// clean name + public static string CleanFileName(string FileName, string BadChars, string ReplaceChar) + { + string strFileName = FileName; + if (String.IsNullOrEmpty(BadChars)) + { + BadChars = ":/\\?*|" + ((char)34) + ((char)39) + ((char)9); + } + if (String.IsNullOrEmpty(ReplaceChar)) + { + ReplaceChar = "_"; + } + int intCounter; + for (intCounter = 0; intCounter <= BadChars.Length - 1; intCounter++) + { + strFileName = strFileName.Replace(BadChars.Substring(intCounter, 1), ReplaceChar); + } + return strFileName; + } + + /// ----------------------------------------------------------------------------- + /// + /// CleanName - removes characters from Module/Tab names that are being used for file names + /// in Module/Tab Import/Export. + /// + /// + /// + /// A cleaned string + /// + /// [cnurse] 10/11/2007 moved from Import/Export Module user controls to avoid + /// duplication and for use in new Import and Export Tab + /// user controls + /// + /// ----------------------------------------------------------------------------- + public static string CleanName(string Name) + { + string strName = Name; + string strBadChars = ". ~`!@#$%^&*()-_+={[}]|\\:;<,>?/" + ((char)34) + ((char)39); + int intCounter; + for (intCounter = 0; intCounter <= strBadChars.Length - 1; intCounter++) + { + strName = strName.Replace(strBadChars.Substring(intCounter, 1), ""); + } + return strName; + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateValidClass - removes characters from Module/Tab names which are invalid + /// for use as an XHTML class attribute / CSS class selector value and optionally + /// prepends the letter 'A' if the first character is not alphabetic. This differs + /// from CreateValidID which replaces invalid characters with an underscore + /// and replaces the first letter with an 'A' if it is not alphabetic + /// + /// String to use to create the class value + /// If set true, validate whether the first character + /// is alphabetic and, if not, prepend the letter 'A' to the returned value + /// + /// + /// A string suitable for use as a class value + /// + /// [jenni] 27/10/2010 Created + /// + /// ----------------------------------------------------------------------------- + public static string CreateValidClass(string inputValue, bool validateFirstChar) + { + string returnValue = Null.NullString; + + //Regex is expensive so we will cache the results in a lookup table + var validClassLookupDictionary = CBO.GetCachedObject>(new CacheItemArgs("ValidClassLookup", 200, CacheItemPriority.NotRemovable), + (CacheItemArgs cacheItemArgs) => new SharedDictionary()); + + bool idFound = Null.NullBoolean; + using (ISharedCollectionLock readLock = validClassLookupDictionary.GetReadLock()) + { + if (validClassLookupDictionary.ContainsKey(inputValue)) + { + //Return value + returnValue = validClassLookupDictionary[inputValue]; + idFound = true; + } + } + + if (!idFound) + { + using (ISharedCollectionLock writeLock = validClassLookupDictionary.GetWriteLock()) + { + if (!validClassLookupDictionary.ContainsKey(inputValue)) + { + //Create Valid Class + // letters ([a-zA-Z]), digits ([0-9]), hyphens ("-") and underscores ("_") are valid in class values + // Remove all characters that aren't in the list + var invalidCharacters = new Regex("[^A-Z0-9_-]", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + returnValue = invalidCharacters.Replace(inputValue, string.Empty); + + // If we're asked to validate the first character... + if ((validateFirstChar)) + { + // classes should begin with a letter ([A-Za-z])' + // prepend a starting non-letter character with an A + var invalidInitialCharacters = new Regex("^[^A-Z]", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + if ((invalidCharacters.IsMatch(returnValue))) + { + returnValue = "A" + returnValue; + } + } + + //put in Dictionary + validClassLookupDictionary[inputValue] = returnValue; + } + } + } + + //Return Value + return returnValue; + } + + /// + /// Creates the valid ID. + /// + /// The input value. + /// String with a valid ID + public static string CreateValidID(string inputValue) + { + string returnValue = Null.NullString; + + //Regex is expensive so we will cache the results in a lookup table + var validIDLookupDictionary = CBO.GetCachedObject>(new CacheItemArgs("ValidIDLookup", 200, CacheItemPriority.NotRemovable), + (CacheItemArgs cacheItemArgs) => new SharedDictionary()); + + bool idFound = Null.NullBoolean; + using (ISharedCollectionLock readLock = validIDLookupDictionary.GetReadLock()) + { + if (validIDLookupDictionary.ContainsKey(inputValue)) + { + //Return value + returnValue = validIDLookupDictionary[inputValue]; + idFound = true; + } + } + + if (!idFound) + { + using (ISharedCollectionLock writeLock = validIDLookupDictionary.GetWriteLock()) + { + if (!validIDLookupDictionary.ContainsKey(inputValue)) + { + //Create Valid ID + // '... letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".")' are valid identifiers + // We aren't allowing hyphens or periods, even though they're valid, since the previous version of this function didn't + // Replace all characters that aren't in the list with an underscore + var invalidCharacters = new Regex("[^A-Z0-9_:]", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + returnValue = invalidCharacters.Replace(inputValue, "_"); + + // identifiers '... must begin with a letter ([A-Za-z])' + // replace a starting non-letter character with an A + var invalidInitialCharacters = new Regex("^[^A-Z]", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); + returnValue = invalidInitialCharacters.Replace(returnValue, "A"); + + //put in Dictionary + validIDLookupDictionary[inputValue] = returnValue; + } + } + } + return returnValue; + } + + + /// + /// Get the path of page to show access denied message. + /// + /// url of access denied + public static string AccessDeniedURL() + { + return AccessDeniedURL(""); + } + + /// + /// Get the path of page to show access denied message. + /// + /// The message. + /// url of access denied + public static string AccessDeniedURL(string Message) + { + string strURL = ""; + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + if (HttpContext.Current.Request.IsAuthenticated) + { + if (String.IsNullOrEmpty(Message)) + { + //redirect to access denied page + strURL = NavigateURL(_portalSettings.ActiveTab.TabID, "Access Denied"); + } + else + { + //redirect to access denied page with custom message + strURL = NavigateURL(_portalSettings.ActiveTab.TabID, "Access Denied", "message=" + HttpUtility.UrlEncode(Message)); + } + } + else + { + strURL = LoginURL(HttpUtility.UrlEncode(HttpContext.Current.Request.RawUrl), false); + } + return strURL; + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds HTTP to URL if no other protocol specified + /// + /// + /// + /// The url + /// The formatted url + /// + /// [cnurse] 12/16/2004 documented + /// [cnurse] 05/06/2005 added chack for mailto: protocol + /// + /// ----------------------------------------------------------------------------- + public static string AddHTTP(string strURL) + { + if (!String.IsNullOrEmpty(strURL)) + { + if (strURL.IndexOf("mailto:") == -1 && strURL.IndexOf("://") == -1 && strURL.IndexOf("~") == -1 && strURL.IndexOf("\\\\") == -1) + { + if (HttpContext.Current != null && HttpContext.Current.Request.IsSecureConnection) + { + strURL = "https://" + strURL; + } + else + { + strURL = "http://" + strURL; + } + } + } + return strURL; + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the Application root url (including the tab/page) + /// + /// + /// This overload assumes the current page + /// + /// The formatted root url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string ApplicationURL() + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + if (_portalSettings != null) + { + return (ApplicationURL(_portalSettings.ActiveTab.TabID)); + } + else + { + return (ApplicationURL(-1)); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the Application root url (including the tab/page) + /// + /// + /// This overload takes the tabid (page id) as a parameter + /// + /// The id of the tab/page + /// The formatted root url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string ApplicationURL(int TabID) + { + string strURL = "~/" + glbDefaultPage; + if (TabID != -1) + { + strURL += "?tabid=" + TabID; + } + return strURL; + } + + /// + /// Formats the help URL. + /// + /// The help URL. + /// The portal settings. + /// The name. + /// Formatted url. + public static string FormatHelpUrl(string HelpUrl, PortalSettings objPortalSettings, string Name) + { + return FormatHelpUrl(HelpUrl, objPortalSettings, Name, ""); + } + + /// + /// Formats the help URL. + /// + /// The help URL. + /// The portal settings. + /// The name. + /// The version. + /// Formatted url. + public static string FormatHelpUrl(string HelpUrl, PortalSettings objPortalSettings, string Name, string Version) + { + string strURL = HelpUrl; + if (strURL.IndexOf("?") != -1) + { + strURL += "&helpculture="; + } + else + { + strURL += "?helpculture="; + } + if (!String.IsNullOrEmpty(Thread.CurrentThread.CurrentUICulture.ToString().ToLower())) + { + strURL += Thread.CurrentThread.CurrentUICulture.ToString().ToLower(); + } + else + { + strURL += objPortalSettings.DefaultLanguage.ToLower(); + } + if (!String.IsNullOrEmpty(Name)) + { + strURL += "&helpmodule=" + HttpUtility.UrlEncode(Name); + } + if (!String.IsNullOrEmpty(Version)) + { + strURL += "&helpversion=" + HttpUtility.UrlEncode(Version); + } + return AddHTTP(strURL); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted friendly url. + /// + /// + /// Assumes Default.aspx, and that portalsettings are saved to Context + /// + /// The current tab + /// The path to format. + /// The formatted (friendly) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string FriendlyUrl(TabInfo tab, string path) + { + return FriendlyUrl(tab, path, glbDefaultPage); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted friendly url + /// + /// + /// This overload includes an optional page to include in the url. + /// + /// The current tab + /// The path to format. + /// The page to include in the url. + /// The formatted (friendly) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string FriendlyUrl(TabInfo tab, string path, string pageName) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return FriendlyUrl(tab, path, pageName, _portalSettings); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted friendly url + /// + /// + /// This overload includes the portal settings for the site + /// + /// The current tab + /// The path to format. + /// The portal Settings + /// The formatted (friendly) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string FriendlyUrl(TabInfo tab, string path, PortalSettings settings) + { + return FriendlyUrl(tab, path, glbDefaultPage, settings); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted friendly url + /// + /// + /// This overload includes an optional page to include in the url, and the portal + /// settings for the site + /// + /// The current tab + /// The path to format. + /// The page to include in the url. + /// The portal Settings + /// The formatted (friendly) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings settings) + { + return FriendlyUrlProvider.Instance().FriendlyUrl(tab, path, pageName, settings); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted friendly url + /// + /// + /// This overload includes an optional page to include in the url, and the portal + /// settings for the site + /// + /// The current tab + /// The path to format. + /// The page to include in the url. + /// The portal Alias for the site + /// The formatted (friendly) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias) + { + return FriendlyUrlProvider.Instance().FriendlyUrl(tab, path, pageName, portalAlias); + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns the type of URl (T=other tab, F=file, U=URL, N=normal) + /// + /// + /// + /// The url + /// The url type + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static TabType GetURLType(string URL) + { + if (String.IsNullOrEmpty(URL)) + { + return TabType.Normal; + } + else + { + if (URL.ToLower().StartsWith("mailto:") == false && URL.IndexOf("://") == -1 && URL.StartsWith("~") == false && URL.StartsWith("\\\\") == false && URL.StartsWith("/") == false) + { + if (Regex.IsMatch(URL, @"^\d+$")) + { + return TabType.Tab; + } + else + { + if (URL.ToLower().StartsWith("userid=")) + { + return TabType.Member; + } + else + { + return TabType.File; + } + } + } + else + { + return TabType.Url; + } + } + } + + /// + /// Url's as internal links to Files, Tabs and Users should only be imported if + /// those files, tabs and users exist. This function parses the url, and checks + /// whether the internal links exist. + /// If the link does not exist, the function will return an empty string + /// + /// Integer + /// String + /// If an internal link does not exist, an empty string is returned, otherwise the passed in url is returned as is + /// + /// [erikvb] 06/11/2008 corrected file check and added tab and member check + /// + public static string ImportUrl(int ModuleId, string url) + { + string strUrl = url; + TabType urlType = GetURLType(url); + int intId = -1; + PortalSettings portalSettings = GetPortalSettings(); + switch (urlType) + { + case TabType.File: + if (Int32.TryParse(url.Replace("FileID=", ""), out intId)) + { + var objFile = FileManager.Instance.GetFile(intId); + if (objFile == null) + { + //fileId does not exist in the portal + strUrl = ""; + } + } + else + { + //failed to get fileId + strUrl = ""; + } + break; + case TabType.Member: + if (Int32.TryParse(url.Replace("UserID=", ""), out intId)) + { + if (UserController.GetUserById(portalSettings.PortalId, intId) == null) + { + //UserId does not exist for this portal + strUrl = ""; + } + } + else + { + //failed to get UserId + strUrl = ""; + } + break; + case TabType.Tab: + if (Int32.TryParse(url, out intId)) + { + var objTabController = new TabController(); + if (objTabController.GetTab(intId, portalSettings.PortalId, false) == null) + { + //the tab does not exist + strUrl = ""; + } + } + else + { + //failed to get TabId + strUrl = ""; + } + break; + } + return strUrl; + } + + /// + /// Gets Login URL. + /// + /// The return URL. + /// if set to true [@override]. + /// Formatted url. + public static string LoginURL(string returnURL, bool @override) + { + string strURL = ""; + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (!string.IsNullOrEmpty(returnURL)) + { + returnURL = String.Format("returnurl={0}", returnURL); + } + if (portalSettings.LoginTabId != -1 && !@override) + { + if (ValidateLoginTabID(portalSettings.LoginTabId)) + { + strURL = string.IsNullOrEmpty(returnURL) + ? NavigateURL(portalSettings.LoginTabId, "") + : NavigateURL(portalSettings.LoginTabId, "", returnURL); + } + else + { + string strMessage = String.Format("error={0}", Localization.GetString("NoLoginControl", Localization.GlobalResourceFile)); + //No account module so use portal tab + strURL = string.IsNullOrEmpty(returnURL) + ? NavigateURL(portalSettings.ActiveTab.TabID, "Login", strMessage) + : NavigateURL(portalSettings.ActiveTab.TabID, "Login", returnURL, strMessage); + } + } + else + { + //portal tab + strURL = string.IsNullOrEmpty(returnURL) + ? NavigateURL(portalSettings.ActiveTab.TabID, "Login") + : NavigateURL(portalSettings.ActiveTab.TabID, "Login", returnURL); + } + return strURL; + } + + /// + /// Gets User profile URL. + /// + /// The user id. + /// Formatted url. + public static string UserProfileURL(int userId) + { + string strURL = ""; + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + + strURL = NavigateURL(portalSettings.UserTabId, "", string.Format("userId={0}", userId)); + + return strURL; + } + + /// + /// Gets the navigates URL. + /// + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL() + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + return NavigateURL(portalSettings.ActiveTab.TabID, Null.NullString); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID) + { + return NavigateURL(tabID, Null.NullString); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// if set to true [is super tab]. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID, bool isSuperTab) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + string cultureCode = GetCultureCode(tabID, isSuperTab, _portalSettings); + return NavigateURL(tabID, isSuperTab, _portalSettings, Null.NullString, cultureCode); + } + + /// + /// Gets the navigates URL. + /// + /// The control key. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(string controlKey) + { + if (controlKey == "Access Denied") + { + return AccessDeniedURL(); + } + else + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return NavigateURL(_portalSettings.ActiveTab.TabID, controlKey); + } + } + + /// + /// Gets the navigates URL. + /// + /// The control key. + /// The additional parameters. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(string controlKey, params string[] additionalParameters) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return NavigateURL(_portalSettings.ActiveTab.TabID, controlKey, additionalParameters); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// The control key. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID, string controlKey) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return NavigateURL(tabID, _portalSettings, controlKey, null); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// The control key. + /// The additional parameters. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID, string controlKey, params string[] additionalParameters) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return NavigateURL(tabID, _portalSettings, controlKey, additionalParameters); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// The settings. + /// The control key. + /// The additional parameters. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID, PortalSettings settings, string controlKey, params string[] additionalParameters) + { + bool isSuperTab = IsHostTab(tabID); + + return NavigateURL(tabID, isSuperTab, settings, controlKey, additionalParameters); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// if set to true [is super tab]. + /// The settings. + /// The control key. + /// The additional parameters. + /// Formatted url. + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public static string NavigateURL(int tabID, bool isSuperTab, PortalSettings settings, string controlKey, params string[] additionalParameters) + { + string cultureCode = GetCultureCode(tabID, isSuperTab, settings); + return NavigateURL(tabID, isSuperTab, settings, controlKey, cultureCode, additionalParameters); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// if set to true [is super tab]. + /// The settings. + /// The control key. + /// The language. + /// The additional parameters. + /// Formatted url. + public static string NavigateURL(int tabID, bool isSuperTab, PortalSettings settings, string controlKey, string language, params string[] additionalParameters) + { + return NavigateURL(tabID, isSuperTab, settings, controlKey, language, glbDefaultPage, additionalParameters); + } + + /// + /// Gets the navigates URL. + /// + /// The tab ID. + /// if set to true [is super tab]. + /// The settings. + /// The control key. + /// The language. + /// The additional parameters. + /// Formatted url. + public static string NavigateURL(int tabID, bool isSuperTab, PortalSettings settings, string controlKey, string language, string pageName, params string[] additionalParameters) + { + string url = tabID == Null.NullInteger ? ApplicationURL() : ApplicationURL(tabID); + if (!String.IsNullOrEmpty(controlKey)) + { + url += "&ctl=" + controlKey; + } + if (additionalParameters != null) + { + url = additionalParameters.Where(parameter => !string.IsNullOrEmpty(parameter)).Aggregate(url, (current, parameter) => current + ("&" + parameter)); + } + if (isSuperTab) + { + url += "&portalid=" + settings.PortalId; + } + + var controller = new TabController(); + + TabInfo tab = null; + + if (settings != null) + { + tab = controller.GetTab(tabID, isSuperTab ? Null.NullInteger : settings.PortalId, false); + } + + //only add language to url if more than one locale is enabled + if (settings != null && language != null && LocaleController.Instance.GetLocales(settings.PortalId).Count > 1) + { + if (settings.ContentLocalizationEnabled) + { + if (language == "") + { + if (tab != null && !string.IsNullOrEmpty(tab.CultureCode)) + { + url += "&language=" + tab.CultureCode; + } + } + else + { + url += "&language=" + language; + } + } + else if (settings.EnableUrlLanguage) + { + //legacy pre 5.5 behavior + if (language == "") + { + url += "&language=" + Thread.CurrentThread.CurrentCulture.Name; + } + else + { + url += "&language=" + language; + } + } + } + + if (Host.UseFriendlyUrls || Config.GetFriendlyUrlProvider() == "advanced") + { + if (String.IsNullOrEmpty(pageName)) + { + pageName = glbDefaultPage; + } + + url = (settings == null) ? FriendlyUrl(tab, url, pageName) : FriendlyUrl(tab, url, pageName, settings); + } + else + { + url = ResolveUrl(url); + } + + return url; + } + + /// + /// UrlEncode query string + /// + /// The query string. + /// Encoded content + public static string QueryStringEncode(string QueryString) + { + QueryString = HttpUtility.UrlEncode(QueryString); + return QueryString; + } + + /// + /// UrlDecode query string + /// + /// The query string. + /// Decoded content + public static string QueryStringDecode(string QueryString) + { + QueryString = HttpUtility.UrlDecode(QueryString); + string fullPath; + try + { + fullPath = HttpContext.Current.Request.MapPath(QueryString, HttpContext.Current.Request.ApplicationPath, false); + } + catch (HttpException exc) + { + Exceptions.ProcessHttpException(exc); + } + string strDoubleDecodeURL = HttpContext.Current.Server.UrlDecode(HttpContext.Current.Server.UrlDecode(QueryString)); + if (QueryString.IndexOf("..") != -1 || strDoubleDecodeURL.IndexOf("..") != -1) + { + Exceptions.ProcessHttpException(); + } + return QueryString; + } + + /// + /// Gets Register URL. + /// + /// The return URL. + /// The original URL. + /// Formatted url. + public static string RegisterURL(string returnURL, string originalURL) + { + string strURL; + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + string extraParams = String.Empty; + if (!string.IsNullOrEmpty(returnURL)) + { + extraParams = string.Concat("returnurl=", returnURL); + } + if (!string.IsNullOrEmpty(originalURL)) + { + extraParams += string.Concat("&orignalurl=", originalURL); + } + if (_portalSettings.RegisterTabId != -1) + { + //user defined tab + strURL = NavigateURL(_portalSettings.RegisterTabId, "", extraParams); + } + else + { + strURL = NavigateURL(_portalSettings.ActiveTab.TabID, "Register", extraParams); + } + return strURL; + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates the correctly formatted url + /// + /// + /// + /// The url to format. + /// The formatted (resolved) url + /// + /// [cnurse] 12/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string ResolveUrl(string url) + { + // String is Empty, just return Url + if (String.IsNullOrEmpty(url)) + { + return url; + } + // String does not contain a ~, so just return Url + if ((url.StartsWith("~") == false)) + { + return url; + } + // There is just the ~ in the Url, return the appPath + if ((url.Length == 1)) + { + return ApplicationPath; + } + if ((url.ToCharArray()[1] == '/' || url.ToCharArray()[1] == '\\')) + { + // Url looks like ~/ or ~\ + if (!string.IsNullOrEmpty(ApplicationPath) && ApplicationPath.Length > 1) + { + return ApplicationPath + "/" + url.Substring(2); + } + else + { + return "/" + url.Substring(2); + } + } + else + { + // Url look like ~something + if (!string.IsNullOrEmpty(ApplicationPath) && ApplicationPath.Length > 1) + { + return ApplicationPath + "/" + url.Substring(1); + } + else + { + return ApplicationPath + url.Substring(1); + } + } + } + + /// + /// Encodes the reserved characters. + /// + /// The query string. + /// Encoded content + public static string EncodeReservedCharacters(string QueryString) + { + QueryString = QueryString.Replace("$", "%24"); + QueryString = QueryString.Replace("&", "%26"); + QueryString = QueryString.Replace("+", "%2B"); + QueryString = QueryString.Replace(",", "%2C"); + QueryString = QueryString.Replace("/", "%2F"); + QueryString = QueryString.Replace(":", "%3A"); + QueryString = QueryString.Replace(";", "%3B"); + QueryString = QueryString.Replace("=", "%3D"); + QueryString = QueryString.Replace("?", "%3F"); + QueryString = QueryString.Replace("@", "%40"); + return QueryString; + } + + /// + /// Dates to string. + /// + /// The date value. + /// return value of input with SortableDateTimePattern. + public static string DateToString(DateTime DateValue) + { + try + { + if (!Null.IsNull(DateValue)) + { + return DateValue.ToString("s"); + } + else + { + return Null.NullString; + } + } + catch (Exception exc) + { + Logger.Error(exc); + + return Null.NullString; + } + } + + /// + /// Gets the hash value. + /// + /// The hash object. + /// The default value. + /// HashOject's value or DefaultValue if HashObject is null. + public static string GetHashValue(object HashObject, string DefaultValue) + { + if (HashObject != null) + { + if (!String.IsNullOrEmpty(HashObject.ToString())) + { + return Convert.ToString(HashObject); + } + else + { + return DefaultValue; + } + } + else + { + return DefaultValue; + } + } + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// Formatted url. + public static string LinkClick(string Link, int TabID, int ModuleID) + { + return LinkClick(Link, TabID, ModuleID, true, ""); + } + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// if set to true [track clicks]. + /// Formatted url. + public static string LinkClick(string Link, int TabID, int ModuleID, bool TrackClicks) + { + return LinkClick(Link, TabID, ModuleID, TrackClicks, ""); + } + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// if set to true [track clicks]. + /// Type of the content. + /// Formatted url. + public static string LinkClick(string Link, int TabID, int ModuleID, bool TrackClicks, string ContentType) + { + return LinkClick(Link, TabID, ModuleID, TrackClicks, !String.IsNullOrEmpty(ContentType)); + } + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// if set to true [track clicks]. + /// if set to true [force download]. + /// Formatted url. + public static string LinkClick(string Link, int TabID, int ModuleID, bool TrackClicks, bool ForceDownload) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return LinkClick(Link, TabID, ModuleID, TrackClicks, ForceDownload, _portalSettings.PortalId, _portalSettings.EnableUrlLanguage, _portalSettings.GUID.ToString()); + } + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// if set to true [track clicks]. + /// if set to true [force download]. + /// The portal id. + /// if set to true [enable URL language]. + /// The portal GUID. + /// Formatted url. + public static string LinkClick(string Link, int TabID, int ModuleID, bool TrackClicks, bool ForceDownload, int PortalId, bool EnableUrlLanguage, string portalGuid) + { + string strLink = ""; + TabType UrlType = GetURLType(Link); + if (UrlType == TabType.Member) + { + strLink = UserProfileURL(Convert.ToInt32(UrlUtils.GetParameterValue(Link))); + } + else if (TrackClicks || ForceDownload || UrlType == TabType.File) + { + //format LinkClick wrapper + if (Link.ToLowerInvariant().StartsWith("fileid=")) + { + strLink = ApplicationPath + "/LinkClick.aspx?fileticket=" + UrlUtils.EncryptParameter(UrlUtils.GetParameterValue(Link)); + } + if (String.IsNullOrEmpty(strLink)) + { + strLink = ApplicationPath + "/LinkClick.aspx?link=" + HttpUtility.UrlEncode(Link); + } + // tabid is required to identify the portal where the click originated + if (TabID != Null.NullInteger) + { + strLink += "&tabid=" + TabID; + } + //append portal id to query string to identity portal the click originated. + if(PortalId != Null.NullInteger) + { + strLink += "&portalid=" + PortalId; + } + // moduleid is used to identify the module where the url is stored + if (ModuleID != -1) + { + strLink += "&mid=" + ModuleID; + } + //only add language to url if more than one locale is enabled, and if admin did not turn it off + if (LocaleController.Instance.GetLocales(PortalId).Count > 1 && EnableUrlLanguage) + { + strLink += "&language=" + Thread.CurrentThread.CurrentCulture.Name; + } + //force a download dialog + if (ForceDownload) + { + strLink += "&forcedownload=true"; + } + } + else + { + switch (UrlType) + { + case TabType.Tab: + strLink = NavigateURL(int.Parse(Link)); + break; + default: + strLink = Link; + break; + } + } + return strLink; + } + + /// + /// Gets the name of the role. + /// + /// The role ID. + /// Role Name + public static string GetRoleName(int RoleID) + { + switch (Convert.ToString(RoleID)) + { + case glbRoleAllUsers: + return "All Users"; + case glbRoleUnauthUser: + return "Unauthenticated Users"; + } + Hashtable htRoles = null; + if (Host.PerformanceSetting != PerformanceSettings.NoCaching) + { + htRoles = (Hashtable)DataCache.GetCache("GetRoles"); + } + if (htRoles == null) + { + var roles = TestableRoleController.Instance.GetRoles(Null.NullInteger, r => r.SecurityMode != SecurityMode.SocialGroup); + htRoles = new Hashtable(); + int i; + for (i = 0; i <= roles.Count - 1; i++) + { + RoleInfo role = roles[i]; + htRoles.Add(role.RoleID, role.RoleName); + } + if (Host.PerformanceSetting != PerformanceSettings.NoCaching) + { + DataCache.SetCache("GetRoles", htRoles); + } + } + return Convert.ToString(htRoles[RoleID]); + } + + /// + /// Gets the content. + /// + /// The content. + /// Type of the content. + /// specific node by content type of the whole document. + public static XmlNode GetContent(string Content, string ContentType) + { + var xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(Content); + if (String.IsNullOrEmpty(ContentType)) + { + return xmlDoc.DocumentElement; + } + else + { + return xmlDoc.SelectSingleNode(ContentType); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// GenerateTabPath generates the TabPath used in Friendly URLS + /// + /// + /// + /// The Id of the Parent Tab + /// The Name of the current Tab + /// The TabPath + /// + /// [cnurse] 1/28/2005 documented + /// modified to remove characters not allowed in urls + /// + /// ----------------------------------------------------------------------------- + public static string GenerateTabPath(int ParentId, string TabName) + { + string strTabPath = ""; + var objTabs = new TabController(); + + if (!Null.IsNull(ParentId)) + { + string strTabName; + var objTab = objTabs.GetTab(ParentId, Null.NullInteger, false); + while (objTab != null) + { + strTabName = HtmlUtils.StripNonWord(objTab.TabName, false); + strTabPath = "//" + strTabName + strTabPath; + if (Null.IsNull(objTab.ParentId)) + { + objTab = null; + } + else + { + objTab = objTabs.GetTab(objTab.ParentId, objTab.PortalID, false); + } + } + } + + strTabPath = strTabPath + "//" + HtmlUtils.StripNonWord(TabName, false); + return strTabPath; + } + + /// + /// Gets the help text. + /// + /// The module control id. + /// help text. + public static string GetHelpText(int moduleControlId) + { + string helpText = Null.NullString; + ModuleControlInfo objModuleControl = ModuleControlController.GetModuleControl(moduleControlId); + if (objModuleControl != null) + { + string FileName = Path.GetFileName(objModuleControl.ControlSrc); + string LocalResourceFile = objModuleControl.ControlSrc.Replace(FileName, Localization.LocalResourceDirectory + "/" + FileName); + if (!String.IsNullOrEmpty(Localization.GetString(ModuleActionType.HelpText, LocalResourceFile))) + { + helpText = Localization.GetString(ModuleActionType.HelpText, LocalResourceFile); + } + } + return helpText; + } + + /// + /// Gets the online help url. + /// + /// The help URL. + /// The module config. + /// url. + public static string GetOnLineHelp(string HelpUrl, ModuleInfo moduleConfig) + { + if (string.IsNullOrEmpty(HelpUrl)) + { + //bool isAdminModule = moduleConfig.DesktopModule.IsAdmin; + //string ctlString = Convert.ToString(HttpContext.Current.Request.QueryString["ctl"]); + //if (((Host.EnableModuleOnLineHelp && !isAdminModule) || (isAdminModule))) + //{ + // if ((isAdminModule) || (IsAdminControl() && ctlString == "Module") || (IsAdminControl() && ctlString == "Tab")) + // { + // HelpUrl = Host.HelpURL; + // } + //} + //else + //{ + HelpUrl = Host.HelpURL; + //} + } + return HelpUrl; + } + + /// + /// Check whether the tab contains "Account Login" module. + /// + /// The tab id. + /// true if the tab contains "Account Login" module, otherwise, false. + public static bool ValidateLoginTabID(int tabId) + { + return ValidateModuleInTab(tabId, "Account Login"); + } + + /// + /// Check whether the tab contains specific module. + /// + /// The tab id. + /// The module need to check. + /// true if the tab contains the module, otherwise, false. + public static bool ValidateModuleInTab(int tabId, string moduleName) + { + bool hasModule = Null.NullBoolean; + foreach (ModuleInfo objModule in new ModuleController().GetTabModules(tabId).Values) + { + if (objModule.ModuleDefinition.FriendlyName == moduleName) + { + //We need to ensure that Anonymous Users or All Users have View permissions to the login page + TabInfo tab = new TabController().GetTab(tabId, objModule.PortalID, false); + if (TabPermissionController.CanViewPage(tab)) + { + hasModule = true; + break; + } + } + } + return hasModule; + } + + /// + /// Check whether the Filename matches extensions. + /// + /// The filename. + /// The valid extensions. + /// true if the Filename matches extensions, otherwise, false. + private static bool FilenameMatchesExtensions(string filename, string strExtensions) + { + bool result = string.IsNullOrEmpty(strExtensions); + if (!result) + { + filename = filename.ToUpper(); + strExtensions = strExtensions.ToUpper(); + foreach (string extension in strExtensions.Split(',')) + { + string ext = extension.Trim(); + if (!ext.StartsWith(".")) + { + ext = "." + extension; + } + result = filename.EndsWith(extension); + if (result) + { + break; + } + } + } + return result; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeserializeHashTableBase64 deserializes a Hashtable using Binary Formatting + /// + /// + /// While this method of serializing is no longer supported (due to Medium Trust + /// issue, it is still required for upgrade purposes. + /// + /// The String Source to deserialize + /// The deserialized Hashtable + /// + /// [cnurse] 2/16/2005 moved to Globals + /// + /// ----------------------------------------------------------------------------- + public static Hashtable DeserializeHashTableBase64(string Source) + { + Hashtable objHashTable; + if (!String.IsNullOrEmpty(Source)) + { + byte[] bits = Convert.FromBase64String(Source); + var mem = new MemoryStream(bits); + var bin = new BinaryFormatter(); + try + { + objHashTable = (Hashtable)bin.Deserialize(mem); + } + catch (Exception exc) + { + Logger.Error(exc); + + objHashTable = new Hashtable(); + } + mem.Close(); + } + else + { + objHashTable = new Hashtable(); + } + return objHashTable; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeserializeHashTableXml deserializes a Hashtable using Xml Serialization + /// + /// + /// This is the preferred method of serialization under Medium Trust + /// + /// The String Source to deserialize + /// The deserialized Hashtable + /// + /// [cnurse] 2/16/2005 created + /// + /// ----------------------------------------------------------------------------- + public static Hashtable DeserializeHashTableXml(string Source) + { + return XmlUtils.DeSerializeHashtable(Source, "profile"); + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeHashTableBase64 serializes a Hashtable using Binary Formatting + /// + /// + /// While this method of serializing is no longer supported (due to Medium Trust + /// issue, it is still required for upgrade purposes. + /// + /// The Hashtable to serialize + /// The serialized String + /// + /// [cnurse] 2/16/2005 moved to Globals + /// + /// ----------------------------------------------------------------------------- + public static string SerializeHashTableBase64(Hashtable Source) + { + string strString; + if (Source.Count != 0) + { + var bin = new BinaryFormatter(); + var mem = new MemoryStream(); + try + { + bin.Serialize(mem, Source); + strString = Convert.ToBase64String(mem.GetBuffer(), 0, Convert.ToInt32(mem.Length)); + } + catch (Exception exc) + { + Logger.Error(exc); + + strString = ""; + } + finally + { + mem.Close(); + } + } + else + { + strString = ""; + } + return strString; + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeHashTableXml serializes a Hashtable using Xml Serialization + /// + /// + /// This is the preferred method of serialization under Medium Trust + /// + /// The Hashtable to serialize + /// The serialized String + /// + /// [cnurse] 2/16/2005 moved to Globals + /// [cnurse] 01/19/2007 extracted to XmlUtils + /// + /// ----------------------------------------------------------------------------- + public static string SerializeHashTableXml(Hashtable Source) + { + return XmlUtils.SerializeDictionary(Source, "profile"); + } + + /// + /// Check whether the specific tab is a host tab. + /// + /// tab id. + /// if true means the tab is a host tab, otherwise means not a host page. + public static bool IsHostTab(int tabId) + { + bool isHostTab = false; + TabCollection hostTabs = new TabController().GetTabsByPortal(Null.NullInteger); + + if (hostTabs != null) + { + isHostTab = hostTabs.Any(t => t.Value.TabID == tabId); + } + return isHostTab; + } + + + /// + /// Return User Profile Picture Formatted Url. UserId, width and height can be passed to build a formatted Avatar Url. + /// + /// Formatted url, e.g. http://www.mysite.com/profilepic.ashx?userid={0}&h={1}&w={2} + /// + /// Usage: ascx - <asp:Image ID="avatar" runat="server" CssClass="SkinObject" /> + /// code behind - avatar.ImageUrl = string.Format(Globals.UserProfilePicFormattedUrl(), userInfo.UserID, 32, 32) + /// + public static string UserProfilePicFormattedUrl() + { + var avatarUrl = PortalController.GetCurrentPortalSettings().DefaultPortalAlias; + if (string.IsNullOrEmpty(avatarUrl)) + { + avatarUrl = HttpContext.Current.Request.Url.Host; + } + avatarUrl = string.Format("{0}://{1}{2}", + UrlUtils.IsSecureConnectionOrSslOffload(HttpContext.Current.Request) ? "https" : "http", + avatarUrl, + !HttpContext.Current.Request.Url.IsDefaultPort && !avatarUrl.Contains(":") ? ":" + HttpContext.Current.Request.Url.Port : string.Empty); + + avatarUrl += "/profilepic.ashx?userId={0}&h={1}&w={2}"; + + return avatarUrl; + } + + #region "Obsolete - retained for Binary Compatability" + + // TODO: These constants are deprecated but cannot be removed until the next batch of breaking change + // **************************************************************************************** + // Constants are inlined in code and would require a rebuild of any module or skinobject + // that may be using these constants. + + [Obsolete("Replaced in DotNetNuke 5.0 by SkinController.GetDefaultAdminSkin and SkinController.GetDefaultPortalSkin")] + public static SkinDefaults DefaultSkin + { + get + { + return SkinDefaults.GetSkinDefaults(SkinDefaultType.SkinInfo); + } + } + + /// + /// Gets the default container. + /// + /// Default Container + public static SkinDefaults DefaultContainer + { + get + { + return SkinDefaults.GetSkinDefaults(SkinDefaultType.ContainerInfo); + } + } + + [Obsolete("Replaced in DotNetNuke 5.0 by Host.GetHostSettingDictionary")] + public static Hashtable HostSettings + { + get + { + var h = new Hashtable(); + foreach (ConfigurationSetting kvp in HostController.Instance.GetSettings().Values) + { + h.Add(kvp.Key, kvp.Value); + } + return h; + } + } + + [Obsolete("Replaced in DotNetNuke 5.0 by Host.PerformanceSetting")] + public static PerformanceSettings PerformanceSetting + { + get + { + return Host.PerformanceSetting; + } + } + + [Obsolete("Deprecated in 5.1. Replaced by CachingProvider.Instance.IsWebFarm.")] + public static bool WebFarmEnabled + { + get + { + return CachingProvider.Instance().IsWebFarm(); + } + } + + #region "Html functions moved to HtmlUtils.vb" + + [Obsolete("This function has been replaced by DotNetNuke.Common.Utilities.HtmlUtils.FormatEmail")] + public static string FormatEmail(string Email) + { + return HtmlUtils.FormatEmail(Email); + } + + [Obsolete("This function has been replaced by DotNetNuke.Common.Utilities.HtmlUtils.FormatWebsite")] + public static string FormatWebsite(object Website) + { + return HtmlUtils.FormatWebsite(Website); + } + + #endregion + + #region "Xml functions moved to XmlUtils.vb" + + [Obsolete("This function has been replaced by DotNetNuke.Common.Utilities.XmlUtils.XMLEncode")] + public static string XMLEncode(string HTML) + { + return XmlUtils.XMLEncode(HTML); + } + + #endregion + + [Obsolete("This method has been deprecated.")] + public static void AddFile(string strFileName, string strExtension, string FolderPath, string strContentType, int Length, int imageWidth, int imageHeight) + { +#pragma warning disable 612,618 + // Obtain PortalSettings from Current Context + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + int PortalId = FileSystemUtils.GetFolderPortalId(_portalSettings); + var objFiles = new FileController(); + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false); + if ((objFolder != null)) + { + var objFile = new FileInfo(PortalId, strFileName, strExtension, Length, imageWidth, imageHeight, strContentType, FolderPath, objFolder.FolderID, objFolder.StorageLocation, true); + objFiles.AddFile(objFile); + } +#pragma warning restore 612,618 + } + + [Obsolete("This function has been replaced by DotNetNuke.Common.Utilities.Config.GetConnectionString")] + public static string GetDBConnectionString() + { + return Config.GetConnectionString(); + } + + [Obsolete("This method has been deprecated. ")] + public static ArrayList GetFileList(DirectoryInfo CurrentDirectory, [Optional, DefaultParameterValue("")] // ERROR: Optional parameters aren't supported in C# + string strExtensions, [Optional, DefaultParameterValue(true)] // ERROR: Optional parameters aren't supported in C# + bool NoneSpecified) + { + var arrFileList = new ArrayList(); + string strExtension = ""; + + if (NoneSpecified) + { + arrFileList.Add(new FileItem("", "<" + Localization.GetString("None_Specified") + ">")); + } + + string File = null; + string[] Files = Directory.GetFiles(CurrentDirectory.FullName); + foreach (string File_loopVariable in Files) + { + File = File_loopVariable; + if (File.IndexOf(".") > -1) + { + strExtension = File.Substring(File.LastIndexOf(".") + 1); + } + string FileName = File.Substring(CurrentDirectory.FullName.Length); + if (strExtensions.ToUpper().IndexOf(strExtension.ToUpper()) != -1 || string.IsNullOrEmpty(strExtensions)) + { + arrFileList.Add(new FileItem(FileName, FileName)); + } + } + + return arrFileList; + } + + [Obsolete("This method has been replaced by DesktopModuleController.GetDesktopModuleByModuleName() in DotNetNuke 5.0")] + public static DesktopModuleInfo GetDesktopModuleByName(string name) + { + return DesktopModuleController.GetDesktopModuleByModuleName(name, Null.NullInteger); + } + + [Obsolete("This method has been deprecated. Replaced by GetSubFolderPath(ByVal strFileNamePath As String, ByVal portaId as Integer).")] + public static string GetSubFolderPath(string strFileNamePath) + { + // Obtain PortalSettings from Current Context + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + string ParentFolderName = null; + if (IsHostTab(_portalSettings.ActiveTab.TabID)) + { + ParentFolderName = HostMapPath.Replace("/", "\\"); + } + else + { + ParentFolderName = _portalSettings.HomeDirectoryMapPath.Replace("/", "\\"); + } + string strFolderpath = strFileNamePath.Substring(0, strFileNamePath.LastIndexOf("\\") + 1); + + return strFolderpath.Substring(ParentFolderName.Length).Replace("\\", "/"); + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by the DatabaseVersion property.")] + public static string GetDatabaseVersion() + { + string strDatabaseVersion = ""; + try + { + Version databaseVersion = DataProvider.Instance().GetVersion(); + strDatabaseVersion = databaseVersion.Major.ToString("00") + databaseVersion.Minor.ToString("00") + databaseVersion.Build.ToString("00"); + } + catch (Exception ex) + { + Logger.Error(ex); + + strDatabaseVersion = "ERROR:" + ex.Message; + } + + return strDatabaseVersion; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by the DatabaseVersion property.")] + public static string GetDatabaseVersion(string separator) + { + string strDatabaseVersion = ""; + try + { + Version databaseVersion = DataProvider.Instance().GetVersion(); + strDatabaseVersion = databaseVersion.Major.ToString("00") + separator + databaseVersion.Minor.ToString("00") + separator + databaseVersion.Build.ToString("00"); + } + catch (Exception ex) + { + Logger.Error(ex); + strDatabaseVersion = "ERROR:" + ex.Message; + } + + return strDatabaseVersion; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by TabController.GetPortalTabs().")] + public static ArrayList GetPortalTabs(int intPortalId, bool blnNoneSpecified, bool blnHidden, bool blnDeleted, bool blnURL, bool bCheckAuthorised) + { + List listTabs = TabController.GetPortalTabs(intPortalId, Null.NullInteger, blnNoneSpecified, Null.NullString, blnHidden, blnDeleted, blnURL, false, bCheckAuthorised); + var arrTabs = new ArrayList(); + foreach (TabInfo objTab in listTabs) + { + TabInfo tabTemp = objTab.Clone(); + tabTemp.TabName = tabTemp.IndentedTabName; + arrTabs.Add(tabTemp); + } + return arrTabs; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by TabController.GetPortalTabs().")] + public static ArrayList GetPortalTabs(int intPortalId, bool blnIncludeActiveTab, bool blnNoneSpecified, bool blnHidden, bool blnDeleted, bool blnURL, bool bCheckAuthorised) + { + // Obtain current PortalSettings from Current Context + int excludeTabId = Null.NullInteger; + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + if (!blnIncludeActiveTab) + { + excludeTabId = _portalSettings.ActiveTab.TabID; + } + + List listTabs = TabController.GetPortalTabs(intPortalId, excludeTabId, blnNoneSpecified, Null.NullString, blnHidden, blnDeleted, blnURL, false, bCheckAuthorised); + var arrTabs = new ArrayList(); + foreach (TabInfo objTab in listTabs) + { + TabInfo tabTemp = objTab.Clone(); + tabTemp.TabName = tabTemp.IndentedTabName; + arrTabs.Add(tabTemp); + } + return arrTabs; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by TabController.GetPortalTabs().")] + public static ArrayList GetPortalTabs(ArrayList objDesktopTabs, bool blnNoneSpecified, bool blnHidden) + { + var arrPortalTabs = new ArrayList(); + TabInfo objTab = default(TabInfo); + + if (blnNoneSpecified) + { + objTab = new TabInfo(); + objTab.TabID = -1; + objTab.TabName = "<" + Localization.GetString("None_Specified") + ">"; + objTab.TabOrder = 0; + objTab.ParentId = -2; + arrPortalTabs.Add(objTab); + } + + foreach (TabInfo tab in objDesktopTabs) + { + if (!tab.IsSuperTab) + { + if ((tab.IsVisible || blnHidden) && (tab.IsDeleted == false) && (tab.TabType == TabType.Normal)) + { + TabInfo tabTemp = tab.Clone(); + tabTemp.TabName = tabTemp.IndentedTabName; + arrPortalTabs.Add(tabTemp); + } + } + } + + return arrPortalTabs; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by TabController.GetPortalTabs().")] + public static ArrayList GetPortalTabs(ArrayList objDesktopTabs, bool blnNoneSpecified, bool blnHidden, bool blnDeleted, bool blnURL) + { + var arrPortalTabs = new ArrayList(); + TabInfo objTab = default(TabInfo); + + if (blnNoneSpecified) + { + objTab = new TabInfo(); + objTab.TabID = -1; + objTab.TabName = "<" + Localization.GetString("None_Specified") + ">"; + objTab.TabOrder = 0; + objTab.ParentId = -2; + arrPortalTabs.Add(objTab); + } + + foreach (TabInfo tab in objDesktopTabs) + { + if (!tab.IsSuperTab) + { + if ((tab.IsVisible || blnHidden) && (tab.IsDeleted == false || blnDeleted) && (tab.TabType == TabType.Normal || blnURL)) + { + TabInfo tabTemp = tab.Clone(); + tabTemp.TabName = tabTemp.IndentedTabName; + arrPortalTabs.Add(tabTemp); + } + } + } + + return arrPortalTabs; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by TabController.GetPortalTabs().")] + public static ArrayList GetPortalTabs(ArrayList objDesktopTabs, int currentTab, bool blnNoneSpecified, bool blnHidden, bool blnDeleted, bool blnURL, bool bCheckAuthorised) + { + var arrPortalTabs = new ArrayList(); + TabInfo objTab = default(TabInfo); + + if (blnNoneSpecified) + { + objTab = new TabInfo(); + objTab.TabID = -1; + objTab.TabName = "<" + Localization.GetString("None_Specified") + ">"; + objTab.TabOrder = 0; + objTab.ParentId = -2; + arrPortalTabs.Add(objTab); + } + + foreach (TabInfo tab in objDesktopTabs) + { + if (((currentTab < 0) || (tab.TabID != currentTab)) && !tab.IsSuperTab) + { + if ((tab.IsVisible || blnHidden) && (tab.IsDeleted == false || blnDeleted) && (tab.TabType == TabType.Normal || blnURL)) + { + TabInfo tabTemp = tab.Clone(); + tabTemp.TabName = tabTemp.IndentedTabName; + if (bCheckAuthorised) + { + //Check if User has Administrator rights to this tab + if (TabPermissionController.CanAdminPage(tabTemp)) + { + arrPortalTabs.Add(tabTemp); + } + } + else + { + arrPortalTabs.Add(tabTemp); + } + } + } + } + + return arrPortalTabs; + } + + [Obsolete("This method has been replaced in DotNetNuke 5.0 by the Status property. and the GetStatus method.")] + public static UpgradeStatus GetUpgradeStatus() + { + return Status; + } + + [Obsolete("This method has been replaced by IsAdminSkin() in DotNetNuke 5.0, as there is no longer the concept of an Admin Tab/Page")] + public static bool IsAdminSkin(bool IsAdminTab) + { + string AdminKeys = "tab,module,importmodule,exportmodule,help"; + + string ControlKey = ""; + if ((HttpContext.Current.Request.QueryString["ctl"] != null)) + { + ControlKey = HttpContext.Current.Request.QueryString["ctl"].ToLower(); + } + + int ModuleID = -1; + if ((HttpContext.Current.Request.QueryString["mid"] != null)) + { + Int32.TryParse(HttpContext.Current.Request.QueryString["mid"], out ModuleID); + } + + return IsAdminTab || (!string.IsNullOrEmpty(ControlKey) && ControlKey != "view" && ModuleID != -1) || + (!string.IsNullOrEmpty(ControlKey) && AdminKeys.IndexOf(ControlKey) != -1 && ModuleID == -1); + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns whether the tab being displayed is in preview mode + /// + /// + /// + /// + /// + /// [Jon Henning] 9/16/2004 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DotNetNuke 5.0")] + public static bool IsTabPreview() + { + return (PortalController.GetCurrentPortalSettings().UserMode == PortalSettings.Mode.View); + } + + [Obsolete("This function has been obsoleted: Use Common.Globals.LinkClick() for proper handling of URLs")] + public static string LinkClickURL(string Link) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return LinkClick(Link, _portalSettings.ActiveTab.TabID, -1, false); + } + + [Obsolete("Deprecated PreventSQLInjection Function to consolidate Security Filter functions in the PortalSecurity class")] + public static string PreventSQLInjection(string strSQL) + { + return (new PortalSecurity()).InputFilter(strSQL, PortalSecurity.FilterFlag.NoSQL); + } + + [Obsolete("Deprecated in DNN 5.3. Replaced by UserProfileURL")] + public static string ProfileURL(int userID) + { + string strURL = ""; + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + + if (_portalSettings.UserTabId != -1) + { + strURL = NavigateURL(_portalSettings.UserTabId); + } + else + { + strURL = NavigateURL(_portalSettings.ActiveTab.TabID, "Profile", "UserID=" + userID); + } + + return strURL; + } + + [Obsolete("This method has been deprecated. Replaced by same method in FileSystemUtils class.")] + public static string UploadFile(string RootPath, HttpPostedFile objHtmlInputFile, bool Unzip) + { + return FileSystemUtils.UploadFile(RootPath, objHtmlInputFile, Unzip); + } + + #endregion + + private static readonly Stopwatch AppStopwatch = Stopwatch.StartNew(); + + public static TimeSpan ElapsedSinceAppStart + { + get + { + return AppStopwatch.Elapsed; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Guard.cs b/DNN Platform/Library/Common/Guard.cs new file mode 100644 index 00000000000..08d7781316b --- /dev/null +++ b/DNN Platform/Library/Common/Guard.cs @@ -0,0 +1,63 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; + +#endregion + +namespace DotNetNuke.Common +{ + /// + /// Object of Guard. + /// + public static class Guard + { + /// + /// Againsts the specified condition, if the condition is false, + /// it will throw an InvalidOperationException with specific message. + /// + /// if set to true [condition]. + /// The message. + /// The args. + /// + public static void Against(bool condition, string message, params object[] args) + { + Against(condition, string.Format(CultureInfo.CurrentUICulture, message, args)); + } + + /// + /// Againsts the specified condition, if the condition is false, + /// it will throw an InvalidOperationException with specific message. + /// + /// if set to true [condition]. + /// The message. + /// + public static void Against(bool condition, string message) + { + if ((condition)) + { + throw new InvalidOperationException(message); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/HttpContextSource.cs b/DNN Platform/Library/Common/HttpContextSource.cs new file mode 100644 index 00000000000..9fd557e42c4 --- /dev/null +++ b/DNN Platform/Library/Common/HttpContextSource.cs @@ -0,0 +1,60 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. + +using System; +using System.Web; + +namespace DotNetNuke.Common +{ + /// + /// A unit testable alternative to HttpContext.Current + /// + public class HttpContextSource + { + private static HttpContextBase _fakeContext; + + /// + /// Gets the current HttpContext + /// + public static HttpContextBase Current + { + get + { + if (_fakeContext != null) + { + return _fakeContext; + } + + if (HttpContext.Current != null) + { + return new HttpContextWrapper(HttpContext.Current); + } + return null; + } + } + + /// + /// Injects a fake/mock context for unit testing + /// + /// The fake context to inject + public static void RegisterInstance(HttpContextBase instance) + { + _fakeContext = instance; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Initialize.cs b/DNN Platform/Library/Common/Initialize.cs new file mode 100644 index 00000000000..39e225daf82 --- /dev/null +++ b/DNN Platform/Library/Common/Initialize.cs @@ -0,0 +1,473 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Remoting; +using System.Threading; +using System.Web; +using System.Web.Hosting; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.EventQueue; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Scheduling; +using DotNetNuke.Services.Upgrade; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.Common +{ + /// + /// The Object to initialize application. + /// + public class Initialize + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(Initialize)); + private static bool InitializedAlready; + private static readonly object InitializeLock = new object(); + + /// ----------------------------------------------------------------------------- + /// + /// CacheMappedDirectory caches the Portal Mapped Directory(s) + /// + /// + /// + /// + /// [cnurse] 1/27/2005 Moved back to App_Start from Caching Module + /// + /// ----------------------------------------------------------------------------- + private static void CacheMappedDirectory() + { + //This code is only retained for binary compatability. +#pragma warning disable 612,618 + var objFolderController = new FolderController(); + var objPortalController = new PortalController(); + ArrayList arrPortals = objPortalController.GetPortals(); + int i; + for (i = 0; i <= arrPortals.Count - 1; i++) + { + var objPortalInfo = (PortalInfo)arrPortals[i]; + objFolderController.SetMappedDirectory(objPortalInfo, HttpContext.Current); + } +#pragma warning restore 612,618 + } + + /// ----------------------------------------------------------------------------- + /// + /// CheckVersion determines whether the App is synchronized with the DB + /// + /// + /// + /// + /// [cnurse] 2/17/2005 created + /// + /// ----------------------------------------------------------------------------- + private static string CheckVersion(HttpApplication app) + { + HttpServerUtility Server = app.Server; + + bool autoUpgrade = Config.GetSetting("AutoUpgrade") == null || bool.Parse(Config.GetSetting("AutoUpgrade")); + bool useWizard = Config.GetSetting("UseInstallWizard") == null || bool.Parse(Config.GetSetting("UseInstallWizard")); + + //Determine the Upgrade status and redirect as neccessary to InstallWizard.aspx + string retValue = Null.NullString; + switch (Globals.Status) + { + case Globals.UpgradeStatus.Install: + if (autoUpgrade || useWizard) + { + retValue = useWizard ? "~/Install/InstallWizard.aspx" : "~/Install/Install.aspx?mode=install"; + } + else + { + CreateUnderConstructionPage(Server); + retValue = "~/Install/UnderConstruction.htm"; + Logger.Info("UnderConstruction page was shown because application needs to be installed, and both the AutoUpgrade and UseWizard AppSettings in web.config are false. Use /install/install.aspx?mode=install to install application. "); + } + break; + case Globals.UpgradeStatus.Upgrade: + if (autoUpgrade || useWizard) + { + retValue = useWizard ? "~/Install/UpgradeWizard.aspx" : "~/Install/Install.aspx?mode=upgrade"; + } + else + { + CreateUnderConstructionPage(Server); + retValue = "~/Install/UnderConstruction.htm"; + Logger.Info("UnderConstruction page was shown because application needs to be upgraded, and both the AutoUpgrade and UseInstallWizard AppSettings in web.config are false. Use /install/install.aspx?mode=upgrade to upgrade application. "); + } + break; + case Globals.UpgradeStatus.Error: + // here we need to check if the application is already installed + // or is in pre-install state. + // see http://support.dotnetnuke.com/project/DNN/2/item/26053 for scenarios + bool isInstalled = Globals.IsInstalled(); + + if (!isInstalled && (useWizard || autoUpgrade)) + { + // app has never been installed, and either Wizard or Autoupgrade is configured + CreateUnderConstructionPage(Server); + retValue = "~/Install/UnderConstruction.htm"; + Logger.Error("UnderConstruction page was shown because we cannot ascertain the application was ever installed, and there is no working database connection. Check database connectivity before continuing. "); + } + else + { + //500 Error - Redirect to ErrorPage + if ((HttpContext.Current != null)) + { + if (!isInstalled) + { + Logger.Error("The connection to the database has failed, the application is not installed yet, and both AutoUpgrade and UseInstallWizard are not set in web.config, a 500 error page will be shown to visitors"); + } + else + { + Logger.Error("The connection to the database has failed, however, the application is already completely installed, a 500 error page will be shown to visitors"); + } + string url = "~/ErrorPage.aspx?status=500&error=Site Unavailable&error2=Connection To The Database Failed"; + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer(url); + } + } + + break; + } + return retValue; + } + + private static void CreateUnderConstructionPage(HttpServerUtility server) + { + //create an UnderConstruction page if it does not exist already + if (!File.Exists(server.MapPath("~/Install/UnderConstruction.htm"))) + { + if (File.Exists(server.MapPath("~/Install/UnderConstruction.template.htm"))) + { + File.Copy(server.MapPath("~/Install/UnderConstruction.template.htm"), server.MapPath("~/Install/UnderConstruction.htm")); + } + } + } + + private static string InitializeApp(HttpApplication app, ref bool initialized) + { + var request = app.Request; + var redirect = Null.NullString; + + Logger.Trace("Request " + request.Url.LocalPath); + + //Don't process some of the AppStart methods if we are installing + if (!IsUpgradeOrInstallRequest(app.Request)) + { + //Check whether the current App Version is the same as the DB Version + redirect = CheckVersion(app); + if (string.IsNullOrEmpty(redirect)) + { + Logger.Info("Application Initializing"); + + //Cache Mapped Directory(s) + CacheMappedDirectory(); + //Set globals + Globals.IISAppName = request.ServerVariables["APPL_MD_PATH"]; + Globals.OperatingSystemVersion = Environment.OSVersion.Version; + Globals.NETFrameworkVersion = GetNETFrameworkVersion(); + Globals.DatabaseEngineVersion = GetDatabaseEngineVersion(); + //Try and Upgrade to Current Framewok + Upgrade.TryUpgradeNETFramework(); + + //Start Scheduler + StartScheduler(); + //Log Application Start + LogStart(); + //Process any messages in the EventQueue for the Application_Start event + EventQueueController.ProcessMessages("Application_Start"); + + ServicesRoutingManager.RegisterServiceRoutes(); + + ModuleInjectionManager.RegisterInjectionFilters(); + + //Set Flag so we can determine the first Page Request after Application Start + app.Context.Items.Add("FirstRequest", true); + + //Log Server information + ServerController.UpdateServerActivity(new ServerInfo()); + Logger.Info("Application Initialized"); + + initialized = true; + } + } + else + { + //NET Framework version is neeed by Upgrade + Globals.NETFrameworkVersion = GetNETFrameworkVersion(); + } + return redirect; + } + + private static Version GetNETFrameworkVersion() + { + string version = Environment.Version.ToString(2); + if (version == "2.0") + { + //Try and load a 3.0 Assembly + try + { + AppDomain.CurrentDomain.Load("System.Runtime.Serialization, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"); + version = "3.0"; + } + catch (Exception exc) + { + Logger.Error(exc); + } + //Try and load a 3.5 Assembly + try + { + AppDomain.CurrentDomain.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"); + version = "3.5"; + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + return new Version(version); + } + + private static Version GetDatabaseEngineVersion() + { + return DataProvider.Instance().GetDatabaseEngineVersion(); + } + + /// + /// Inits the app. + /// + /// The app. + public static void Init(HttpApplication app) + { + string redirect; + //Check if app is initialised + if (InitializedAlready && Globals.Status == Globals.UpgradeStatus.None) + { + return; + } + lock (InitializeLock) + { + //Double-Check if app was initialised by another request + if (InitializedAlready && Globals.Status == Globals.UpgradeStatus.None) + { + return; + } + //Initialize ... + redirect = InitializeApp(app, ref InitializedAlready); + } + if (!string.IsNullOrEmpty(redirect)) + { + app.Response.Redirect(redirect, true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// LogStart logs the Application Start Event + /// + /// + /// + /// + /// [cnurse] 1/27/2005 Moved back to App_Start from Logging Module + /// + /// ----------------------------------------------------------------------------- + public static void LogStart() + { + var objEv = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.BypassBuffering = true; + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.APPLICATION_START.ToString(); + objEv.AddLog(objEventLogInfo); + } + + /// ----------------------------------------------------------------------------- + /// + /// LogEnd logs the Application Start Event + /// + /// + /// + /// + /// [cnurse] 1/28/2005 Moved back to App_End from Logging Module + /// + /// ----------------------------------------------------------------------------- + public static void LogEnd() + { + try + { + ApplicationShutdownReason shutdownReason = HostingEnvironment.ShutdownReason; + string shutdownDetail = ""; + switch (shutdownReason) + { + case ApplicationShutdownReason.BinDirChangeOrDirectoryRename: + shutdownDetail = "The AppDomain shut down because of a change to the Bin folder or files contained in it."; + break; + case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename: + shutdownDetail = "The AppDomain shut down because of a change to the App_Browsers folder or files contained in it."; + break; + case ApplicationShutdownReason.ChangeInGlobalAsax: + shutdownDetail = "The AppDomain shut down because of a change to Global.asax."; + break; + case ApplicationShutdownReason.ChangeInSecurityPolicyFile: + shutdownDetail = "The AppDomain shut down because of a change in the code access security policy file."; + break; + case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename: + shutdownDetail = "The AppDomain shut down because of a change to the App_Code folder or files contained in it."; + break; + case ApplicationShutdownReason.ConfigurationChange: + shutdownDetail = "The AppDomain shut down because of a change to the application level configuration."; + break; + case ApplicationShutdownReason.HostingEnvironment: + shutdownDetail = "The AppDomain shut down because of the hosting environment."; + break; + case ApplicationShutdownReason.HttpRuntimeClose: + shutdownDetail = "The AppDomain shut down because of a call to Close."; + break; + case ApplicationShutdownReason.IdleTimeout: + shutdownDetail = "The AppDomain shut down because of the maximum allowed idle time limit."; + break; + case ApplicationShutdownReason.InitializationError: + shutdownDetail = "The AppDomain shut down because of an AppDomain initialization error."; + break; + case ApplicationShutdownReason.MaxRecompilationsReached: + shutdownDetail = "The AppDomain shut down because of the maximum number of dynamic recompiles of resources limit."; + break; + case ApplicationShutdownReason.PhysicalApplicationPathChanged: + shutdownDetail = "The AppDomain shut down because of a change to the physical path for the application."; + break; + case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename: + shutdownDetail = "The AppDomain shut down because of a change to the App_GlobalResources folder or files contained in it."; + break; + case ApplicationShutdownReason.UnloadAppDomainCalled: + shutdownDetail = "The AppDomain shut down because of a call to UnloadAppDomain."; + break; + default: + shutdownDetail = "No shutdown reason provided."; + break; + } + var objEv = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.BypassBuffering = true; + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.APPLICATION_SHUTTING_DOWN.ToString(); + objEventLogInfo.AddProperty("Shutdown Details", shutdownDetail); + objEv.AddLog(objEventLogInfo); + + Logger.InfoFormat("Application shutting down. Reason: {0}", shutdownDetail); + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + if (Globals.Status != Globals.UpgradeStatus.Install) + { + //purge log buffer + LoggingProvider.Instance().PurgeLogBuffer(); + } + } + + private static bool IsUpgradeOrInstallRequest(HttpRequest request) + { + var url = request.Url.LocalPath.ToLower(); + + return url.EndsWith("/install.aspx") + || url.Contains("/upgradewizard.aspx") + || url.Contains("/installwizard.aspx"); + } + + public static void RunSchedule(HttpRequest request) + { + if (!IsUpgradeOrInstallRequest(request)) + { + try + { + if (SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD && SchedulingProvider.ReadyForPoll) + { + Logger.Trace("Running Schedule " + (SchedulingProvider.SchedulerMode)); + var scheduler = SchedulingProvider.Instance(); + var requestScheduleThread = new Thread(scheduler.ExecuteTasks) {IsBackground = true}; + requestScheduleThread.Start(); + SchedulingProvider.ScheduleLastPolled = DateTime.Now; + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// StopScheduler stops the Scheduler + /// + /// + /// + /// + /// [cnurse] 1/28/2005 Moved back to App_End from Scheduling Module + /// + /// ----------------------------------------------------------------------------- + public static void StopScheduler() + { + //stop scheduled jobs + SchedulingProvider.Instance().Halt("Stopped by Application_End"); + } + + /// ----------------------------------------------------------------------------- + /// + /// StartScheduler starts the Scheduler + /// + /// + /// + /// + /// [cnurse] 1/27/2005 Moved back to App_Start from Scheduling Module + /// + /// ----------------------------------------------------------------------------- + public static void StartScheduler() + { + //instantiate APPLICATION_START scheduled jobs + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) + { + Logger.Trace("Running Schedule " + SchedulingProvider.SchedulerMode); + var scheduler = SchedulingProvider.Instance(); + scheduler.RunEventSchedule(EventName.APPLICATION_START); + var newThread = new Thread(scheduler.Start) + { + IsBackground = true, + Name = "Scheduler Thread" + }; + newThread.Start(); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Internal/GlobalsImpl.cs b/DNN Platform/Library/Common/Internal/GlobalsImpl.cs new file mode 100644 index 00000000000..24593642191 --- /dev/null +++ b/DNN Platform/Library/Common/Internal/GlobalsImpl.cs @@ -0,0 +1,132 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Text; +using System.Web; +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Common.Internal +{ + public class GlobalsImpl : IGlobals + { + public string ApplicationPath + { + get { return Globals.ApplicationPath; } + } + + public string HostMapPath + { + get { return Globals.HostMapPath; } + } + + public string GetSubFolderPath(string strFileNamePath, int portalId) + { + return Globals.GetSubFolderPath(strFileNamePath, portalId); + } + + public string LinkClick(string link, int tabId, int moduleId) + { + return Globals.LinkClick(link, tabId, moduleId); + } + + public string ResolveUrl(string url) + { + return Globals.ResolveUrl(url); + } + + public string GetDomainName(Uri requestedUri) + { + return GetDomainName(requestedUri, false); + } + + public string GetDomainName(Uri requestedUri, bool parsePortNumber) + { + var domainName = new StringBuilder(); + + // split both URL separater, and parameter separator + // We trim right of '?' so test for filename extensions can occur at END of URL-componenet. + // Test: 'www.aspxforum.net' should be returned as a valid domain name. + // just consider left of '?' in URI + // Binary, else '?' isn't taken literally; only interested in one (left) string + string uri = requestedUri.ToString(); + string hostHeader = Config.GetSetting("HostHeader"); + if (!String.IsNullOrEmpty(hostHeader)) + { + uri = uri.ToLower().Replace(hostHeader.ToLower(), ""); + } + int queryIndex = uri.IndexOf("?", StringComparison.Ordinal); + if (queryIndex > -1) + { + uri = uri.Substring(0, queryIndex); + } + string[] url = uri.Split('/'); + for (queryIndex = 2; queryIndex <= url.GetUpperBound(0); queryIndex++) + { + bool needExit = false; + switch (url[queryIndex].ToLower()) + { + case "": + continue; + case "admin": + case "controls": + case "desktopmodules": + case "mobilemodules": + case "premiummodules": + case "providers": + needExit = true; + break; + default: + // exclude filenames ENDing in ".aspx" or ".axd" --- + // we'll use reverse match, + // - but that means we are checking position of left end of the match; + // - and to do that, we need to ensure the string we test against is long enough; + if ((url[queryIndex].Length >= ".aspx".Length)) + { + if (url[queryIndex].ToLower().LastIndexOf(".aspx", StringComparison.Ordinal) == (url[queryIndex].Length - (".aspx".Length)) || + url[queryIndex].ToLower().LastIndexOf(".axd", StringComparison.Ordinal) == (url[queryIndex].Length - (".axd".Length)) || + url[queryIndex].ToLower().LastIndexOf(".ashx", StringComparison.Ordinal) == (url[queryIndex].Length - (".ashx".Length))) + { + break; + } + } + // non of the exclusionary names found + domainName.Append((!String.IsNullOrEmpty(domainName.ToString()) ? "/" : "") + url[queryIndex]); + break; + } + if (needExit) + { + break; + } + } + if (parsePortNumber) + { + if (domainName.ToString().IndexOf(":", StringComparison.Ordinal) != -1) + { + if (!Globals.UsePortNumber()) + { + domainName = domainName.Replace(":" + requestedUri.Port, ""); + } + } + } + return domainName.ToString(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Internal/IGlobals.cs b/DNN Platform/Library/Common/Internal/IGlobals.cs new file mode 100644 index 00000000000..646fc61b634 --- /dev/null +++ b/DNN Platform/Library/Common/Internal/IGlobals.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Web; + +namespace DotNetNuke.Common.Internal +{ + + public interface IGlobals + { + /// + /// Gets the application path. + /// + string ApplicationPath { get; } + + /// + /// Gets or sets the host map path. + /// + /// ApplicationMapPath + "Portals\_default\" + string HostMapPath { get; } + + /// + /// Returns the folder path under the root for the portal + /// + /// The folder the absolute path + /// Portal Id. + string GetSubFolderPath(string fileNamePath, int portalId); + + /// + /// Gets Link click url. + /// + /// The link. + /// The tab ID. + /// The module ID. + /// Formatted url. + string LinkClick(string link, int tabId, int moduleId); + + /// + /// Generates the correctly formatted url + /// + /// + /// + /// The url to format. + /// The formatted (resolved) url + string ResolveUrl(string url); + + /// + /// Gets the name of the domain. + /// + /// The requested Uri + /// domain name + string GetDomainName(Uri requestedUri); + + /// + /// returns the domain name of the current request ( ie. www.domain.com or 207.132.12.123 or www.domain.com/directory if subhost ) + /// + /// The requested Uri + /// if set to true [parse port number]. + /// domain name + string GetDomainName(Uri requestedUri, bool parsePortNumber); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Internal/ServicesRoutingManager.cs b/DNN Platform/Library/Common/Internal/ServicesRoutingManager.cs new file mode 100644 index 00000000000..cdffa667f70 --- /dev/null +++ b/DNN Platform/Library/Common/Internal/ServicesRoutingManager.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; + +namespace DotNetNuke.Common.Internal +{ + public static class ServicesRoutingManager + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ServicesRoutingManager)); + + public static void RegisterServiceRoutes() + { + const string unableToRegisterServiceRoutes = "Unable to register service routes"; + + try + { + //new ServicesRoutingManager().RegisterRoutes(); + var instance = Activator.CreateInstance("DotNetNuke.Web", + "DotNetNuke.Web.Api.Internal.ServicesRoutingManager"); + + var method = instance.Unwrap().GetType().GetMethod("RegisterRoutes"); + method.Invoke(instance.Unwrap(), new object[0]); + } + catch (Exception e) + { + Logger.Error(unableToRegisterServiceRoutes, e); + } + } + + public static void ReRegisterServiceRoutesWhileSiteIsRunning() + { + //by clearing a "fake" key on the caching provider we can echo this + //command to all the members of a web farm + //the caching provider will call to make the actual registration of new routes + CachingProvider.Instance().Clear("ServiceFrameworkRoutes", "-1"); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Internal/TestableGlobals.cs b/DNN Platform/Library/Common/Internal/TestableGlobals.cs new file mode 100644 index 00000000000..12b8941a6ce --- /dev/null +++ b/DNN Platform/Library/Common/Internal/TestableGlobals.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Common.Internal +{ + public class TestableGlobals : ServiceLocator + { + protected override Func GetFactory() + { + return () => new GlobalsImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Lists/EntryInfo.cs b/DNN Platform/Library/Common/Lists/EntryInfo.cs new file mode 100644 index 00000000000..9889d0e5445 --- /dev/null +++ b/DNN Platform/Library/Common/Lists/EntryInfo.cs @@ -0,0 +1,240 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Common.Lists +{ + [Serializable] + public class ListEntryInfo + { + private int _DefinitionID; + private string _Description = Null.NullString; + private string _DisplayName = Null.NullString; + private int _EntryID; + private bool _HasChildren; + private string _Key = Null.NullString; + private int _Level; + private string _ListName = Null.NullString; + private string _Parent = Null.NullString; + private int _ParentID; + private string _ParentKey = Null.NullString; + private int _PortalID; + private int _SortOrder; + private string _Text = Null.NullString; + private string _Value = Null.NullString; + private bool _systemlist; + + public int EntryID + { + get + { + return _EntryID; + } + set + { + _EntryID = value; + } + } + + public int PortalID + { + get + { + return _PortalID; + } + set + { + _PortalID = value; + } + } + + public string Key + { + get + { + string _Key = ParentKey.Replace(":", "."); + if (!string.IsNullOrEmpty(_Key)) + { + _Key += "."; + } + return _Key + ListName + ":" + Value; + } + } + + public string ListName + { + get + { + return _ListName; + } + set + { + _ListName = value; + } + } + + public string DisplayName + { + get + { + return ListName + ":" + Text; + } + } + + public string Value + { + get + { + return _Value; + } + set + { + _Value = value; + } + } + + public string Text + { + get + { + return _Text; + } + set + { + _Text = value; + } + } + + public string Description + { + get + { + return _Description; + } + set + { + _Description = value; + } + } + + public int ParentID + { + get + { + return _ParentID; + } + set + { + _ParentID = value; + } + } + + public string Parent + { + get + { + return _Parent; + } + set + { + _Parent = value; + } + } + + public int Level + { + get + { + return _Level; + } + set + { + _Level = value; + } + } + + public int SortOrder + { + get + { + return _SortOrder; + } + set + { + _SortOrder = value; + } + } + + public int DefinitionID + { + get + { + return _DefinitionID; + } + set + { + _DefinitionID = value; + } + } + + public bool HasChildren + { + get + { + return _HasChildren; + } + set + { + _HasChildren = value; + } + } + + public string ParentKey + { + get + { + return _ParentKey; + } + set + { + _ParentKey = value; + } + } + + public bool SystemList + { + get + { + return _systemlist; + } + set + { + _systemlist = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Lists/ListController.cs b/DNN Platform/Library/Common/Lists/ListController.cs new file mode 100644 index 00000000000..a3989e15034 --- /dev/null +++ b/DNN Platform/Library/Common/Lists/ListController.cs @@ -0,0 +1,349 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Linq; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Common.Lists +{ + public class ListController + { + private void ClearCache(int PortalId) + { + DataCache.ClearListsCache(PortalId); + } + + private ListInfo FillListInfo(IDataReader dr, bool CheckForOpenDataReader) + { + ListInfo objListInfo = null; + // read datareader + bool canContinue = true; + if (CheckForOpenDataReader) + { + canContinue = false; + if (dr.Read()) + { + canContinue = true; + } + } + if (canContinue) + { + objListInfo = new ListInfo(Convert.ToString(dr["ListName"])); + { + objListInfo.Level = Convert.ToInt32(dr["Level"]); + objListInfo.PortalID = Convert.ToInt32(dr["PortalID"]); + objListInfo.DefinitionID = Convert.ToInt32(dr["DefinitionID"]); + objListInfo.EntryCount = Convert.ToInt32(dr["EntryCount"]); + objListInfo.ParentID = Convert.ToInt32(dr["ParentID"]); + objListInfo.ParentKey = Convert.ToString(dr["ParentKey"]); + objListInfo.Parent = Convert.ToString(dr["Parent"]); + objListInfo.ParentList = Convert.ToString(dr["ParentList"]); + objListInfo.EnableSortOrder = (Convert.ToInt32(dr["MaxSortOrder"]) > 0); + objListInfo.SystemList = Convert.ToInt32(dr["SystemList"]) > 0; + } + } + return objListInfo; + } + + private Dictionary FillListInfoDictionary(IDataReader dr) + { + var dic = new Dictionary(); + try + { + ListInfo obj; + while (dr.Read()) + { + // fill business object + obj = FillListInfo(dr, false); + if (!dic.ContainsKey(obj.Key)) + { + dic.Add(obj.Key, obj); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + // close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + private object GetListInfoDictionaryCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int) cacheItemArgs.ParamList[0]; + return FillListInfoDictionary(DataProvider.Instance().GetLists(portalId)); + } + + private Dictionary GetListInfoDictionary(int PortalId) + { + string cacheKey = string.Format(DataCache.ListsCacheKey, PortalId); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.ListsCacheTimeOut, DataCache.ListsCachePriority, PortalId), GetListInfoDictionaryCallBack); + } + + public int AddListEntry(ListEntryInfo ListEntry) + { + bool EnableSortOrder = (ListEntry.SortOrder > 0); + ClearCache(ListEntry.PortalID); + int entryId = DataProvider.Instance().AddListEntry(ListEntry.ListName, + ListEntry.Value, + ListEntry.Text, + ListEntry.ParentID, + ListEntry.Level, + EnableSortOrder, + ListEntry.DefinitionID, + ListEntry.Description, + ListEntry.PortalID, + ListEntry.SystemList, + UserController.GetCurrentUserInfo().UserID); + + if (entryId != Null.NullInteger) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(ListEntry, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LISTENTRY_CREATED); + } + + return entryId; + } + + public void DeleteList(string ListName, string ParentKey) + { + ListInfo list = GetListInfo(ListName, ParentKey); + var objEventLog = new EventLogController(); + objEventLog.AddLog("ListName", ListName, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.LISTENTRY_DELETED); + DataProvider.Instance().DeleteList(ListName, ParentKey); + if (list != null) + ClearCache(list.PortalID); + } + + public void DeleteList(ListInfo list, bool includeChildren) + { + if (list == null) + { + return; + } + + var lists = new SortedList(); + lists.Add(list.Key, list); + //add Children + if (includeChildren) + { + foreach (KeyValuePair listPair in GetListInfoDictionary(list.PortalID)) + { + if ((listPair.Value.ParentList.StartsWith(list.Key))) + { + lists.Add(listPair.Value.Key.Replace(":", "."), listPair.Value); + } + } + } + //Delete items in reverse order so deeper descendants are removed before their parents + for (int i = lists.Count - 1; i >= 0; i += -1) + { + DeleteList(lists.Values[i].Name, lists.Values[i].ParentKey); + } + } + + public void DeleteListEntryByID(int EntryID, bool DeleteChild) + { + ListEntryInfo entry = GetListEntryInfo(EntryID); + DataProvider.Instance().DeleteListEntryByID(EntryID, DeleteChild); + ClearCache(entry.PortalID); + } + + public void DeleteListEntryByListName(string ListName, string Value, bool DeleteChild) + { + ListEntryInfo entry = GetListEntryInfo(ListName, Value); + DataProvider.Instance().DeleteListEntryByListName(ListName, Value, DeleteChild); + ClearCache(entry.PortalID); + } + + public ListEntryInfo GetListEntryInfo(int EntryID) + { + return (ListEntryInfo) CBO.FillObject(DataProvider.Instance().GetListEntry(EntryID), typeof (ListEntryInfo)); + } + + public ListEntryInfo GetListEntryInfo(string ListName, string Value) + { + return (ListEntryInfo) CBO.FillObject(DataProvider.Instance().GetListEntry(ListName, Value), typeof (ListEntryInfo)); + } + + public IEnumerable GetListEntryInfoItems(string listName) + { + return GetListEntryInfoItems(listName, "", Null.NullInteger); + } + + public IEnumerable GetListEntryInfoItems(string listName, string parentKey) + { + return GetListEntryInfoItems(listName, parentKey, Null.NullInteger); + } + + public IEnumerable GetListEntryInfoItems(string listName, string parentKey, int portalId) + { + return CBO.FillCollection(DataProvider.Instance().GetListEntriesByListName(listName, parentKey, portalId)); + } + + public Dictionary GetListEntryInfoDictionary(string listName) + { + return GetListEntryInfoDictionary(listName, "", Null.NullInteger); + } + + public Dictionary GetListEntryInfoDictionary(string listName, string parentKey) + { + return GetListEntryInfoDictionary(listName, parentKey, Null.NullInteger); + } + + public Dictionary GetListEntryInfoDictionary(string listName, string parentKey, int portalId) + { + return ListEntryInfoItemsToDictionary(GetListEntryInfoItems(listName, parentKey, portalId)); + } + + private static Dictionary ListEntryInfoItemsToDictionary(IEnumerable items) + { + var dict = new Dictionary(); + items.ToList().ForEach(x => dict.Add(x.Key, x)); + + return dict; + } + + public ListInfo GetListInfo(string ListName) + { + return GetListInfo(ListName, ""); + } + + public ListInfo GetListInfo(string ListName, string ParentKey) + { + return GetListInfo(ListName, ParentKey, -1); + } + + public ListInfo GetListInfo(string ListName, string ParentKey, int PortalID) + { + ListInfo list = null; + string key = Null.NullString; + if (!string.IsNullOrEmpty(ParentKey)) + { + key = ParentKey + ":"; + } + key += ListName; + Dictionary dicLists = GetListInfoDictionary(PortalID); + if (!dicLists.TryGetValue(key, out list)) + { + IDataReader dr = DataProvider.Instance().GetList(ListName, ParentKey, PortalID); + try + { + list = FillListInfo(dr, true); + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + return list; + } + + public ListInfoCollection GetListInfoCollection() + { + return GetListInfoCollection(""); + } + + public ListInfoCollection GetListInfoCollection(string ListName) + { + return GetListInfoCollection(ListName, ""); + } + + public ListInfoCollection GetListInfoCollection(string ListName, string ParentKey) + { + return GetListInfoCollection(ListName, ParentKey, -1); + } + + public ListInfoCollection GetListInfoCollection(string ListName, string ParentKey, int PortalID) + { + IList lists = new ListInfoCollection(); + foreach (KeyValuePair listPair in GetListInfoDictionary(PortalID)) + { + ListInfo list = listPair.Value; + if ((list.Name == ListName || string.IsNullOrEmpty(ListName)) && (list.ParentKey == ParentKey || string.IsNullOrEmpty(ParentKey)) && + (list.PortalID == PortalID || PortalID == Null.NullInteger)) + { + lists.Add(list); + } + } + return (ListInfoCollection) lists; + } + + public void UpdateListEntry(ListEntryInfo ListEntry) + { + DataProvider.Instance().UpdateListEntry(ListEntry.EntryID, ListEntry.Value, ListEntry.Text, ListEntry.Description, UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(ListEntry, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LISTENTRY_UPDATED); + ClearCache(ListEntry.PortalID); + } + + public void UpdateListSortOrder(int EntryID, bool MoveUp) + { + DataProvider.Instance().UpdateListSortOrder(EntryID, MoveUp); + ListEntryInfo entry = GetListEntryInfo(EntryID); + ClearCache(entry.PortalID); + } + + [Obsolete("Obsoleted in 6.0.1 use IEnumerable GetListEntryInfoXXX(string) instead"), EditorBrowsable(EditorBrowsableState.Never)] + public ListEntryInfoCollection GetListEntryInfoCollection(string listName) + { + return GetListEntryInfoCollection(listName, "", Null.NullInteger); + } + + [Obsolete("Obsoleted in 6.0.1 use IEnumerable GetListEntryInfoXXX(string, string, int) instead"), EditorBrowsable(EditorBrowsableState.Never)] + public ListEntryInfoCollection GetListEntryInfoCollection(string listName, string parentKey) + { + return GetListEntryInfoCollection(listName, parentKey, Null.NullInteger); + } + + [Obsolete("Obsoleted in 6.0.1 use IEnumerable GetListEntryInfoXXX(string, string, int) instead"), EditorBrowsable(EditorBrowsableState.Never)] + public ListEntryInfoCollection GetListEntryInfoCollection(string listName, string parentKey, int portalId) + { + var items = GetListEntryInfoItems(listName, parentKey, portalId); + + var collection = new ListEntryInfoCollection(); + if (items != null) + { + items.ToList().ForEach(x => collection.Add(x.Key, x)); + } + return collection; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Lists/ListEntryCollection.cs b/DNN Platform/Library/Common/Lists/ListEntryCollection.cs new file mode 100644 index 00000000000..cb01eaf1360 --- /dev/null +++ b/DNN Platform/Library/Common/Lists/ListEntryCollection.cs @@ -0,0 +1,98 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; + +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Common.Lists +{ + [Serializable] + [Obsolete("Obsoleted in 6.0.1. Replaced by using generic collections of ListEntryInfo objects"), EditorBrowsable(EditorBrowsableState.Never)] + public class ListEntryInfoCollection : CollectionBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ListEntryInfoCollection)); + private readonly Hashtable _keyIndexLookup = new Hashtable(); + + public ListEntryInfo Item(int index) + { + try + { + return (ListEntryInfo) base.List[index]; + } + catch (Exception exc) + { + Logger.Error(exc); + return null; + } + } + + public ListEntryInfo Item(string key) + { + int index; + // + try + { + if (_keyIndexLookup[key.ToLower()] == null) + { + return null; + } + } + catch (Exception exc) + { + Logger.Error(exc); + return null; + } + index = Convert.ToInt32(_keyIndexLookup[key.ToLower()]); + return (ListEntryInfo) base.List[index]; + } + + public ListEntryInfo GetChildren(string parentName) + { + return Item(parentName); + } + + internal new void Clear() + { + _keyIndexLookup.Clear(); + base.Clear(); + } + + public void Add(string key, ListEntryInfo value) + { + int index; + try //Do validation first + { + index = base.List.Add(value); + _keyIndexLookup.Add(key.ToLower(), index); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Lists/ListInfo.cs b/DNN Platform/Library/Common/Lists/ListInfo.cs new file mode 100644 index 00000000000..d26f25788d2 --- /dev/null +++ b/DNN Platform/Library/Common/Lists/ListInfo.cs @@ -0,0 +1,227 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; + +#endregion + +namespace DotNetNuke.Common.Lists +{ + [Serializable] + public class ListInfo : BaseEntityInfo + { + private int mDefinitionID = Null.NullInteger; + private bool mEnableSortOrder = Null.NullBoolean; + private int mEntryCount; + private bool mIsPopulated = Null.NullBoolean; + private int mLevel; + private string mName = Null.NullString; + private string mParent = Null.NullString; + private int mParentID; + private string mParentKey = Null.NullString; + private string mParentList = Null.NullString; + private int mPortalID = Null.NullInteger; + private bool mSystemList = Null.NullBoolean; + + public ListInfo(string Name) + { + mName = Name; + } + + public ListInfo() + { + } + + public string Name + { + get + { + return mName; + } + set + { + mName = value; + } + } + + public string DisplayName + { + get + { + string _DisplayName = Parent; + if (!string.IsNullOrEmpty(_DisplayName)) + { + _DisplayName += ":"; + } + return _DisplayName + Name; + } + } + + public int Level + { + get + { + return mLevel; + } + set + { + mLevel = value; + } + } + + public int DefinitionID + { + get + { + return mDefinitionID; + } + set + { + mDefinitionID = value; + } + } + + public string Key + { + get + { + string _Key = ParentKey; + if (!string.IsNullOrEmpty(_Key)) + { + _Key += ":"; + } + return _Key + Name; + } + } + + public int EntryCount + { + get + { + return mEntryCount; + } + set + { + mEntryCount = value; + } + } + + public int PortalID + { + get + { + return mPortalID; + } + set + { + mPortalID = value; + } + } + + public int ParentID + { + get + { + return mParentID; + } + set + { + mParentID = value; + } + } + + public string ParentKey + { + get + { + return mParentKey; + } + set + { + mParentKey = value; + } + } + + public string Parent + { + get + { + return mParent; + } + set + { + mParent = value; + } + } + + public string ParentList + { + get + { + return mParentList; + } + set + { + mParentList = value; + } + } + + public bool IsPopulated + { + get + { + return mIsPopulated; + } + set + { + mIsPopulated = value; + } + } + + public bool EnableSortOrder + { + get + { + return mEnableSortOrder; + } + set + { + mEnableSortOrder = value; + } + } + + public bool SystemList + { + get + { + return mSystemList; + } + set + { + mSystemList = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Lists/ListInfoCollection.cs b/DNN Platform/Library/Common/Lists/ListInfoCollection.cs new file mode 100644 index 00000000000..e220e32ea8e --- /dev/null +++ b/DNN Platform/Library/Common/Lists/ListInfoCollection.cs @@ -0,0 +1,152 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Common.Lists +{ + [Serializable] + public class ListInfoCollection : CollectionBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ListInfoCollection)); + private readonly Hashtable mKeyIndexLookup = new Hashtable(); + + public ListInfo GetChildren(string ParentName) + { + return (ListInfo) Item(ParentName); + } + + internal new void Clear() + { + mKeyIndexLookup.Clear(); + base.Clear(); + } + + public void Add(string key, object value) + { + int index; + // + try + { + index = base.List.Add(value); + mKeyIndexLookup.Add(key.ToLower(), index); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + public object Item(int index) + { + try + { + object obj; + obj = base.List[index]; + return obj; + } + catch (Exception exc) + { + Logger.Error(exc); + return null; + } + } + + public object Item(string key) + { + int index; + object obj; + try //Do validation first + { + if (mKeyIndexLookup[key.ToLower()] == null) + { + return null; + } + } + catch (Exception exc) + { + Logger.Error(exc); + return null; + } + index = Convert.ToInt32(mKeyIndexLookup[key.ToLower()]); + obj = base.List[index]; + return obj; + } + + // Another method, get Lists on demand + public object Item(string key, bool Cache) + { + int index; + object obj = null; + bool itemExists = false; + try //Do validation first + { + if (mKeyIndexLookup[key.ToLower()] != null) + { + itemExists = true; + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + //key will be in format Country.US:Region + if (!itemExists) + { + var ctlLists = new ListController(); + string listName = key.Substring(key.IndexOf(":") + 1); + string parentKey = key.Replace(listName, "").TrimEnd(':'); + ListInfo listInfo = ctlLists.GetListInfo(listName, parentKey); + //the collection has been cache, so add this entry list into it if specified + if (Cache) + { + Add(listInfo.Key, listInfo); + return listInfo; + } + } + else + { + index = Convert.ToInt32(mKeyIndexLookup[key.ToLower()]); + obj = base.List[index]; + } + return obj; + } + + public ArrayList GetChild(string ParentKey) + { + var childList = new ArrayList(); + foreach (object child in List) + { + if (((ListInfo) child).Key.IndexOf(ParentKey.ToLower()) > -1) + { + childList.Add(child); + } + } + return childList; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Requires.cs b/DNN Platform/Library/Common/Requires.cs new file mode 100644 index 00000000000..9750b21c976 --- /dev/null +++ b/DNN Platform/Library/Common/Requires.cs @@ -0,0 +1,195 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Common +{ + /// + /// Assert Class. + /// + public static class Requires + { + #region "Public Methods" + + /// + /// Determines whether argValue is type of T. + /// + /// + /// Name of the arg. + /// The arg value. + /// + public static void IsTypeOf(string argName, object argValue) + { + if (!((argValue) is T)) + { + throw new ArgumentException(Localization.GetExceptionMessage("ValueMustBeOfType", "The argument '{0}' must be of type '{1}'.", argName, typeof (T).FullName)); + } + } + + /// + /// Determines whether argValue is less than zero. + /// + /// Name of the arg. + /// The arg value. + /// + public static void NotNegative(string argName, int argValue) + { + if (argValue < 0) + { + throw new ArgumentOutOfRangeException(argName, Localization.GetExceptionMessage("ValueCannotBeNegative", "The argument '{0}' cannot be negative.", argName)); + } + } + + /// + /// Determines whether the argValue is null. + /// + /// Name of the arg. + /// The arg value. + /// + public static void NotNull(string argName, object argValue) + { + if (argValue == null) + { + throw new ArgumentNullException(argName); + } + } + + /// + /// Determines whether the argValue is null or empty. + /// + /// Name of the arg. + /// The arg value. + /// + public static void NotNullOrEmpty(string argName, string argValue) + { + if (string.IsNullOrEmpty(argValue)) + { + throw new ArgumentException(Localization.GetExceptionMessage("ArgumentCannotBeNullOrEmpty", "The argument '{0}' cannot be null or empty.", argName), argName); + } + } + + /// + /// Determins whether propertyValye is not null or empty. + /// + /// Name of the arg. + /// The arg property. + /// The property value. + /// + public static void PropertyNotNullOrEmpty(string argName, string argProperty, string propertyValue) + { + if (string.IsNullOrEmpty(propertyValue)) + { + throw new ArgumentException(argName, + Localization.GetExceptionMessage("PropertyCannotBeNullOrEmpty", "The property '{1}' in object '{0}' cannot be null or empty.", argName, argProperty)); + } + } + + /// + /// Determines whether propertyValue is less than zero. + /// + /// Name of the arg. + /// The arg property. + /// The property value. + /// + public static void PropertyNotNegative(string argName, string argProperty, int propertyValue) + { + if (propertyValue < 0) + { + throw new ArgumentOutOfRangeException(argName, + Localization.GetExceptionMessage("PropertyCannotBeNegative", "The property '{1}' in object '{0}' cannot be negative.", argName, argProperty)); + } + } + + /// + /// Determines whether propertyValue equal to testValue. + /// + /// The type of the value. + /// Name of the arg. + /// The arg property. + /// The property value. + /// The test value. + /// + public static void PropertyNotEqualTo(string argName, string argProperty, TValue propertyValue, TValue testValue) where TValue : IEquatable + { + if (propertyValue.Equals(testValue)) + { + throw new ArgumentException(argName, Localization.GetExceptionMessage("PropertyNotEqualTo", "The property '{1}' in object '{0}' is invalid.", argName, argProperty)); + } + } + + #endregion + } + + public static class Arg + { + #region "Public Methods" + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.IsTypeOf()")] + public static void IsTypeOf(string argName, object argValue) + { + Requires.IsTypeOf(argName, argValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.NotNegative()")] + public static void NotNegative(string argName, int argValue) + { + Requires.NotNegative(argName, argValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.NotNull()")] + public static void NotNull(string argName, object argValue) + { + Requires.NotNull(argName, argValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.NotNullOrEmpty()")] + public static void NotNullOrEmpty(string argName, string argValue) + { + Requires.NotNullOrEmpty(argName, argValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.PropertyNotNullOrEmpty()")] + public static void PropertyNotNullOrEmpty(string argName, string argProperty, string propertyValue) + { + Requires.PropertyNotNullOrEmpty(argName, argProperty, propertyValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.PropertyNotNegative()")] + public static void PropertyNotNegative(string argName, string argProperty, int propertyValue) + { + Requires.PropertyNotNegative(argName, argProperty, propertyValue); + } + + [Obsolete("Deprecated in DNN 5.4.0. Replaced by Requires.PropertyNotEqualTo()")] + public static void PropertyNotEqualTo(string argName, string argProperty, TValue propertyValue, TValue testValue) where TValue : IEquatable + { + Requires.PropertyNotEqualTo(argName, argProperty, propertyValue, testValue); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Common/SerializableKeyValuePair.cs b/DNN Platform/Library/Common/SerializableKeyValuePair.cs new file mode 100644 index 00000000000..e429f1e0ccd --- /dev/null +++ b/DNN Platform/Library/Common/SerializableKeyValuePair.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Common +{ + [DataContract] + public class SerializableKeyValuePair + { + [DataMember(Name = "key")] + public TKey Key { get; set; } + + [DataMember(Name = "value")] + public TValue Value { get; set; } + + public SerializableKeyValuePair(TKey key, TValue value) + { + Key = key; + Value = value; + } + + public override string ToString() + { + return Json.Serialize(this); + } + } + +} diff --git a/DNN Platform/Library/Common/Utilities/CBO.cs b/DNN Platform/Library/Common/Utilities/CBO.cs new file mode 100644 index 00000000000..58d845f9901 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/CBO.cs @@ -0,0 +1,1385 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; + +using DotNetNuke.Entities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Common.Utilities + /// Class: CBO + /// ----------------------------------------------------------------------------- + /// + /// The CBO class generates objects. + /// + /// + /// [cnurse] 12/01/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public class CBO + { + #region Private Constants + + private const string defaultPrimaryKey = "ItemID"; + + private const string objectMapCacheKey = "ObjectMap_"; + + #endregion + + #region Private Shared Methods + + #region Object Creation/Hydration Helper Methods + + /// ----------------------------------------------------------------------------- + /// + /// CreateObjectFromReader creates an object of a specified type from the + /// provided DataReader + /// + /// The type of the Object + /// The IDataReader to use to fill the object + /// A flag that indicates whether the DataReader should be closed + /// The object (TObject) + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static object CreateObjectFromReader(Type objType, IDataReader dr, bool closeReader) + { + object objObject = null; + bool isSuccess = Null.NullBoolean; + bool canRead = true; + + if (closeReader) + { + canRead = false; + //read datareader + if (dr.Read()) + { + canRead = true; + } + } + try + { + if (canRead) + { + //Create the Object + objObject = CreateObject(objType, false); + + //hydrate the custom business object + FillObjectFromReader(objObject, dr); + } + isSuccess = true; + } + finally + { + //Ensure DataReader is closed + if ((!isSuccess)) + { + closeReader = true; + } + CloseDataReader(dr, closeReader); + } + return objObject; + } + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionaryFromReader fills a dictionary of objects of a specified type + /// from a DataReader. + /// + /// The type of the key + /// The type of the value + /// The key field for the object. This is used as + /// the key in the Dictionary. + /// The IDataReader to use to fill the objects + /// The Dictionary to fill. + /// Whether close the data reader when operation complete. + /// A Dictionary of objects (T) + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static IDictionary FillDictionaryFromReader(string keyField, IDataReader dr, + IDictionary + objDictionary, + bool closeReader) + { + TValue objObject; + TKey keyValue = default(TKey); + bool isSuccess = Null.NullBoolean; + + try + { + //iterate datareader + while (dr.Read()) + { + //Create the Object + objObject = (TValue) CreateObjectFromReader(typeof (TValue), dr, false); + if (keyField == "KeyID" && objObject is IHydratable) + { + //Get the value of the key field from the KeyID + keyValue = (TKey) Null.SetNull(((IHydratable) objObject).KeyID, keyValue); + } + else + { + //Get the value of the key field from the DataReader + if (typeof (TKey).Name == "Int32" && dr[keyField].GetType().Name == "Decimal") + { + keyValue = (TKey) Convert.ChangeType(Null.SetNull(dr[keyField], keyValue), typeof (TKey)); + } + else if (typeof (TKey).Name.ToLower() == "string" && + dr[keyField].GetType().Name.ToLower() == "dbnull") + { + keyValue = (TKey) Convert.ChangeType(Null.SetNull(dr[keyField], ""), typeof (TKey)); + } + else + { + keyValue = (TKey) Convert.ChangeType(Null.SetNull(dr[keyField], ""), typeof (TKey)); + } + } + //add to dictionary + if (objObject != null) + { + objDictionary[keyValue] = objObject; + } + } + isSuccess = true; + } + finally + { + //Ensure DataReader is closed + if ((!isSuccess)) + { + closeReader = true; + } + CloseDataReader(dr, closeReader); + } + + //Return the dictionary + return objDictionary; + } + + /// ----------------------------------------------------------------------------- + /// + /// FillListFromReader fills a list of objects of a specified type + /// from a DataReader + /// + /// The type of the business object + /// The IDataReader to use to fill the objects + /// The List to Fill + /// A flag that indicates whether the DataReader should be closed + /// A List of objects (TItem) + /// + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static IList FillListFromReader(Type objType, IDataReader dr, IList objList, bool closeReader) + { + object objObject; + bool isSuccess = Null.NullBoolean; + try + { + //iterate datareader + while (dr.Read()) + { + //Create the Object + objObject = CreateObjectFromReader(objType, dr, false); + //add to collection + objList.Add(objObject); + } + isSuccess = true; + } + finally + { + //Ensure DataReader is closed + if ((!isSuccess)) + { + closeReader = true; + } + CloseDataReader(dr, closeReader); + } + return objList; + } + + /// ----------------------------------------------------------------------------- + /// + /// FillListFromReader fills a list of objects of a specified type + /// from a DataReader + /// + /// The IDataReader to use to fill the objects + /// The List to Fill + /// A flag that indicates whether the DataReader should be closed + /// A List of objects (TItem) + /// + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static IList FillListFromReader(IDataReader dr, IList objList, bool closeReader) + { + TItem objObject; + bool isSuccess = Null.NullBoolean; + try + { + //iterate datareader + while (dr.Read()) + { + //Create the Object + objObject = (TItem) CreateObjectFromReader(typeof (TItem), dr, false); + //add to collection + objList.Add(objObject); + } + isSuccess = true; + } + finally + { + //Ensure DataReader is closed + if ((!isSuccess)) + { + closeReader = true; + } + CloseDataReader(dr, closeReader); + } + return objList; + } + + /// ----------------------------------------------------------------------------- + /// + /// FillObjectFromReader fills an object from the provided DataReader. If the object + /// implements the IHydratable interface it will use the object's IHydratable.Fill() method. + /// Otherwise, it will use reflection to fill the object. + /// + /// The object to fill + /// The DataReader + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static void FillObjectFromReader(object objObject, IDataReader dr) + { + try + { + //Determine if object is IHydratable + if (objObject is IHydratable) + { + //Use IHydratable's Fill + var objHydratable = objObject as IHydratable; + if (objHydratable != null) + { + objHydratable.Fill(dr); + } + } + else + { + //Use Reflection + HydrateObject(objObject, dr); + } + } + catch (IndexOutOfRangeException iex) + { + //Call to GetOrdinal is being made with a bad column name + if (Host.ThrowCBOExceptions) + { + throw new ObjectHydrationException("Error Reading DataReader", iex, objObject.GetType(), dr); + } + else + { + Exceptions.LogException(iex); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// HydrateObject uses reflection to hydrate an object. + /// + /// The object to Hydrate + /// The IDataReader that contains the columns of data for the object + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static void HydrateObject(object hydratedObject, IDataReader dr) + { + PropertyInfo objPropertyInfo = null; + Type propType = null; + object coloumnValue; + Type objDataType; + int intIndex; + //get cached object mapping for type + ObjectMappingInfo objMappingInfo = GetObjectMapping(hydratedObject.GetType()); + if (hydratedObject is BaseEntityInfo && !(hydratedObject is ScheduleItem)) + { + //Call the base classes fill method to populate base class properties + ((BaseEntityInfo) hydratedObject).FillBaseProperties(dr); + } + //fill object with values from datareader + for (intIndex = 0; intIndex <= dr.FieldCount - 1; intIndex++) + { + //If the Column matches a Property in the Object Map's PropertyInfo Dictionary + if (objMappingInfo.Properties.TryGetValue(dr.GetName(intIndex).ToUpperInvariant(), out objPropertyInfo)) + { + //Get its type + propType = objPropertyInfo.PropertyType; + //If property can be set + if (objPropertyInfo.CanWrite) + { + //Get the Data Value from the data reader + coloumnValue = dr.GetValue(intIndex); + //Get the Data Value's type + objDataType = coloumnValue.GetType(); + if (coloumnValue == null || coloumnValue == DBNull.Value) + { + //set property value to Null + objPropertyInfo.SetValue(hydratedObject, Null.SetNull(objPropertyInfo), null); + } + else if (propType.Equals(objDataType)) + { + //Property and data objects are the same type + objPropertyInfo.SetValue(hydratedObject, coloumnValue, null); + } + else + { + //business object info class member data type does not match datareader member data type + //need to handle enumeration conversions differently than other base types + if (propType.BaseType.Equals(typeof (Enum))) + { + //check if value is numeric and if not convert to integer ( supports databases like Oracle ) + if (Regex.IsMatch(coloumnValue.ToString(), "^\\d+$")) + { + objPropertyInfo.SetValue(hydratedObject, + Enum.ToObject(propType, Convert.ToInt32(coloumnValue)), + null); + } + else + { + objPropertyInfo.SetValue(hydratedObject, Enum.ToObject(propType, coloumnValue), null); + } + } + else if (propType == typeof (Guid)) + { + //guid is not a datatype common across all databases ( ie. Oracle ) + objPropertyInfo.SetValue(hydratedObject, + Convert.ChangeType(new Guid(coloumnValue.ToString()), propType), + null); + } + else if (propType == typeof (Version)) + { + objPropertyInfo.SetValue(hydratedObject, new Version(coloumnValue.ToString()), null); + } + else if (coloumnValue is IConvertible) + { + objPropertyInfo.SetValue(hydratedObject, Convert.ChangeType(coloumnValue, propType), + null); + } + else + { + // try explicit conversion + objPropertyInfo.SetValue(hydratedObject, coloumnValue, null); + } + } + } + } + } + } + + #endregion + + #region Object Mapping Helper Methods + + /// ----------------------------------------------------------------------------- + /// + /// GetColumnName gets the name of the Database Column that maps to the property. + /// + /// The proeprty of the business object + /// The name of the Database Column + /// + /// [cnurse] 12/02/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static string GetColumnName(PropertyInfo objProperty) + { + string columnName = objProperty.Name; + return columnName; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetObjectMapping gets an instance of the ObjectMappingInfo class for the type. + /// This is cached using a high priority as reflection is expensive. + /// + /// The type of the business object + /// An ObjectMappingInfo object representing the mapping for the object + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static ObjectMappingInfo GetObjectMapping(Type objType) + { + string cacheKey = objectMapCacheKey + objType.FullName; + var objMap = (ObjectMappingInfo) DataCache.GetCache(cacheKey); + if (objMap == null) + { + //Create an ObjectMappingInfo instance + objMap = new ObjectMappingInfo(); + objMap.ObjectType = objType.FullName; + //Reflect on class to create Object Map + objMap.PrimaryKey = GetPrimaryKey(objType); + objMap.TableName = GetTableName(objType); + //Iterate through the objects properties and add each one to the ObjectMappingInfo's Properties Dictionary + foreach (PropertyInfo objProperty in objType.GetProperties()) + { + objMap.Properties.Add(objProperty.Name.ToUpperInvariant(), objProperty); + objMap.ColumnNames.Add(objProperty.Name.ToUpperInvariant(), GetColumnName(objProperty)); + } + //Persist to Cache + DataCache.SetCache(cacheKey, objMap); + } + + //Return Object Map + return objMap; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetPrimaryKey gets the Primary Key property + /// + /// The type of the business object + /// The name of the Primary Key property + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static string GetPrimaryKey(Type objType) + { + string primaryKey = defaultPrimaryKey; + return primaryKey; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetTableName gets the name of the Database Table that maps to the object. + /// + /// The type of the business object + /// The name of the Database Table + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + private static string GetTableName(Type objType) + { + string tableName = string.Empty; + //If no attrubute then use Type Name + if (string.IsNullOrEmpty(tableName)) + { + tableName = objType.Name; + if (tableName.EndsWith("Info")) + { + //Remove Info ending + tableName.Replace("Info", string.Empty); + } + } + //Check if there is an object qualifier + if (!string.IsNullOrEmpty(Config.GetSetting("ObjectQualifier"))) + { + tableName = Config.GetSetting("ObjectQualifier") + tableName; + } + return tableName; + } + + #endregion + + #endregion + + #region Public Shared Methods + + #region Clone Object + + /// ----------------------------------------------------------------------------- + /// + /// CloneObject clones an object + /// + /// The Object to Clone + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static object CloneObject(object objObject) + { + try + { + Type objType = objObject.GetType(); + object objNewObject = Activator.CreateInstance(objType); + //get cached object mapping for type + ObjectMappingInfo objMappingInfo = GetObjectMapping(objType); + foreach (KeyValuePair kvp in objMappingInfo.Properties) + { + PropertyInfo objProperty = kvp.Value; + if (objProperty.CanWrite) + { + //Check if property is ICloneable + var objPropertyClone = objProperty.GetValue(objObject, null) as ICloneable; + if (objPropertyClone == null) + { + objProperty.SetValue(objNewObject, objProperty.GetValue(objObject, null), null); + } + else + { + objProperty.SetValue(objNewObject, objPropertyClone.Clone(), null); + } + //Check if Property is IEnumerable + var enumerable = objProperty.GetValue(objObject, null) as IEnumerable; + if (enumerable != null) + { + var list = objProperty.GetValue(objNewObject, null) as IList; + if (list != null) + { + foreach (object obj in enumerable) + { + list.Add(CloneObject(obj)); + } + } + var dic = objProperty.GetValue(objNewObject, null) as IDictionary; + if (dic != null) + { + foreach (DictionaryEntry de in enumerable) + { + dic.Add(de.Key, CloneObject(de.Value)); + } + } + } + } + } + return objNewObject; + } + catch (Exception exc) + { + Exceptions.LogException(exc); + return null; + } + } + + #endregion + + #region CloseDataReader + + public static void CloseDataReader(IDataReader dr, bool closeReader) + { + //close datareader + if (dr != null && closeReader) + { + dr.Close(); + } + } + + #endregion + + #region Create Object + + /// ----------------------------------------------------------------------------- + /// + /// CreateObject creates a new object of Type TObject. + /// + /// The type of object to create. + /// This overload does not initialise the object + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static TObject CreateObject() + { + return (TObject) CreateObject(typeof (TObject), false); + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateObject creates a new object of Type TObject. + /// + /// The type of object to create. + /// A flag that indicates whether to initialise the + /// object. + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static TObject CreateObject(bool initialise) + { + return (TObject) CreateObject(typeof (TObject), initialise); + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateObject creates a new object. + /// + /// The type of object to create. + /// A flag that indicates whether to initialise the + /// object. + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(Type objType, bool initialise) + { + object objObject = Activator.CreateInstance(objType); + + if (initialise) + { + InitializeObject(objObject); + } + return objObject; + } + + #endregion + + #region DeserializeObject + + public static TObject DeserializeObject(string fileName) + { + return DeserializeObject(XmlReader.Create(new FileStream(fileName, FileMode.Open, FileAccess.Read))); + } + + public static TObject DeserializeObject(XmlDocument document) + { + return DeserializeObject(XmlReader.Create(new StringReader(document.OuterXml))); + } + + public static TObject DeserializeObject(Stream stream) + { + return DeserializeObject(XmlReader.Create(stream)); + } + + public static TObject DeserializeObject(TextReader reader) + { + return DeserializeObject(XmlReader.Create(reader)); + } + + public static TObject DeserializeObject(XmlReader reader) + { + //First Create the Object + var objObject = CreateObject(true); + //Try to cast the Object as IXmlSerializable + var xmlSerializableObject = objObject as IXmlSerializable; + if (xmlSerializableObject == null) + { + //Use XmlSerializer + var serializer = new XmlSerializer(objObject.GetType()); + objObject = (TObject) serializer.Deserialize(reader); + } + else + { + //Use XmlReader + xmlSerializableObject.ReadXml(reader); + } + return objObject; + } + + #endregion + + #region FillCollection + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a Collection of objects from a DataReader + /// + /// The Data Reader + /// The type of the Object + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static ArrayList FillCollection(IDataReader dr, Type objType) + { + return (ArrayList) FillListFromReader(objType, dr, new ArrayList(), true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a Collection of objects from a DataReader + /// + /// The Data Reader + /// The type of the Object + /// Flag that indicates whether the Data Reader should be closed. + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static ArrayList FillCollection(IDataReader dr, Type objType, bool closeReader) + { + return (ArrayList) FillListFromReader(objType, dr, new ArrayList(), closeReader); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a Collection of objects from a DataReader + /// + /// The Data Reader + /// The type of the Object + /// An IList to fill + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static IList FillCollection(IDataReader dr, Type objType, ref IList objToFill) + { + return FillListFromReader(objType, dr, objToFill, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a Collection of objects from a DataReader + /// + /// The type of object + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static List FillCollection(IDataReader dr) + { + return (List) FillListFromReader(dr, new List(), true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a Collection of objects from a DataReader + /// + /// The type of object + /// The List to fill + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static IList FillCollection(IDataReader dr, ref IList objToFill) + { + return FillListFromReader(dr, objToFill, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillCollection fills a List of objects from a DataReader + /// + /// The type of the Object + /// The List to fill + /// The Data Reader + /// A flag that indicates whether the DataReader should be closed + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static IList FillCollection(IDataReader dr, IList objToFill, bool closeReader) + { + return FillListFromReader(dr, objToFill, closeReader); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generic version of FillCollection fills a List custom business object of a specified type + /// from the supplied DataReader + /// + /// The IDataReader to use to fill the object + /// The type of the Object + /// The total No of records + /// A List of custom business objects + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static ArrayList FillCollection(IDataReader dr, ref Type objType, ref int totalRecords) + { + var objFillCollection = (ArrayList) FillListFromReader(objType, dr, new ArrayList(), false); + try + { + if (dr.NextResult()) + { + //Get the total no of records from the second result + totalRecords = Globals.GetTotalRecords(ref dr); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //Ensure DataReader is closed + CloseDataReader(dr, true); + } + return objFillCollection; + } + + /// ----------------------------------------------------------------------------- + /// + /// Generic version of FillCollection fills a List custom business object of a specified type + /// from the supplied DataReader + /// + /// The type of the business object + /// The IDataReader to use to fill the object + /// + /// A List of custom business objects + /// + /// + /// [cnurse] 10/10/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static List FillCollection(IDataReader dr, ref int totalRecords) + { + IList objFillCollection = FillCollection(dr, new List(), false); + try + { + if (dr.NextResult()) + { + //Get the total no of records from the second result + totalRecords = Globals.GetTotalRecords(ref dr); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //Ensure DataReader is closed + CloseDataReader(dr, true); + } + return (List) objFillCollection; + } + + #endregion + + #region FillDictionary + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionary fills a Dictionary of objects from a DataReader + /// + /// The value for the Dictionary Item + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static IDictionary FillDictionary(IDataReader dr) where TItem : IHydratable + { + return FillDictionaryFromReader("KeyID", dr, new Dictionary(), true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionary fills a Dictionary of objects from a DataReader + /// + /// The value for the Dictionary Item + /// The Dictionary to fill + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static IDictionary FillDictionary(IDataReader dr, + ref IDictionary objToFill) + where TItem : IHydratable + { + return FillDictionaryFromReader("KeyID", dr, objToFill, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionary fills a Dictionary of objects from a DataReader + /// + /// The key for the Dictionary + /// The value for the Dictionary Item + /// The key field used for the Key + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary FillDictionary(string keyField, IDataReader dr) + { + return + (Dictionary) FillDictionaryFromReader(keyField, dr, new Dictionary(), true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionary fills a Dictionary of objects from a DataReader + /// + /// The key for the Dictionary + /// The value for the Dictionary Item + /// The key field used for the Key + /// The Data Reader + /// if true, closes reader. If false, rdr left open + /// + /// [bchapman] 10/29/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary FillDictionary(string keyField, IDataReader dr, + bool closeReader) + { + return + (Dictionary) + FillDictionaryFromReader(keyField, dr, new Dictionary(), closeReader); + } + + + /// ----------------------------------------------------------------------------- + /// + /// FillDictionary fills a Dictionary of objects from a DataReader + /// + /// The key for the Dictionary + /// The value for the Dictionary Item + /// The key field used for the Key + /// The Dictionary to fill + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary FillDictionary(string keyField, IDataReader dr, + IDictionary objDictionary) + { + return (Dictionary) FillDictionaryFromReader(keyField, dr, objDictionary, true); + } + + #endregion + + #region FillObject + + /// ----------------------------------------------------------------------------- + /// + /// FillObject fills an object from a DataReader + /// + /// The type of the object + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static TObject FillObject(IDataReader dr) + { + return (TObject) CreateObjectFromReader(typeof (TObject), dr, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillObject fills an object from a DataReader + /// + /// The type of the object + /// The Data Reader + /// A flag that indicates the reader should be closed + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static TObject FillObject(IDataReader dr, bool closeReader) + { + return (TObject) CreateObjectFromReader(typeof (TObject), dr, closeReader); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillObject fills an object from a DataReader + /// + /// The Data Reader + /// The type of the object + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static object FillObject(IDataReader dr, Type objType) + { + return CreateObjectFromReader(objType, dr, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillObject fills an object from a DataReader + /// + /// The Data Reader + /// The type of the object + /// A flag that indicates the reader should be closed + /// + /// [cnurse] 11/29/2007 Documented + /// + /// ----------------------------------------------------------------------------- + public static object FillObject(IDataReader dr, Type objType, bool closeReader) + { + return CreateObjectFromReader(objType, dr, closeReader); + } + + #endregion + + public static IQueryable FillQueryable(IDataReader dr) + { + return FillListFromReader(dr, new List(), true).AsQueryable(); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillSortedList fills a SortedList of objects from a DataReader + /// + /// The key for the SortedList + /// The value for the SortedList Item + /// The key field used for the Key + /// The Data Reader + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static SortedList FillSortedList(string keyField, IDataReader dr) + { + return + (SortedList) FillDictionaryFromReader(keyField, dr, new SortedList(), true); + } + + public static void DeserializeSettings(IDictionary dictionary, XmlNode rootNode, string elementName) + { + string sKey = null; + string sValue = null; + + foreach (XmlNode settingNode in rootNode.SelectNodes(elementName)) + { + sKey = XmlUtils.GetNodeValue(settingNode.CreateNavigator(), "settingname"); + sValue = XmlUtils.GetNodeValue(settingNode.CreateNavigator(), "settingvalue"); + + dictionary[sKey] = sValue; + } + } + + /// + /// Iterates items in a IDictionary object and generates XML nodes + /// + ///The IDictionary to iterate + ///The XML document the node should be added to + ///Path at which to serialize settings + ///The name of the new element created + /// + /// + /// + /// [jlucarino] 09/18/2009 created + /// [kbeigi] updated to IDictionary + /// + public static void SerializeSettings(IDictionary dictionary, XmlDocument document, string targetPath, + string elementName) + { + string sOuterElementName = elementName + "s"; + string sInnerElementName = elementName; + XmlNode nodeSetting = default(XmlNode); + XmlNode nodeSettings = default(XmlNode); + XmlNode nodeSettingName = default(XmlNode); + XmlNode nodeSettingValue = default(XmlNode); + + XmlNode targetNode = document.SelectSingleNode(targetPath); + + if (targetNode != null) + { + nodeSettings = targetNode.AppendChild(document.CreateElement(sOuterElementName)); + foreach (object sKey in dictionary.Keys) + { + nodeSetting = nodeSettings.AppendChild(document.CreateElement(sInnerElementName)); + + nodeSettingName = nodeSetting.AppendChild(document.CreateElement("settingname")); + nodeSettingName.InnerText = sKey.ToString(); + + nodeSettingValue = nodeSetting.AppendChild(document.CreateElement("settingvalue")); + nodeSettingValue.InnerText = dictionary[sKey].ToString(); + } + } + else + { + throw new ArgumentException("Invalid Target Path"); + } + } + + #region "GetCachedObject" + + /// ----------------------------------------------------------------------------- + /// + /// GetCachedObject gets an object from the Cache + /// + /// The type of th object to fetch + /// A CacheItemArgs object that provides parameters to manage the + /// cache AND to fetch the item if the cache has expired + /// A CacheItemExpiredCallback delegate that is used to repopulate + /// the cache if the item has expired + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static TObject GetCachedObject(CacheItemArgs cacheItemArgs, + CacheItemExpiredCallback cacheItemExpired) + { + return DataCache.GetCachedData(cacheItemArgs, cacheItemExpired); + } + + public static TObject GetCachedObject(CacheItemArgs cacheItemArgs, + CacheItemExpiredCallback cacheItemExpired, bool saveInDictionary) + { + return DataCache.GetCachedData(cacheItemArgs, cacheItemExpired, saveInDictionary); + } + + #endregion + + #region "GetProperties" + + /// ----------------------------------------------------------------------------- + /// + /// GetProperties gets a Dictionary of the Properties for an object + /// + /// The type of the object + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetProperties() + { + return GetObjectMapping(typeof (TObject)).Properties; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetProperties gets a Dictionary of the Properties for an object + /// + /// The type of the object + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetProperties(Type objType) + { + return GetObjectMapping(objType).Properties; + } + + #endregion + + #region "InitializeObject" + + /// ----------------------------------------------------------------------------- + /// + /// InitializeObject initialises all the properties of an object to their + /// Null Values. + /// + /// The object to Initialise + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void InitializeObject(object objObject) + { + //initialize properties + foreach (PropertyInfo objPropertyInfo in GetObjectMapping(objObject.GetType()).Properties.Values) + { + if (objPropertyInfo.CanWrite) + { + objPropertyInfo.SetValue(objObject, Null.SetNull(objPropertyInfo), null); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// InitializeObject initialises all the properties of an object to their + /// Null Values. + /// + /// The object to Initialise + /// The type of the object + /// + /// [cnurse] 11/29/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static object InitializeObject(object objObject, Type objType) + { + //initialize properties + foreach (PropertyInfo objPropertyInfo in GetObjectMapping(objType).Properties.Values) + { + if (objPropertyInfo.CanWrite) + { + objPropertyInfo.SetValue(objObject, Null.SetNull(objPropertyInfo), null); + } + } + return objObject; + } + + #endregion + + #region "SerializeObject" + + /// ----------------------------------------------------------------------------- + /// + /// SerializeObject serializes an Object + /// + /// The object to Initialise + /// A filename for the resulting serialized xml + /// + /// [cnurse] 01/17/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeObject(object objObject, string fileName) + { + using ( + XmlWriter writer = XmlWriter.Create(fileName, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment))) + { + SerializeObject(objObject, writer); + writer.Flush(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeObject serializes an Object + /// + /// The object to Initialise + /// An XmlDocument to serialize to + /// + /// [cnurse] 01/17/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeObject(object objObject, XmlDocument document) + { + var sb = new StringBuilder(); + //Serialize the object + SerializeObject(objObject, XmlWriter.Create(sb, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Document))); + //Load XmlDocument + document.LoadXml(sb.ToString()); + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeObject serializes an Object + /// + /// The object to Initialise + /// A Stream to serialize to + /// + /// [cnurse] 01/17/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeObject(object objObject, Stream stream) + { + using (XmlWriter writer = XmlWriter.Create(stream, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)) + ) + { + SerializeObject(objObject, writer); + writer.Flush(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeObject serializes an Object + /// + /// The object to Initialise + /// A TextWriter to serialize to + /// + /// [cnurse] 01/17/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeObject(object objObject, TextWriter textWriter) + { + using ( + XmlWriter writer = XmlWriter.Create(textWriter, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)) + ) + { + SerializeObject(objObject, writer); + writer.Flush(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// SerializeObject serializes an Object + /// + /// The object to Initialise + /// An XmlWriter to serialize to + /// + /// [cnurse] 01/17/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeObject(object objObject, XmlWriter writer) + { + //Try to cast the Object as IXmlSerializable + var xmlSerializableObject = objObject as IXmlSerializable; + if (xmlSerializableObject == null) + { + //Use XmlSerializer + var serializer = new XmlSerializer(objObject.GetType()); + serializer.Serialize(writer, objObject); + } + else + { + //Use XmlWriter + xmlSerializableObject.WriteXml(writer); + } + } + + #endregion + + #endregion + + #region Obsolete + + [Obsolete("Obsolete in DotNetNuke 5.0. Replaced by GetProperties(Of TObject)() ")] + public static ArrayList GetPropertyInfo(Type objType) + { + var arrProperties = new ArrayList(); + + //get cached object mapping for type + ObjectMappingInfo objMappingInfo = GetObjectMapping(objType); + + arrProperties.AddRange(objMappingInfo.Properties.Values); + + return arrProperties; + } + + [Obsolete("Obsolete in DotNetNuke 5.0. Replaced by SerializeObject(Object) ")] + public static XmlDocument Serialize(object objObject) + { + var document = new XmlDocument(); + SerializeObject(objObject, document); + return document; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Common/Utilities/CacheItemArgs.cs b/DNN Platform/Library/Common/Utilities/CacheItemArgs.cs new file mode 100644 index 00000000000..4fe3bd46a2c --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/CacheItemArgs.cs @@ -0,0 +1,222 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.Web.Caching; + +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Common.Utilities + /// Class: CacheItemArgs + /// ----------------------------------------------------------------------------- + /// + /// The CacheItemArgs class provides an EventArgs implementation for the + /// CacheItemExpiredCallback delegate + /// + /// + /// [cnurse] 01/12/2008 created + /// + /// ----------------------------------------------------------------------------- + public class CacheItemArgs + { + private ArrayList _paramList; + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new CacheItemArgs Object + /// + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemArgs(string key) + : this(key, 20, CacheItemPriority.Default, null) + { + } + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new CacheItemArgs Object + /// + /// + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemArgs(string key, int timeout) + : this(key, timeout, CacheItemPriority.Default, null) + { + } + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new CacheItemArgs Object + /// + /// + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemArgs(string key, CacheItemPriority priority) + : this(key, 20, priority, null) + { + } + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new CacheItemArgs Object + /// + /// + /// + /// + /// + /// [cnurse] 07/15/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemArgs(string key, int timeout, CacheItemPriority priority) + : this(key, timeout, priority, null) + { + } + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new CacheItemArgs Object + /// + /// + /// + /// + /// + /// + /// [cnurse] 07/14/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemArgs(string key, int timeout, CacheItemPriority priority, params object[] parameters) + { + CacheKey = key; + CacheTimeOut = timeout; + CachePriority = priority; + Params = parameters; + } + + ///----------------------------------------------------------------------------- + /// + /// Gets and sets the Cache Item's CacheItemRemovedCallback delegate + /// + /// + /// [cnurse] 01/13/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemRemovedCallback CacheCallback { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets and sets the Cache Item's CacheDependency + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public DNNCacheDependency CacheDependency { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Cache Item's Key + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public string CacheKey { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Cache Item's priority (defaults to Default) + /// + /// Note: DotNetNuke currently doesn't support the ASP.NET Cache's + /// ItemPriority, but this is included for possible future use. + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public CacheItemPriority CachePriority { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Cache Item's Timeout + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public int CacheTimeOut { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Cache Item's Parameter List + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public ArrayList ParamList + { + get + { + if (_paramList == null) + { + _paramList = new ArrayList(); + //add additional params to this list if its not null + if (Params != null) + { + foreach (object param in Params) + { + _paramList.Add(param); + } + } + } + + return _paramList; + } + } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Cache Item's Parameter Array + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public object[] Params { get; private set; } + + public string ProcedureName { get; set; } + } +} diff --git a/DNN Platform/Library/Common/Utilities/CacheItemExpiredCallback.cs b/DNN Platform/Library/Common/Utilities/CacheItemExpiredCallback.cs new file mode 100644 index 00000000000..c77f86f1a51 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/CacheItemExpiredCallback.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Common.Utilities + /// Class: CacheItemExpiredCallback + /// ----------------------------------------------------------------------------- + /// + /// The CacheItemExpiredCallback delegate defines a callback method that notifies + /// the application when a CacheItem is Expired (when an attempt is made to get the item) + /// + /// + /// [cnurse] 01/12/2008 created + /// + /// ----------------------------------------------------------------------------- + public delegate object CacheItemExpiredCallback(CacheItemArgs dataArgs); +} diff --git a/DNN Platform/Library/Common/Utilities/Calendar.cs b/DNN Platform/Library/Common/Utilities/Calendar.cs new file mode 100644 index 00000000000..5c8bd3a0a59 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/Calendar.cs @@ -0,0 +1,84 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Globalization; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Utilities; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class Calendar + { + /// ----------------------------------------------------------------------------- + /// + /// Opens a popup Calendar + /// + /// TextBox to return the date value + /// + /// + /// + /// + /// [VMasanas] 12/09/2004 Added localized parameter strings: today, close, calendar + /// Use AbbreviatedDayName property instead of first 3 chars of day name + /// [VMasanas] 14/10/2004 Added support for First Day Of Week + /// [VMasanas] 14/11/2004 Register client script to work with FriendlyURLs + /// + /// ----------------------------------------------------------------------------- + public static string InvokePopupCal(TextBox Field) + { + //Define character array to trim from language strings + char[] TrimChars = {',', ' '}; + //Get culture array of month names and convert to string for + //passing to the popup calendar + string MonthNameString = ""; + foreach (string Month in DateTimeFormatInfo.CurrentInfo.MonthNames) + { + MonthNameString += Month + ","; + } + MonthNameString = MonthNameString.TrimEnd(TrimChars); + //Get culture array of day names and convert to string for + //passing to the popup calendar + string DayNameString = ""; + foreach (string Day in DateTimeFormatInfo.CurrentInfo.AbbreviatedDayNames) + { + DayNameString += Day + ","; + } + DayNameString = DayNameString.TrimEnd(TrimChars); + //Get the short date pattern for the culture + string FormatString = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; + if (!Field.Page.ClientScript.IsClientScriptIncludeRegistered("PopupCalendar.js")) + { + ScriptManager.RegisterClientScriptInclude(Field.Page, Field.Page.GetType(), "PopupCalendar.js", ClientAPI.ScriptPath + "PopupCalendar.js"); + } + string strToday = ClientAPI.GetSafeJSString(Localization.GetString("Today")); + string strClose = ClientAPI.GetSafeJSString(Localization.GetString("Close")); + string strCalendar = ClientAPI.GetSafeJSString(Localization.GetString("Calendar")); + return "javascript:popupCal('Cal','" + Field.ClientID + "','" + FormatString + "','" + MonthNameString + "','" + DayNameString + "','" + strToday + "','" + strClose + "','" + strCalendar + + "'," + (int) DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek + ");"; + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/Config.cs b/DNN Platform/Library/Common/Utilities/Config.cs new file mode 100644 index 00000000000..dec92ed5905 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/Config.cs @@ -0,0 +1,810 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; +using System.IO; +using System.Web.Configuration; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Application; +using DotNetNuke.Framework.Providers; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; +using DotNetNuke.Services.Exceptions; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// + /// The Config class provides access to the web.config file + /// + /// + /// + /// + /// [cnurse] 11/15/2005 documented + /// + /// ----------------------------------------------------------------------------- + public class Config + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(Config)); + #region ConfigFileType enum + + public enum ConfigFileType + { + DotNetNuke, + //compatible with glbDotNetNukeConfig + SiteAnalytics, + Compression, + SiteUrls, + SolutionsExplorer + } + + #endregion + + /// + /// Adds a new AppSetting to Web.Config. The update parameter allows you to define if, + /// when the key already exists, this need to be updated or not + /// + /// xml representation of the web.config file + /// key to be created + /// value to be created + /// If setting already exists, it will be updated if this parameter true + /// + public static XmlDocument AddAppSetting(XmlDocument xmlDoc, string key, string value, bool update) + { + XmlElement xmlElement; + //retrieve the appSettings node + XmlNode xmlAppSettings = xmlDoc.SelectSingleNode("//appSettings"); + if (xmlAppSettings != null) + { + //get the node based on key + XmlNode xmlNode = xmlAppSettings.SelectSingleNode(("//add[@key='" + key + "']")); + if (update && xmlNode != null) + { + //update the existing element + xmlElement = (XmlElement)xmlNode; + xmlElement.SetAttribute("value", value); + } + else + { + //create a new element + xmlElement = xmlDoc.CreateElement("add"); + xmlElement.SetAttribute("key", key); + xmlElement.SetAttribute("value", value); + xmlAppSettings.AppendChild(xmlElement); + } + } + //return the xml doc + return xmlDoc; + } + + /// + /// Adds a new AppSetting to Web.Config. If the key already exists, it will be updated with the new value + /// + /// xml representation of the web.config file + /// key to be created + /// value to be created + /// + public static XmlDocument AddAppSetting(XmlDocument xmlDoc, string key, string value) + { + return AddAppSetting(xmlDoc, key, value, true); + } + + public static void AddCodeSubDirectory(string name) + { + XmlDocument xmlConfig = Load(); + XmlNode xmlCompilation = xmlConfig.SelectSingleNode("configuration/system.web/compilation"); + if (xmlCompilation == null) + { + //Try location node + xmlCompilation = xmlConfig.SelectSingleNode("configuration/location/system.web/compilation"); + } + //Get the CodeSubDirectories Node + if (xmlCompilation != null) + { + XmlNode xmlSubDirectories = xmlCompilation.SelectSingleNode("codeSubDirectories"); + if (xmlSubDirectories == null) + { + //Add Node + xmlSubDirectories = xmlConfig.CreateElement("codeSubDirectories"); + xmlCompilation.AppendChild(xmlSubDirectories); + } + + var length = name.IndexOf("/", StringComparison.Ordinal); + var codeSubDirectoryName = name; + if (length > 0) + { + codeSubDirectoryName = name.Substring(0, length); + } + + //Check if the node is already present + XmlNode xmlSubDirectory = xmlSubDirectories.SelectSingleNode("add[@directoryName='" + codeSubDirectoryName + "']"); + if (xmlSubDirectory == null) + { + //Add Node + xmlSubDirectory = xmlConfig.CreateElement("add"); + XmlUtils.CreateAttribute(xmlConfig, xmlSubDirectory, "directoryName", codeSubDirectoryName); + xmlSubDirectories.AppendChild(xmlSubDirectory); + } + } + Save(xmlConfig); + } + + public static void BackupConfig() + { + string backupFolder = Globals.glbConfigFolder + "Backup_" + DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + "\\"; + //save the current config files + try + { + if (!Directory.Exists(Globals.ApplicationMapPath + backupFolder)) + { + Directory.CreateDirectory(Globals.ApplicationMapPath + backupFolder); + } + if (File.Exists(Globals.ApplicationMapPath + "\\web.config")) + { + File.Copy(Globals.ApplicationMapPath + "\\web.config", Globals.ApplicationMapPath + backupFolder + "web_old.config", true); + } + } + catch (Exception e) + { + Exceptions.LogException(e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the default connection String as specified in the provider. + /// + /// The connection String + /// + /// + /// [cnurse] 11/15/2005 created + /// + /// ----------------------------------------------------------------------------- + public static string GetConnectionString() + { + return GetConnectionString(GetDefaultProvider("data").Attributes["connectionStringName"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the specified connection String + /// + /// Name of Connection String to return + /// The connection String + /// + /// + /// [cnurse] 11/15/2005 created + /// + /// ----------------------------------------------------------------------------- + public static string GetConnectionString(string name) + { + string connectionString = ""; + //First check if connection string is specified in (ASP.NET 2.0 / DNN v4.x) + if (!String.IsNullOrEmpty(name)) + { + //ASP.NET 2 version connection string (in ) + //This will be for new v4.x installs or upgrades from v4.x + connectionString = WebConfigurationManager.ConnectionStrings[name].ConnectionString; + } + if (String.IsNullOrEmpty(connectionString)) + { + if (!String.IsNullOrEmpty(name)) + { + //Next check if connection string is specified in (ASP.NET 1.1 / DNN v3.x) + //This will accomodate upgrades from v3.x + connectionString = GetSetting(name); + } + } + return connectionString; + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns the decryptionkey from webconfig machinekey + /// + /// decryption key + /// ----------------------------------------------------------------------------- + public static string GetDecryptionkey() + { + var configNav = Load(); + var httpNode = configNav.SelectSingleNode("configuration//system.web//machineKey").CreateNavigator(); + + var result = XmlUtils.GetAttributeValue(httpNode, "decryptionKey"); + + return result; + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns the maximum file size allowed to be uploaded to the application in bytes + /// + /// Size in bytes + /// ----------------------------------------------------------------------------- + public static long GetMaxUploadSize() + { + var configNav = Load(); + + var httpNode = configNav.SelectSingleNode("configuration//system.web//httpRuntime") ?? + configNav.SelectSingleNode("configuration//location//system.web//httpRuntime"); + long maxRequestLength = 0; + if (httpNode != null) + { + maxRequestLength = XmlUtils.GetAttributeValueAsLong(httpNode.CreateNavigator(), "maxRequestLength", 0) * 1024; + } + + httpNode = configNav.SelectSingleNode("configuration//system.webServer//security//requestFiltering//requestLimits") ?? + configNav.SelectSingleNode("configuration//location//system.webServer//security//requestFiltering//requestLimits"); + if (httpNode != null) + { + var maxAllowedContentLength = XmlUtils.GetAttributeValueAsLong(httpNode.CreateNavigator(), "maxAllowedContentLength", 0); + return Math.Min(maxRequestLength, maxAllowedContentLength); + } + + return maxRequestLength; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the specified upgrade connection string + /// + /// The connection String + /// + /// + /// [smehaffie] 07/13/2008 created + /// + /// ----------------------------------------------------------------------------- + public static string GetUpgradeConnectionString() + { + return GetDefaultProvider("data").Attributes["upgradeConnectionString"]; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the specified database owner + /// + /// The database owner + /// + /// + /// [cnurse] 02/13/2007 created + /// + /// ----------------------------------------------------------------------------- + public static string GetDataBaseOwner() + { + string databaseOwner = GetDefaultProvider("data").Attributes["databaseOwner"]; + if (!String.IsNullOrEmpty(databaseOwner) && databaseOwner.EndsWith(".") == false) + { + databaseOwner += "."; + } + return databaseOwner; + } + + public static Provider GetDefaultProvider(string type) + { + ProviderConfiguration providerConfiguration = ProviderConfiguration.GetProviderConfiguration(type); + //Read the configuration specific information for this provider + return (Provider)providerConfiguration.Providers[providerConfiguration.DefaultProvider]; + } + + public static string GetFriendlyUrlProvider() + { + string providerToUse; + ProviderConfiguration fupConfig = ProviderConfiguration.GetProviderConfiguration("friendlyUrl"); + if (fupConfig != null) + { + string defaultFriendlyUrlProvider = fupConfig.DefaultProvider; + var provider = (Provider)fupConfig.Providers[defaultFriendlyUrlProvider]; + string urlFormat = provider.Attributes["urlFormat"]; + if (string.IsNullOrEmpty(urlFormat) == false) + { + switch (urlFormat.ToLower()) + { + case "advanced": + case "customonly": + providerToUse = "advanced"; + break; + default: + providerToUse = "standard"; + break; + } + } + else + { + providerToUse = "standard"; + } + } + else + { + providerToUse = "standard"; + } + + return providerToUse; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the specified object qualifier + /// + /// The object qualifier + /// + /// + /// [cnurse] 02/13/2007 created + /// + /// ----------------------------------------------------------------------------- + public static string GetObjectQualifer() + { + Provider provider = GetDefaultProvider("data"); + string objectQualifier = provider.Attributes["objectQualifier"]; + if (!String.IsNullOrEmpty(objectQualifier) && objectQualifier.EndsWith("_") == false) + { + objectQualifier += "_"; + } + return objectQualifier; + } + + public static int GetAuthCookieTimeout() + { + XPathNavigator configNav = Load().CreateNavigator(); + //Select the location node + XPathNavigator locationNav = configNav.SelectSingleNode("configuration/location"); + XPathNavigator formsNav; + //Test for the existence of the location node if it exists then include that in the nodes of the XPath Query + if (locationNav == null) + { + formsNav = configNav.SelectSingleNode("configuration/system.web/authentication/forms"); + } + else + { + formsNav = configNav.SelectSingleNode("configuration/location/system.web/authentication/forms"); + } + return (formsNav != null) ? XmlUtils.GetAttributeValueAsInteger(formsNav, "timeout", 30) : 30; ; + + } + + /// + /// Get's optional persistent cookie timeout value from web.config + /// + /// persistent cookie value + /// + /// allows users to override default asp.net values + /// + public static int GetPersistentCookieTimeout() + { + int persistentCookieTimeout = 0; + if (!String.IsNullOrEmpty(GetSetting("PersistentCookieTimeout"))) + { + persistentCookieTimeout = int.Parse(GetSetting("PersistentCookieTimeout")); + } + + return (persistentCookieTimeout == 0) ? GetAuthCookieTimeout() : persistentCookieTimeout; + } + + public static Provider GetProvider(string type, string name) + { + ProviderConfiguration providerConfiguration = ProviderConfiguration.GetProviderConfiguration(type); + //Read the configuration specific information for this provider + return (Provider)providerConfiguration.Providers[name]; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the specified provider path + /// + /// The provider path + /// + /// + /// [cnurse] 02/13/2007 created + /// + /// ----------------------------------------------------------------------------- + public static string GetProviderPath(string type) + { + Provider objProvider = GetDefaultProvider(type); + string providerPath = objProvider.Attributes["providerPath"]; + return providerPath; + } + + public static string GetSetting(string setting) + { + return WebConfigurationManager.AppSettings[setting]; + } + + public static object GetSection(string section) + { + return WebConfigurationManager.GetWebApplicationSection(section); + } + + public static XmlDocument Load() + { + return Load("web.config"); + } + + public static string GetCustomErrorMode() + { + + XPathNavigator configNav = Load().CreateNavigator(); + //Select the location node + XPathNavigator locationNav = configNav.SelectSingleNode("configuration/location"); + XPathNavigator customErrorsNav; + //Test for the existence of the location node if it exists then include that in the nodes of the XPath Query + if (locationNav == null) + { + customErrorsNav = configNav.SelectSingleNode("configuration/system.web/customErrors"); + } + else + { + customErrorsNav = configNav.SelectSingleNode("configuration/location/system.web/customErrors"); + } + + string customErrorMode = XmlUtils.GetAttributeValue(customErrorsNav, "mode"); + if (string.IsNullOrEmpty(customErrorMode)) + { + customErrorMode = "RemoteOnly"; + } + return (customErrorsNav != null) ? customErrorMode : "RemoteOnly"; ; + + } + + public static XmlDocument Load(string filename) + { + //open the config file + var xmlDoc = new XmlDocument(); + xmlDoc.Load(Globals.ApplicationMapPath + "\\" + filename); + //test for namespace added by Web Admin Tool + if (!String.IsNullOrEmpty(xmlDoc.DocumentElement.GetAttribute("xmlns"))) + { + //remove namespace + string strDoc = xmlDoc.InnerXml.Replace("xmlns=\"http://schemas.microsoft.com/.NetConfiguration/v2.0\"", ""); + xmlDoc.LoadXml(strDoc); + } + return xmlDoc; + } + + public static void RemoveCodeSubDirectory(string name) + { + XmlDocument xmlConfig = Load(); + //Select the location node + XmlNode xmlCompilation = xmlConfig.SelectSingleNode("configuration/system.web/compilation"); + if (xmlCompilation == null) + { + //Try location node + xmlCompilation = xmlConfig.SelectSingleNode("configuration/location/system.web/compilation"); + } + //Get the CodeSubDirectories Node + XmlNode xmlSubDirectories = xmlCompilation.SelectSingleNode("codeSubDirectories"); + if (xmlSubDirectories == null) + { + //Parent doesn't exist so subDirectory node can't exist + return; + } + + var length = name.IndexOf("/", StringComparison.Ordinal); + var codeSubDirectoryName = name; + if (length > 0) + { + codeSubDirectoryName = name.Substring(0, length); + } + + //Check if the node is present + XmlNode xmlSubDirectory = xmlSubDirectories.SelectSingleNode("add[@directoryName='" + codeSubDirectoryName + "']"); + if (xmlSubDirectory != null) + { + //Remove Node + xmlSubDirectories.RemoveChild(xmlSubDirectory); + + Save(xmlConfig); + } + } + + public static string Save(XmlDocument xmlDoc) + { + return Save(xmlDoc, "web.config"); + } + + public static string Save(XmlDocument xmlDoc, string filename) + { + try + { + string strFilePath = Globals.ApplicationMapPath + "\\" + filename; + FileAttributes objFileAttributes = FileAttributes.Normal; + if (File.Exists(strFilePath)) + { + //save current file attributes + objFileAttributes = File.GetAttributes(strFilePath); + //change to normal ( in case it is flagged as read-only ) + File.SetAttributes(strFilePath, FileAttributes.Normal); + } + //save the config file + var writer = new XmlTextWriter(strFilePath, null) { Formatting = Formatting.Indented }; + xmlDoc.WriteTo(writer); + writer.Flush(); + writer.Close(); + //reset file attributes + File.SetAttributes(strFilePath, objFileAttributes); + return ""; + } + catch (Exception exc) + { + //the file permissions may not be set properly + Logger.Error(exc); + return exc.Message; + } + } + + public static bool Touch() + { + try + { + File.SetLastWriteTime(Globals.ApplicationMapPath + "\\web.config", DateTime.Now); + return true; + } + catch (Exception exc) + { + Logger.Error(exc); + return false; + } + } + + public static void UpdateConnectionString(string conn) + { + XmlDocument xmlConfig = Load(); + string name = GetDefaultProvider("data").Attributes["connectionStringName"]; + + //Update ConnectionStrings + XmlNode xmlConnection = xmlConfig.SelectSingleNode("configuration/connectionStrings/add[@name='" + name + "']"); + XmlUtils.UpdateAttribute(xmlConnection, "connectionString", conn); + + //Update AppSetting + XmlNode xmlAppSetting = xmlConfig.SelectSingleNode("configuration/appSettings/add[@key='" + name + "']"); + XmlUtils.UpdateAttribute(xmlAppSetting, "value", conn); + + //Save changes + Save(xmlConfig); + } + + public static void UpdateDataProvider(string name, string databaseOwner, string objectQualifier) + { + XmlDocument xmlConfig = Load(); + + //Update provider + XmlNode xmlProvider = xmlConfig.SelectSingleNode("configuration/dotnetnuke/data/providers/add[@name='" + name + "']"); + XmlUtils.UpdateAttribute(xmlProvider, "databaseOwner", databaseOwner); + XmlUtils.UpdateAttribute(xmlProvider, "objectQualifier", objectQualifier); + + //Save changes + Save(xmlConfig); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates the specified upgrade connection string + /// + /// + /// ----------------------------------------------------------------------------- + public static void UpdateUpgradeConnectionString(string name, string upgradeConnectionString) + { + XmlDocument xmlConfig = Load(); + + //Update provider + XmlNode xmlProvider = xmlConfig.SelectSingleNode("configuration/dotnetnuke/data/providers/add[@name='" + name + "']"); + XmlUtils.UpdateAttribute(xmlProvider, "upgradeConnectionString", upgradeConnectionString); + + //Save changes + Save(xmlConfig); + } + + public static string UpdateMachineKey() + { + string backupFolder = Globals.glbConfigFolder + "Backup_" + DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + "\\"; + var xmlConfig = new XmlDocument(); + string strError = ""; + + //save the current config files + BackupConfig(); + try + { + //open the web.config + xmlConfig = Load(); + + //create random keys for the Membership machine keys + xmlConfig = UpdateMachineKey(xmlConfig); + + } + catch (Exception ex) + { + Logger.Error(ex); + strError += ex.Message; + } + + //save a copy of the web.config + strError += Save(xmlConfig, backupFolder + "web_.config"); + + //save the web.config + strError += Save(xmlConfig); + + return strError; + } + + public static XmlDocument UpdateMachineKey(XmlDocument xmlConfig) + { + var portalSecurity = new PortalSecurity(); + string validationKey = portalSecurity.CreateKey(20); + string decryptionKey = portalSecurity.CreateKey(24); + + XmlNode xmlMachineKey = xmlConfig.SelectSingleNode("configuration/system.web/machineKey"); + XmlUtils.UpdateAttribute(xmlMachineKey, "validationKey", validationKey); + XmlUtils.UpdateAttribute(xmlMachineKey, "decryptionKey", decryptionKey); + + xmlConfig = AddAppSetting(xmlConfig, "InstallationDate", DateTime.Today.ToString("d", new CultureInfo("en-US"))); + + return xmlConfig; + } + + public static string UpdateValidationKey() + { + string backupFolder = Globals.glbConfigFolder + "Backup_" + DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + "\\"; + var xmlConfig = new XmlDocument(); + string strError = ""; + + //save the current config files + BackupConfig(); + try + { + //open the web.config + xmlConfig = Load(); + + //create random keys for the Membership machine keys + xmlConfig = UpdateValidationKey(xmlConfig); + } + catch (Exception ex) + { + Logger.Error(ex); + strError += ex.Message; + } + + //save a copy of the web.config + strError += Save(xmlConfig, backupFolder + "web_.config"); + + //save the web.config + strError += Save(xmlConfig); + return strError; + } + + public static XmlDocument UpdateValidationKey(XmlDocument xmlConfig) + { + XmlNode xmlMachineKey = xmlConfig.SelectSingleNode("configuration/system.web/machineKey"); + if (xmlMachineKey.Attributes["validationKey"].Value == "F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902") + { + var objSecurity = new PortalSecurity(); + string validationKey = objSecurity.CreateKey(20); + XmlUtils.UpdateAttribute(xmlMachineKey, "validationKey", validationKey); + } + return xmlConfig; + } + + /// + /// Gets the path for the specificed Config file + /// + /// The config.file to get the path for + /// fully qualified path to the file + /// + /// Will copy the file from the template directory as requried + /// + public static string GetPathToFile(ConfigFileType file) + { + return GetPathToFile(file, false); + } + + /// + /// Gets the path for the specificed Config file + /// + /// The config.file to get the path for + /// force an overwrite of the config file + /// fully qualified path to the file + /// + /// Will copy the file from the template directory as requried + /// + public static string GetPathToFile(ConfigFileType file, bool overwrite) + { + string fileName = EnumToFileName(file); + string path = Path.Combine(Globals.ApplicationMapPath, fileName); + + if (!File.Exists(path) || overwrite) + { + //Copy from \Config + string pathToDefault = Path.Combine(Globals.ApplicationMapPath + Globals.glbConfigFolder, fileName); + if ((File.Exists(pathToDefault))) + { + File.Copy(pathToDefault, path, true); + } + } + + return path; + } + + private static string EnumToFileName(ConfigFileType file) + { + switch (file) + { + case ConfigFileType.SolutionsExplorer: + return "SolutionsExplorer.opml.config"; + default: + return file + ".config"; + } + } + + /// + /// UpdateInstallVersion, but only if the setting does not already exist + /// + /// + public static string UpdateInstallVersion(Version version) + { + string strError = ""; + + var installVersion = GetSetting("InstallVersion"); + if (string.IsNullOrEmpty(installVersion)) + { + // we need to add the InstallVersion + + string backupFolder = Globals.glbConfigFolder + "Backup_" + DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + DateTime.Now.Hour + DateTime.Now.Minute + "\\"; + var xmlConfig = new XmlDocument(); + //save the current config files + BackupConfig(); + try + { + //open the web.config + xmlConfig = Load(); + + //Update the InstallVersion + xmlConfig = UpdateInstallVersion(xmlConfig, version); + + } + catch (Exception ex) + { + Logger.Error(ex); + strError += ex.Message; + } + + //save a copy of the web.config + strError += Save(xmlConfig, backupFolder + "web_.config"); + + //save the web.config + strError += Save(xmlConfig); + + } + + return strError; + } + + private static XmlDocument UpdateInstallVersion(XmlDocument xmlConfig, Version version) + { + // only update appsetting if necessary + xmlConfig = AddAppSetting(xmlConfig, "InstallVersion", Globals.FormatVersion(version), false); + + return xmlConfig; + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/DataCache.cs b/DNN Platform/Library/Common/Utilities/DataCache.cs new file mode 100644 index 00000000000..591366e9df6 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/DataCache.cs @@ -0,0 +1,769 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using System.Web.Caching; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.OutputCache; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public enum CoreCacheType + { + Host = 1, + Portal = 2, + Tab = 3 + } + + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Common.Utilities + /// Class: DataCache + /// ----------------------------------------------------------------------------- + /// + /// The DataCache class is a facade class for the CachingProvider Instance's + /// + /// + /// [cnurse] 12/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public class DataCache + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (DataCache)); + //Host keys + public const string SecureHostSettingsCacheKey = "SecureHostSettings"; + public const string UnSecureHostSettingsCacheKey = "UnsecureHostSettings"; + public const string HostSettingsCacheKey = "HostSettings"; + public const CacheItemPriority HostSettingsCachePriority = CacheItemPriority.NotRemovable; + public const int HostSettingsCacheTimeOut = 20; + + //Portal keys + public const string PortalAliasCacheKey = "PortalAlias"; + public const CacheItemPriority PortalAliasCachePriority = CacheItemPriority.NotRemovable; + public const int PortalAliasCacheTimeOut = 200; + + public const string PortalSettingsCacheKey = "PortalSettings{0}"; + public const CacheItemPriority PortalSettingsCachePriority = CacheItemPriority.NotRemovable; + public const int PortalSettingsCacheTimeOut = 20; + + public const string PortalDictionaryCacheKey = "PortalDictionary"; + public const CacheItemPriority PortalDictionaryCachePriority = CacheItemPriority.High; + public const int PortalDictionaryTimeOut = 20; + + public const string PortalCacheKey = "Portal{0}_{1}"; + public const CacheItemPriority PortalCachePriority = CacheItemPriority.High; + public const int PortalCacheTimeOut = 20; + + public const string AllPortalsCacheKey = "AllPortals"; + public const CacheItemPriority AllPortalsCachePriority = CacheItemPriority.High; + public const int AllPortalsCacheTimeOut = 20; + + public const string PortalUserCountCacheKey = "PortalUserCount{0}"; + public const CacheItemPriority PortalUserCountCachePriority = CacheItemPriority.High; + public const int PortalUserCountCacheTimeOut = 20; + + public const string PortalGroupsCacheKey = "PortalGroups"; + public const CacheItemPriority PortalGroupsCachePriority = CacheItemPriority.High; + public const int PortalGroupsCacheTimeOut = 20; + + //Tab cache keys + public const string TabCacheKey = "Tab_Tabs{0}"; + public const CacheItemPriority TabCachePriority = CacheItemPriority.High; + public const int TabCacheTimeOut = 20; + public const string TabPathCacheKey = "Tab_TabPathDictionary{0}_{1}"; + public const CacheItemPriority TabPathCachePriority = CacheItemPriority.High; + public const int TabPathCacheTimeOut = 20; + public const string TabPermissionCacheKey = "Tab_TabPermissions{0}"; + public const CacheItemPriority TabPermissionCachePriority = CacheItemPriority.High; + public const int TabPermissionCacheTimeOut = 20; + public const string TabAliasSkinCacheKey = "Tab_TabAliasSkins{0}"; + public const CacheItemPriority TabAliasSkinCachePriority = CacheItemPriority.High; + public const int TabAliasSkinCacheTimeOut = 20; + public const string TabCustomAliasCacheKey = "Tab_TabCustomAliases{0}"; + public const CacheItemPriority TabCustomAliasCachePriority = CacheItemPriority.High; + public const int TabCustomAliasCacheTimeOut = 20; + public const string TabUrlCacheKey = "Tab_TabUrls{0}"; + public const CacheItemPriority TabUrlCachePriority = CacheItemPriority.High; + public const int TabUrlCacheTimeOut = 20; + + public const string AuthenticationServicesCacheKey = "AuthenticationServices"; + public const CacheItemPriority AuthenticationServicesCachePriority = CacheItemPriority.NotRemovable; + public const int AuthenticationServicesCacheTimeOut = 20; + + public const string DesktopModulePermissionCacheKey = "DesktopModulePermissions"; + public const CacheItemPriority DesktopModulePermissionCachePriority = CacheItemPriority.High; + public const int DesktopModulePermissionCacheTimeOut = 20; + + public const string DesktopModuleCacheKey = "DesktopModulesByPortal{0}"; + public const CacheItemPriority DesktopModuleCachePriority = CacheItemPriority.High; + public const int DesktopModuleCacheTimeOut = 20; + + public const string PortalDesktopModuleCacheKey = "PortalDesktopModules{0}"; + public const CacheItemPriority PortalDesktopModuleCachePriority = CacheItemPriority.AboveNormal; + public const int PortalDesktopModuleCacheTimeOut = 20; + + public const string ModuleDefinitionCacheKey = "ModuleDefinitions"; + public const CacheItemPriority ModuleDefinitionCachePriority = CacheItemPriority.High; + public const int ModuleDefinitionCacheTimeOut = 20; + + public const string ModuleControlsCacheKey = "ModuleControls"; + public const CacheItemPriority ModuleControlsCachePriority = CacheItemPriority.High; + public const int ModuleControlsCacheTimeOut = 20; + + public const string TabModuleCacheKey = "TabModules{0}"; + public const CacheItemPriority TabModuleCachePriority = CacheItemPriority.AboveNormal; + public const int TabModuleCacheTimeOut = 20; + + public const string ModulePermissionCacheKey = "ModulePermissions{0}"; + public const CacheItemPriority ModulePermissionCachePriority = CacheItemPriority.AboveNormal; + public const int ModulePermissionCacheTimeOut = 20; + + public const string ModuleCacheKey = "Modules{0}"; + public const int ModuleCacheTimeOut = 20; + + public const string FolderCacheKey = "Folders{0}"; + public const int FolderCacheTimeOut = 20; + public const CacheItemPriority FolderCachePriority = CacheItemPriority.Normal; + + public const string FolderUserCacheKey = "Folders|{0}|{1}|{2}"; + public const int FolderUserCacheTimeOut = 20; + public const CacheItemPriority FolderUserCachePriority = CacheItemPriority.Normal; + + public const string FolderMappingCacheKey = "FolderMapping|{0}"; + public const int FolderMappingCacheTimeOut = 20; + public const CacheItemPriority FolderMappingCachePriority = CacheItemPriority.High; + + public const string FolderPermissionCacheKey = "FolderPermissions{0}"; + public const CacheItemPriority FolderPermissionCachePriority = CacheItemPriority.Normal; + public const int FolderPermissionCacheTimeOut = 20; + + public const string ListsCacheKey = "Lists{0}"; + public const CacheItemPriority ListsCachePriority = CacheItemPriority.Normal; + public const int ListsCacheTimeOut = 20; + + public const string ProfileDefinitionsCacheKey = "ProfileDefinitions{0}"; + public const int ProfileDefinitionsCacheTimeOut = 20; + + public const string UserCacheKey = "UserInfo|{0}|{1}"; + public const int UserCacheTimeOut = 1; + public const CacheItemPriority UserCachePriority = CacheItemPriority.Normal; + + public const string UserLookupCacheKey = "UserLookup|{0}"; + public const int UserLookupCacheTimeOut = 20; + public const CacheItemPriority UserLookupCachePriority = CacheItemPriority.High; + + public const string LocalesCacheKey = "Locales{0}"; + public const CacheItemPriority LocalesCachePriority = CacheItemPriority.Normal; + public const int LocalesCacheTimeOut = 20; + + public const string SkinDefaultsCacheKey = "SkinDefaults_{0}"; + public const CacheItemPriority SkinDefaultsCachePriority = CacheItemPriority.Normal; + public const int SkinDefaultsCacheTimeOut = 20; + + public const CacheItemPriority ResourceFilesCachePriority = CacheItemPriority.Normal; + public const int ResourceFilesCacheTimeOut = 20; + + public const string ResourceFileLookupDictionaryCacheKey = "ResourceFileLookupDictionary"; + public const CacheItemPriority ResourceFileLookupDictionaryCachePriority = CacheItemPriority.NotRemovable; + public const int ResourceFileLookupDictionaryTimeOut = 200; + + public const string SkinsCacheKey = "GetSkins{0}"; + + public const string BannersCacheKey = "Banners:{0}:{1}:{2}"; + public const CacheItemPriority BannersCachePriority = CacheItemPriority.Normal; + public const int BannersCacheTimeOut = 20; + + public const string RedirectionsCacheKey = "Redirections:{0}"; + public const CacheItemPriority RedirectionsCachePriority = CacheItemPriority.Default; + public const int RedirectionsCacheTimeOut = 20; + + public const string PreviewProfilesCacheKey = "PreviewProfiles:{0}"; + public const CacheItemPriority PreviewProfilesCachePriority = CacheItemPriority.Default; + public const int PreviewProfilesCacheTimeOut = 20; + + public const string RelationshipTypesCacheKey = "RelationshipTypes"; + public const CacheItemPriority RelationshipTypesCachePriority = CacheItemPriority.Default; + public const int RelationshipTypesCacheTimeOut = 20; + + public const string RelationshipByPortalIDCacheKey = "RelationshipByPortalID:{0}"; + public const CacheItemPriority RelationshipByPortalIDCachePriority = CacheItemPriority.Default; + public const int RelationshipByPortalIDCacheTimeOut = 20; + + public const string RolesCacheKey = "Roles:{0}"; + public const CacheItemPriority RolesCachePriority = CacheItemPriority.Default; + public const int RolesCacheTimeOut = 20; + + public const string NotificationTypesCacheKey = "NotificationTypes:{0}"; + public const CacheItemPriority NotificationTypesCachePriority = CacheItemPriority.Default; + public const int NotificationTypesTimeOut = 20; + + public const string NotificationTypeActionsCacheKey = "NotificationTypeActions:{0}"; + public const string NotificationTypeActionsByNameCacheKey = "NotificationTypeActions:{0}|{1}"; + public const CacheItemPriority NotificationTypeActionsPriority = CacheItemPriority.Default; + public const int NotificationTypeActionsTimeOut = 20; + + + public const string PackagesCacheKey = "Packages_{0}"; + public const CacheItemPriority PackagesCachePriority = CacheItemPriority.Default; + public const int PackagesCacheTimeout = 20; + + private static string _CachePersistenceEnabled = ""; + + private static readonly ReaderWriterLock dictionaryLock = new ReaderWriterLock(); + private static readonly Dictionary lockDictionary = new Dictionary(); + + private static readonly SharedDictionary dictionaryCache = new SharedDictionary(); + + public static bool CachePersistenceEnabled + { + get + { + if (string.IsNullOrEmpty(_CachePersistenceEnabled)) + { + _CachePersistenceEnabled = Config.GetSetting("EnableCachePersistence") ?? "false"; + } + return bool.Parse(_CachePersistenceEnabled); + } + } + + private static string GetDnnCacheKey(string CacheKey) + { + return CachingProvider.GetCacheKey(CacheKey); + } + + private static string CleanCacheKey(string CacheKey) + { + return CachingProvider.CleanCacheKey(CacheKey); + } + + internal static void ItemRemovedCallback(string key, object value, CacheItemRemovedReason removedReason) + { + //if the item was removed from the cache, log the key and reason to the event log + try + { + if (Globals.Status == Globals.UpgradeStatus.None) + { + var objEventLogInfo = new LogInfo(); + switch (removedReason) + { + case CacheItemRemovedReason.Removed: + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.CACHE_REMOVED.ToString(); + break; + case CacheItemRemovedReason.Expired: + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.CACHE_EXPIRED.ToString(); + break; + case CacheItemRemovedReason.Underused: + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.CACHE_UNDERUSED.ToString(); + break; + case CacheItemRemovedReason.DependencyChanged: + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.CACHE_DEPENDENCYCHANGED.ToString(); + break; + } + objEventLogInfo.LogProperties.Add(new LogDetailInfo(key, removedReason.ToString())); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objEventLogInfo); + } + } + catch (Exception exc) + { + //Swallow exception + Logger.Error(exc); + } + } + + public static void ClearCache() + { + CachingProvider.Instance().Clear("Prefix", "DNN_"); + using (ISharedCollectionLock writeLock = dictionaryCache.GetWriteLock()) + { + dictionaryCache.Clear(); + } + + //log the cache clear event + var objEventLogInfo = new LogInfo {LogTypeKey = EventLogController.EventLogType.CACHE_REFRESH.ToString()}; + objEventLogInfo.LogProperties.Add(new LogDetailInfo("*", "Refresh")); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objEventLogInfo); + } + + public static void ClearCache(string cachePrefix) + { + CachingProvider.Instance().Clear("Prefix", GetDnnCacheKey(cachePrefix)); + } + + public static void ClearFolderCache(int PortalId) + { + CachingProvider.Instance().Clear("Folder", PortalId.ToString()); + } + + public static void ClearHostCache(bool Cascade) + { + if (Cascade) + { + ClearCache(); + } + else + { + CachingProvider.Instance().Clear("Host", ""); + } + } + + public static void ClearModuleCache(int TabId) + { + CachingProvider.Instance().Clear("Module", TabId.ToString()); + Dictionary portals = PortalController.GetPortalDictionary(); + if (portals.ContainsKey(TabId)) + { + var tabController = new TabController(); + + Hashtable tabSettings = tabController.GetTabSettings(TabId); + if (tabSettings["CacheProvider"] != null && tabSettings["CacheProvider"].ToString().Length > 0) + { + OutputCachingProvider outputProvider = OutputCachingProvider.Instance(tabSettings["CacheProvider"].ToString()); + if (outputProvider != null) + { + outputProvider.Remove(TabId); + } + } + } + } + + public static void ClearModulePermissionsCachesByPortal(int PortalId) + { + CachingProvider.Instance().Clear("ModulePermissionsByPortal", PortalId.ToString()); + } + + public static void ClearPortalCache(int PortalId, bool Cascade) + { + CachingProvider.Instance().Clear(Cascade ? "PortalCascade" : "Portal", PortalId.ToString()); + } + + public static void ClearTabsCache(int PortalId) + { + CachingProvider.Instance().Clear("Tab", PortalId.ToString()); + } + + public static void ClearDefinitionsCache(int PortalId) + { + RemoveCache(string.Format(ProfileDefinitionsCacheKey, PortalId)); + } + + public static void ClearDesktopModulePermissionsCache() + { + RemoveCache(DesktopModulePermissionCacheKey); + } + + public static void ClearFolderPermissionsCache(int PortalId) + { + RemoveCache(string.Format(FolderPermissionCacheKey, PortalId)); + } + + public static void ClearListsCache(int PortalId) + { + RemoveCache(string.Format(ListsCacheKey, PortalId)); + } + + public static void ClearModulePermissionsCache(int TabId) + { + RemoveCache(string.Format(ModulePermissionCacheKey, TabId)); + } + + public static void ClearTabPermissionsCache(int PortalId) + { + RemoveCache(string.Format(TabPermissionCacheKey, PortalId)); + } + + public static void ClearUserCache(int PortalId, string username) + { + RemoveCache(string.Format(UserCacheKey, PortalId, username)); + } + + + public static void ClearPackagesCache(int portalId) + { + RemoveCache(string.Format(PackagesCacheKey, portalId)); + } + + private static object GetCachedDataFromRuntimeCache(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired) + { + object objObject = GetCache(cacheItemArgs.CacheKey); + + // if item is not cached + if (objObject == null) + { + //Get Unique Lock for cacheKey + object @lock = GetUniqueLockObject(cacheItemArgs.CacheKey); + + // prevent other threads from entering this block while we regenerate the cache + lock (@lock) + { + // try to retrieve object from the cache again (in case another thread loaded the object since we first checked) + objObject = GetCache(cacheItemArgs.CacheKey); + + // if object was still not retrieved + + if (objObject == null) + { + // get object from data source using delegate + try + { + objObject = cacheItemExpired(cacheItemArgs); + } + catch (Exception ex) + { + objObject = null; + Exceptions.LogException(ex); + } + + // set cache timeout + int timeOut = cacheItemArgs.CacheTimeOut * Convert.ToInt32(Host.PerformanceSetting); + + // if we retrieved a valid object and we are using caching + if (objObject != null && timeOut > 0) + { + // save the object in the cache + SetCache(cacheItemArgs.CacheKey, + objObject, + cacheItemArgs.CacheDependency, + Cache.NoAbsoluteExpiration, + TimeSpan.FromMinutes(timeOut), + cacheItemArgs.CachePriority, + cacheItemArgs.CacheCallback); + + // check if the item was actually saved in the cache + + if (GetCache(cacheItemArgs.CacheKey) == null) + { + // log the event if the item was not saved in the cache ( likely because we are out of memory ) + var objEventLogInfo = new LogInfo + { + LogTypeKey = EventLogController.EventLogType.CACHE_OVERFLOW.ToString() + }; + objEventLogInfo.LogProperties.Add(new LogDetailInfo(cacheItemArgs.CacheKey, "Overflow - Item Not Cached")); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objEventLogInfo); + } + } + + //This thread won so remove unique Lock from collection + RemoveUniqueLockObject(cacheItemArgs.CacheKey); + } + } + } + + return objObject; + } + + private static object GetCachedDataFromDictionary(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired) + { + object cachedObject; + + bool isFound; + using (ISharedCollectionLock readLock = dictionaryCache.GetReadLock()) + { + isFound = dictionaryCache.TryGetValue(cacheItemArgs.CacheKey, out cachedObject); + } + + if (!isFound) + { + // get object from data source using delegate + try + { + cachedObject = cacheItemExpired != null ? cacheItemExpired(cacheItemArgs) : null; + } + catch (Exception ex) + { + cachedObject = null; + Exceptions.LogException(ex); + } + + using (ISharedCollectionLock writeLock = dictionaryCache.GetWriteLock()) + { + if (!dictionaryCache.ContainsKey(cacheItemArgs.CacheKey)) + { + if (cachedObject != null) + { + dictionaryCache[cacheItemArgs.CacheKey] = cachedObject; + } + } + } + } + + return cachedObject; + } + + public static TObject GetCachedData(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired) + { + // declare local object and try and retrieve item from the cache + return GetCachedData(cacheItemArgs, cacheItemExpired, false); + } + + internal static TObject GetCachedData(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired, bool storeInDictionary) + { + object objObject = storeInDictionary + ? GetCachedDataFromDictionary(cacheItemArgs, cacheItemExpired) + : GetCachedDataFromRuntimeCache(cacheItemArgs, cacheItemExpired); + + // return the object + if (objObject == null) + { + return default(TObject); + } + return (TObject)objObject; + } + + private static object GetUniqueLockObject(string key) + { + object @lock = null; + dictionaryLock.AcquireReaderLock(new TimeSpan(0, 0, 5)); + try + { + //Try to get lock Object (for key) from Dictionary + if (lockDictionary.ContainsKey(key)) + { + @lock = lockDictionary[key]; + } + } + finally + { + dictionaryLock.ReleaseReaderLock(); + } + if (@lock == null) + { + dictionaryLock.AcquireWriterLock(new TimeSpan(0, 0, 5)); + try + { + //Double check dictionary + if (!lockDictionary.ContainsKey(key)) + { + //Create new lock + lockDictionary[key] = new object(); + } + //Retrieve lock + @lock = lockDictionary[key]; + } + finally + { + dictionaryLock.ReleaseWriterLock(); + } + } + return @lock; + } + + private static void RemoveUniqueLockObject(string key) + { + dictionaryLock.AcquireWriterLock(new TimeSpan(0, 0, 5)); + try + { + //check dictionary + if (lockDictionary.ContainsKey(key)) + { + //Remove lock + lockDictionary.Remove(key); + } + } + finally + { + dictionaryLock.ReleaseWriterLock(); + } + } + + public static TObject GetCache(string CacheKey) + { + object objObject = GetCache(CacheKey); + if (objObject == null) + { + return default(TObject); + } + return (TObject)objObject; + } + + public static object GetCache(string CacheKey) + { + return CachingProvider.Instance().GetItem(GetDnnCacheKey(CacheKey)); + } + + public static void RemoveCache(string CacheKey) + { + CachingProvider.Instance().Remove(GetDnnCacheKey(CacheKey)); + } + + public static void RemoveFromPrivateDictionary(string DnnCacheKey) + { + using (ISharedCollectionLock writeLock = dictionaryCache.GetWriteLock()) + { + dictionaryCache.Remove(CleanCacheKey(DnnCacheKey)); + } + } + + public static void SetCache(string CacheKey, object objObject) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + public static void SetCache(string CacheKey, object objObject, DNNCacheDependency objDependency) + { + SetCache(CacheKey, objObject, objDependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + public static void SetCache(string CacheKey, object objObject, DateTime AbsoluteExpiration) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, AbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + public static void SetCache(string CacheKey, object objObject, TimeSpan SlidingExpiration) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, Cache.NoAbsoluteExpiration, SlidingExpiration, CacheItemPriority.Normal, null); + } + + public static void SetCache(string CacheKey, object objObject, DNNCacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration) + { + SetCache(CacheKey, objObject, objDependency, AbsoluteExpiration, SlidingExpiration, CacheItemPriority.Normal, null); + } + + public static void SetCache(string CacheKey, object objObject, DNNCacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration, CacheItemPriority Priority, + CacheItemRemovedCallback OnRemoveCallback) + { + if (objObject != null) + { + //if no OnRemoveCallback value is specified, use the default method + if (OnRemoveCallback == null) + { + OnRemoveCallback = ItemRemovedCallback; + } + CachingProvider.Instance().Insert(GetDnnCacheKey(CacheKey), objObject, objDependency, AbsoluteExpiration, SlidingExpiration, Priority, OnRemoveCallback); + } + } + + #region "Obsolete Methods" + + [Obsolete("Deprecated in DNN 5.0 - Replace by ClearHostCache(True)")] + public static void ClearModuleCache() + { + ClearHostCache(true); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static object GetPersistentCacheItem(string CacheKey, Type objType) + { + return CachingProvider.Instance().GetItem(GetDnnCacheKey(CacheKey)); + } + + [Obsolete("Deprecated in DNN 5.1.1 - Should have been declared Friend")] + public static void ClearDesktopModuleCache(int PortalId) + { + RemoveCache(string.Format(DesktopModuleCacheKey, PortalId)); + RemoveCache(ModuleDefinitionCacheKey); + RemoveCache(ModuleControlsCacheKey); + } + + [Obsolete("Deprecated in DNN 5.1.1 - Should have been declared Friend")] + public static void ClearHostSettingsCache() + { + RemoveCache(HostSettingsCacheKey); + RemoveCache(SecureHostSettingsCacheKey); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static void RemovePersistentCacheItem(string CacheKey) + { + CachingProvider.Instance().Remove(GetDnnCacheKey(CacheKey)); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static void SetCache(string CacheKey, object objObject, bool PersistAppRestart) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency, bool PersistAppRestart) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static void SetCache(string CacheKey, object objObject, DateTime AbsoluteExpiration, bool PersistAppRestart) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, AbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public static void SetCache(string CacheKey, object objObject, TimeSpan SlidingExpiration, bool PersistAppRestart) + { + DNNCacheDependency objDependency = null; + SetCache(CacheKey, objObject, objDependency, Cache.NoAbsoluteExpiration, SlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - SetCache(ByVal CacheKey As String, ByVal objObject As Object, ByVal objDependency As DotNetNuke.Services.Cache.DNNCacheDependency, ByVal AbsoluteExpiration As Date, ByVal SlidingExpiration As System.TimeSpan)")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration, bool PersistAppRestart) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), AbsoluteExpiration, SlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - SetCache(ByVal CacheKey As String, ByVal objObject As Object, ByVal objDependency As DotNetNuke.Services.Cache.DNNCacheDependency, ByVal AbsoluteExpiration As Date, ByVal SlidingExpiration As System.TimeSpan, ByVal Priority As CacheItemPriority, ByVal OnRemoveCallback As CacheItemRemovedCallback)")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration, CacheItemPriority Priority, + CacheItemRemovedCallback OnRemoveCallback, bool PersistAppRestart) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), AbsoluteExpiration, SlidingExpiration, Priority, OnRemoveCallback); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), AbsoluteExpiration, SlidingExpiration, CacheItemPriority.Normal, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public static void SetCache(string CacheKey, object objObject, CacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration, CacheItemPriority Priority, + CacheItemRemovedCallback OnRemoveCallback) + { + SetCache(CacheKey, objObject, new DNNCacheDependency(objDependency), AbsoluteExpiration, SlidingExpiration, Priority, OnRemoveCallback); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/DateUtils.cs b/DNN Platform/Library/Common/Utilities/DateUtils.cs new file mode 100644 index 00000000000..a239bb3be9e --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/DateUtils.cs @@ -0,0 +1,95 @@ +using System; + +using DotNetNuke.Services.Localization; + +namespace DotNetNuke.Common.Utilities +{ + /// + /// Provides utility methods to work with Dates + /// + public class DateUtils + { + + private static DateTime _lastUpdate = DateTime.MinValue; + + private static TimeSpan _drift = TimeSpan.MinValue; + + private static DateTime GetDatabaseTime() + { + if (DateTime.UtcNow >= _lastUpdate + TimeSpan.FromMinutes(5)) + { + _lastUpdate = DateTime.UtcNow; + _drift = DateTime.UtcNow - Services.SystemDateTime.SystemDateTime.GetCurrentTimeUtc(); + } + + return DateTime.UtcNow + _drift; + } + + /// + /// Returns a string with the pretty printed amount of time since the specified date. + /// + /// DateTime in Utc + public static string CalculateDateForDisplay(DateTime date) + { + var utcTimeDifference = GetDatabaseTime() - date; + + if (utcTimeDifference.TotalSeconds < 60) + { + return String.Format(Localization.GetString("SecondsAgo"), (int) utcTimeDifference.TotalSeconds); + } + + if (utcTimeDifference.TotalMinutes < 60) + { + if (utcTimeDifference.TotalMinutes < 2) + { + return String.Format(Localization.GetString("MinuteAgo"), (int) utcTimeDifference.TotalMinutes); + } + + return String.Format(Localization.GetString("MinutesAgo"), (int)utcTimeDifference.TotalMinutes); + } + + if (utcTimeDifference.TotalHours < 24) + { + if (utcTimeDifference.TotalHours < 2) + { + return String.Format(Localization.GetString("HourAgo"), (int)utcTimeDifference.TotalHours); + } + + return String.Format(Localization.GetString("HoursAgo"), (int)utcTimeDifference.TotalHours); + } + + if (utcTimeDifference.TotalDays < 7) + { + if (utcTimeDifference.TotalDays < 2) + { + return String.Format(Localization.GetString("DayAgo"), (int)utcTimeDifference.TotalDays); + } + + return String.Format(Localization.GetString("DaysAgo"), (int)utcTimeDifference.TotalDays); + } + + if (utcTimeDifference.TotalDays < 30) + { + if (utcTimeDifference.TotalDays < 14) + { + return String.Format(Localization.GetString("WeekAgo"), (int)utcTimeDifference.TotalDays / 7); + } + + return String.Format(Localization.GetString("WeeksAgo"), (int)utcTimeDifference.TotalDays / 7); + } + + if (utcTimeDifference.TotalDays < 180) + { + if (utcTimeDifference.TotalDays < 60) + { + return String.Format(Localization.GetString("MonthAgo"), (int)utcTimeDifference.TotalDays / 30); + } + + return String.Format(Localization.GetString("MonthsAgo"), (int)utcTimeDifference.TotalDays / 30); + } + + // anything else (this is the only time we have to personalize it to the user) + return date.ToShortDateString(); + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/DictionaryExtensions.cs b/DNN Platform/Library/Common/Utilities/DictionaryExtensions.cs new file mode 100644 index 00000000000..7460988acea --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/DictionaryExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections; + +namespace DotNetNuke.Common.Utilities +{ + public static class DictionaryExtensions + { + public static T GetValue(this IDictionary bag, object key, T defaultValue) + { + var value = bag[key] ?? defaultValue; + return (T)value; + } + + public static void SetValue(this IDictionary bag, object key, T value, T defaultValue) + { + if (Equals(defaultValue, value)) + { + bag.Remove(key); + } + else + { + bag[key] = value; + } + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/EnumExtensions.cs b/DNN Platform/Library/Common/Utilities/EnumExtensions.cs new file mode 100644 index 00000000000..9f46a84250b --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/EnumExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Common.Utilities +{ + public static class EnumExtensions + { + public static List> ToKeyValuePairs(this Enum enumType) + { + var pairs = new List>(); + + var names = Enum.GetNames(enumType.GetType()); + var values = Enum.GetValues(enumType.GetType()); + for (var i = 0; i < values.Length; i++) + { + pairs.Add(new KeyValuePair((int) values.GetValue(i), names[i])); + } + return pairs; + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/EscapedString.cs b/DNN Platform/Library/Common/Utilities/EscapedString.cs new file mode 100644 index 00000000000..d76682b9b89 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/EscapedString.cs @@ -0,0 +1,139 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections; +using System.Collections.Generic; + +namespace DotNetNuke.Common.Utilities +{ + public static class EscapedString + { + private const char EscapeSequence = '\\'; + private const string DoubleEscapseSequence = @"\\"; + private const char DefaultSeperator = ','; + + /// + /// Combine the string values of the enumerable into an escaped string + /// + /// An IEnumerable of values to combine + /// An escaped string that is seperated using the specified characeter. The escape character is '\'. + /// The string returned by .ToString() is used as the value of each item in the IEnumerable. + /// The seperator char is ',' + public static string Combine(IEnumerable enumerable) + { + return Combine(enumerable, DefaultSeperator); + } + + /// + /// Combine the string values of the enumerable into an escaped string + /// + /// An IEnumerable of values to combine + /// The character to use as a seperator + /// An escaped string that is seperated using the specified characeter. The escape character is '\'. + /// The string returned by .ToString() is used as the value of each item in the IEnumerable. + public static string Combine(IEnumerable enumerable, char seperator) + { + string result = ""; + + foreach (var item in enumerable) + { + var s = item.ToString(); + s = s.Replace(EscapeSequence.ToString(), EscapeSequence.ToString() + EscapeSequence); + s = s.Replace(seperator.ToString(), EscapeSequence.ToString() + seperator); + result += s + seperator; + } + + return String.IsNullOrEmpty(result) ? "" : result.Substring(0, result.Length - 1); + } + + /// + /// Takes an escaped string and splits it into an IEnumerable of seperate strings + /// + /// The string to seperate + /// IEnumerable of all the seperated strings + /// The escape character is '\', the seperator char is ',' + public static IEnumerable Seperate(string combinedString) + { + return Seperate(combinedString, DefaultSeperator); + } + + /// + /// Takes an escaped string and splits it into an IEnumerable of seperate strings + /// + /// The string to seperate + /// The character on which to split + /// IEnumerable of all the seperated strings + /// The escape character is '\' + public static IEnumerable Seperate(string combinedString, char seperator) + { + var result = new List(); + + if(String.IsNullOrEmpty(combinedString)) + { + return result; + } + + var segments = combinedString.Split(new[] {seperator}); + + for(int i = 0; i < segments.Length; i++) + { + var current = segments[i]; + + while(current.EndsWith(EscapeSequence.ToString())) + { + if(EndsInEscapeMode(current)) + { + i++; + current = current.Substring(0, current.Length - 1) + seperator + segments[i]; + } + else + { + break; + } + } + + result.Add(current.Replace(DoubleEscapseSequence, EscapeSequence.ToString())); + } + + return result; + } + + private static bool EndsInEscapeMode(string s) + { + int escapeCount = 0; + + //count the number of escape chars on end of string + for(int i = s.Length - 1; i > -1; i--) + { + if(s.Substring(i, 1) == EscapeSequence.ToString()) + { + escapeCount++; + } + else + { + break; + } + } + + return escapeCount%2 == 1; //odd count means escape mode is active + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/FileExtensionWhitelist.cs b/DNN Platform/Library/Common/Utilities/FileExtensionWhitelist.cs new file mode 100644 index 00000000000..b943307b00d --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/FileExtensionWhitelist.cs @@ -0,0 +1,161 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; + +namespace DotNetNuke.Common.Utilities +{ + public class FileExtensionWhitelist + { + private readonly List _extensions; + + /// + /// Initializes a new instance of the FileExtensionWhiteList class. + /// + /// a comma seperated list of file extensions with no '.' + /// should match the format used in the FileExtensions Host setting specifically it + /// should not have an '.' in the extensions (e.g. txt,jpg,png,doc) + public FileExtensionWhitelist(string extensionList) + { + _extensions = EscapedString.Seperate(extensionList.ToLowerInvariant()).Select(item => "." + item).ToList(); + } + + /// + /// Returns a string suitale for display to an end user + /// + /// A String of the whitelist extensions formatted for display to an end user + public string ToDisplayString() + { + return ToDisplayString(null); + } + + /// + /// Formats the extension whitelist appropriate for display to an end user + /// + /// A list of additionalExtensions to add to the current extensions + /// case and '.' prefix will be corrected, and duplicates will be excluded from the string + /// A String of the whitelist extensions formatted for storage display to an end user + public string ToDisplayString(IEnumerable additionalExtensions) + { + IEnumerable allExtensions = CombineLists(additionalExtensions); + return "*" + string.Join(", *", allExtensions.ToArray()); + } + + /// + /// The list of extensions in the whitelist. + /// + /// All extensions are lowercase and prefixed with a '.' + public IEnumerable AllowedExtensions + { + get + { + return _extensions; + } + } + + /// + /// Indicates if the file extension is permitted by the Host Whitelist + /// + /// The file extension with or without preceding '.' + /// True if extension is in whitelist or whitelist is empty. False otherwise. + public bool IsAllowedExtension(String extension) + { + return IsAllowedExtension(extension, null); + } + + /// + /// Indicates if the file extension is permitted by the Host Whitelist + /// + /// The file extension with or without preceding '.' + /// + /// True if extension is in whitelist or whitelist is empty. False otherwise. + public bool IsAllowedExtension(string extension, IEnumerable additionalExtensions) + { + List allExtensions = CombineLists(additionalExtensions).ToList(); + if (!allExtensions.Any()) + { + return true; + } + + if (!extension.StartsWith(".")) + { + extension = "." + extension.ToLowerInvariant(); + } + else + { + extension = extension.ToLowerInvariant(); + } + + return allExtensions.Contains(extension); + } + + public override string ToString() + { + return ToDisplayString(); + } + + /// + /// Formats the extension whitelist appropriate for storage in the Host setting + /// + /// A String of the whitelist extensions formatted for storage as a Host setting + public string ToStorageString() + { + return ToStorageString(null); + } + + /// + /// Formats the extension whitelist appropriate for storage in the Host setting + /// + /// A list of additionalExtensions to add to the current extensions + /// case and '.' prefix will be corrected, and duplicates will be excluded from the string + /// A String of the whitelist extensions formatted for storage as a Host setting + public string ToStorageString(IEnumerable additionalExtensions) + { + IEnumerable allExtensions = CombineLists(additionalExtensions); + var leadingDotRemoved = allExtensions.Select(ext => ext.Substring(1)); + return EscapedString.Combine(leadingDotRemoved); + } + + private IEnumerable CombineLists(IEnumerable additionalExtensions) + { + if(additionalExtensions == null) + { + return _extensions; + } + + //toList required to ensure that multiple enumerations of the list are possible + var additionalExtensionsList = additionalExtensions.ToList(); + if( !additionalExtensionsList.Any()) + { + return _extensions; + } + + var normalizedExtensions = NormalizeExtensions(additionalExtensionsList); + return _extensions.Union(normalizedExtensions); + } + + private IEnumerable NormalizeExtensions(IEnumerable additionalExtensions) + { + return additionalExtensions.Select(ext => (ext.StartsWith(".") ? ext : "." + ext).ToLowerInvariant()); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/FileSystemPermissionVerifier.cs b/DNN Platform/Library/Common/Utilities/FileSystemPermissionVerifier.cs new file mode 100644 index 00000000000..35159975633 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/FileSystemPermissionVerifier.cs @@ -0,0 +1,206 @@ +#region Copyright +// +// DotNetNuke? - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; + +using DotNetNuke.Common.Utilities.Internal; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// + /// Verifies the abililty to create and delete files and folders + /// + /// + /// This class is not meant for use in modules, or in any other manner outside the DotNetNuke core. + /// + public class FileSystemPermissionVerifier + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (FileSystemPermissionVerifier)); + private readonly string _basePath; + + private int _retryTimes = 30; + + /// + /// Base path need to verify permission. + /// + public string BasePath + { + get + { + return _basePath; + } + } + + public FileSystemPermissionVerifier(string basePath) + { + _basePath = basePath; + } + + public FileSystemPermissionVerifier(string basePath, int retryTimes) : this(basePath) + { + + _retryTimes = retryTimes; + } + + /// ----------------------------------------------------------------------------- + /// + /// VerifyFileCreate checks whether a file can be created + /// + /// ----------------------------------------------------------------------------- + public bool VerifyFileCreate() + { + string verifyPath = Path.Combine(_basePath, "Verify\\Verify.txt"); + bool verified = VerifyFolderCreate(); + + if (verified) + { + //Attempt to create the File + try + { + Try(() => FileCreateAction(verifyPath), "Creating verification file"); + } + catch (Exception exc) + { + Logger.Error(exc); + verified = false; + } + } + + return verified; + } + + private static void FileCreateAction(string verifyPath) + { + if (File.Exists(verifyPath)) + { + File.Delete(verifyPath); + } + + using(File.Create(verifyPath)) + { + //do nothing just let it close + } + } + + /// ----------------------------------------------------------------------------- + /// + /// VerifyFileDelete checks whether a file can be deleted + /// + /// ----------------------------------------------------------------------------- + public bool VerifyFileDelete() + { + string verifyPath = Path.Combine(_basePath, "Verify\\Verify.txt"); + bool verified = VerifyFileCreate(); + + if (verified) + { + //Attempt to delete the File + try + { + Try(() => File.Delete(verifyPath), "Deleting verification file"); + } + catch (Exception exc) + { + Logger.Error(exc); + verified = false; + } + } + + return verified; + } + + /// ----------------------------------------------------------------------------- + /// + /// VerifyFolderCreate checks whether a folder can be created + /// + /// ----------------------------------------------------------------------------- + public bool VerifyFolderCreate() + { + string verifyPath = Path.Combine(_basePath, "Verify"); + bool verified = true; + + //Attempt to create the Directory + try + { + Try(() => FolderCreateAction(verifyPath), "Creating verification folder"); + } + catch (Exception exc) + { + Logger.Error(exc); + verified = false; + } + + return verified; + } + + private static void FolderCreateAction(string verifyPath) + { + if (Directory.Exists(verifyPath)) + { + Directory.Delete(verifyPath, true); + } + + Directory.CreateDirectory(verifyPath); + } + + /// ----------------------------------------------------------------------------- + /// + /// VerifyFolderDelete checks whether a folder can be deleted + /// + /// ----------------------------------------------------------------------------- + public bool VerifyFolderDelete() + { + string verifyPath = Path.Combine(_basePath, "Verify"); + bool verified = VerifyFolderCreate(); + + if (verified) + { + //Attempt to delete the Directory + try + { + Try(() => Directory.Delete(verifyPath), "Deleting verification folder"); + } + catch (Exception exc) + { + Logger.Error(exc); + verified = false; + } + } + + return verified; + } + + public bool VerifyAll() + { + return VerifyFileDelete() && VerifyFolderDelete(); + } + + private void Try(Action action, string description) + { + new RetryableAction(action, description, _retryTimes, TimeSpan.FromSeconds(1)).TryIt(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/FileSystemUtils.cs b/DNN Platform/Library/Common/Utilities/FileSystemUtils.cs new file mode 100644 index 00000000000..5ce3f09b5e2 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/FileSystemUtils.cs @@ -0,0 +1,1706 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Web; + +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip; + +using Telerik.Web.UI; + +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class FileSystemUtils + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (FileSystemUtils)); + #region Private Methods + + private static string CreateFile(IFolderInfo folder, string fileName, string contentType, Stream fileContent, bool unzip, bool overwrite, bool checkPermissions) + { + var strMessage = ""; + var fileManager = FileManager.Instance; + + try + { + var file = fileManager.AddFile(folder, fileName, fileContent, overwrite, checkPermissions, contentType); + if (unzip && file.Extension == "zip") + { + fileManager.UnzipFile(file, folder); + } + } + catch (PermissionsNotMetException) + { + strMessage += "
" + string.Format(Localization.GetString("InsufficientFolderPermission"), folder.FolderPath); + } + catch (NoSpaceAvailableException) + { + strMessage += "
" + string.Format(Localization.GetString("DiskSpaceExceeded"), fileName); + } + catch (InvalidFileExtensionException) + { + strMessage += "
" + string.Format(Localization.GetString("RestrictedFileType"), fileName, Host.AllowedExtensionWhitelist.ToDisplayString()); + } + catch (Exception ex) + { + Logger.Error(ex); + + strMessage += "
" + string.Format(Localization.GetString("SaveFileError"), fileName); + } + + return strMessage; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the filename for a file path + /// + /// The full name of the file + /// + /// [cnurse] 04/26/2006 Created + /// + /// ----------------------------------------------------------------------------- + private static string GetFileName(string filePath) + { + return Path.GetFileName(filePath).Replace(Globals.glbProtectedExtension, ""); + } + + private static int GetFolderPortalID(PortalSettings settings) + { + return (settings.ActiveTab.ParentId == settings.SuperTabId) ? Null.NullInteger : settings.PortalId; + } + + private static void RemoveOrphanedFiles(FolderInfo folder, int PortalId) + { + if (folder.FolderMappingID != FolderMappingController.Instance.GetFolderMapping(PortalId, "Database").FolderMappingID) + { + foreach (FileInfo objFile in FolderManager.Instance.GetFiles(folder)) + { + RemoveOrphanedFile(objFile, PortalId); + } + } + } + + private static void RemoveOrphanedFile(FileInfo objFile, int PortalId) + { + FileManager.Instance.DeleteFile(objFile); + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a Stream to the appropriate File Storage + /// + /// The Id of the File + /// The Input Stream + /// + /// + /// + /// [cnurse] 04/27/2006 Created + /// + /// ----------------------------------------------------------------------------- + private static void WriteStream(HttpResponse objResponse, Stream objStream) + { + //Buffer to read 10K bytes in chunk: + var bytBuffer = new byte[10000]; + + //Length of the file: + int intLength; + + //Total bytes to read: + long lngDataToRead; + try + { + //Total bytes to read: + lngDataToRead = objStream.Length; + + //Read the bytes. + while (lngDataToRead > 0) + { + //Verify that the client is connected. + if (objResponse.IsClientConnected) + { + //Read the data in buffer + intLength = objStream.Read(bytBuffer, 0, 10000); + + //Write the data to the current output stream. + objResponse.OutputStream.Write(bytBuffer, 0, intLength); + + //Flush the data to the HTML output. + objResponse.Flush(); + + lngDataToRead = lngDataToRead - intLength; + } + else + { + lngDataToRead = -1; + } + } + } + catch (Exception ex) + { + Logger.Error(ex); + objResponse.Write("Error : " + ex.Message); + } + finally + { + if (objStream != null) + { + objStream.Close(); + objStream.Dispose(); + } + } + } + + #endregion + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string CheckValidFileName(string fileName) + { + FileExtensionWhitelist whiteList = Host.AllowedExtensionWhitelist; + if (!whiteList.IsAllowedExtension(Path.GetExtension(fileName))) + { + if (HttpContext.Current != null) + { + return "
" + string.Format(Localization.GetString("RestrictedFileType"), fileName, whiteList.ToDisplayString()); + } + + return "RestrictedFileType"; + } + + return Null.NullString; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.AddTrailingSlash(string source) ")] + public static string AddTrailingSlash(string strSource) + { + return PathUtils.Instance.AddTrailingSlash(strSource); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.RemoveTrailingSlash(string source) ")] + public static string RemoveTrailingSlash(string strSource) + { + return PathUtils.Instance.RemoveTrailingSlash(strSource); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.StripFolderPath(string originalPath) ")] + public static string StripFolderPath(string strOrigPath) + { + return PathUtils.Instance.StripFolderPath(strOrigPath); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.FormatFolderPath(string folderPath) ")] + public static string FormatFolderPath(string folderPath) + { + return PathUtils.Instance.FormatFolderPath(folderPath); + } + + /// + /// The MapPath method maps the specified relative or virtual path to the corresponding physical directory on the server. + /// + /// Specifies the relative or virtual path to map to a physical directory. If Path starts with either + /// a forward (/) or backward slash (\), the MapPath method returns a path as if Path were a full, virtual path. If Path + /// doesn't start with a slash, the MapPath method returns a path relative to the directory of the .asp file being processed + /// + /// If path is a null reference (Nothing in Visual Basic), then the MapPath method returns the full physical path + /// of the directory that contains the current application + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.MapPath(string path) ")] + public static string MapPath(string path) + { + return PathUtils.Instance.MapPath(path); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.AddAllUserReadPermission(IFolderInfo folder, PermissionInfo permission) ")] + public static void AddAllUserReadPermission(FolderInfo folder, PermissionInfo permission) + { + FolderManager.Instance.AddAllUserReadPermission(folder, permission); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a File + /// + /// File name + /// The Id of the Portal + /// the folder to save file + /// + /// The type of the content + /// This method adds a new file + /// + /// + /// [cnurse] 04/26/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static void AddFile(string FileName, int PortalId, string Folder, string HomeDirectoryMapPath, string contentType) + { + var fileManager = FileManager.Instance; + + var folder = FolderManager.Instance.GetFolder(PortalId, Folder); + + var file = fileManager.GetFile(folder, FileName); + + if (file == null) + { + file = new FileInfo { PortalId = PortalId, FolderId = folder.FolderID, FileName = FileName }; + using (var fileContent = fileManager.GetFileContent(file)) + { + fileManager.AddFile(folder, FileName, fileContent, false); + } + } + else + { + using (var fileContent = fileManager.GetFileContent(file)) + { + fileManager.UpdateFile(file, fileContent); + } + } + } + + /// + /// Adds a File + /// + /// The File Name + /// The Id of the Portal + /// A flag that indicates whether the file cache should be cleared + /// + /// This method is called by the SynchonizeFolder method, when the file exists in the file system + /// but not in the Database + /// + /// + /// [cnurse] 12/2/2004 Created + /// [cnurse] 04/26/2006 Updated to account for secure storage + /// [cnurse] 04/07/2008 Made public + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string AddFile(string strFile, int PortalId, bool ClearCache, FolderInfo folder) + { + var fileManager = FileManager.Instance; + + var fileName = GetFileName(strFile); + + var file = (FileInfo)fileManager.GetFile(folder, fileName); + + if (file == null) + { + file = new FileInfo { PortalId = PortalId, FolderId = folder.FolderID, FileName = fileName }; + using (var fileContent = fileManager.GetFileContent(file)) + { + fileManager.AddFile(folder, GetFileName(strFile), fileContent, false); + } + } + else + { + using (var fileContent = fileManager.GetFileContent(file)) + { + fileManager.UpdateFile(file, fileContent); + } + } + + return ""; + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a Folder + /// + /// The Portal Settings + /// The parent folder + /// The new folder name + /// + /// [cnurse] 04/26/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.AddFolder(FolderMappingInfo folderMapping, string folderPath) ")] + public static void AddFolder(PortalSettings portalSettings, string parentFolder, string newFolder) + { + var portalID = GetFolderPortalID(portalSettings); + var folderMapping = FolderMappingController.Instance.GetDefaultFolderMapping(portalID); + + if (folderMapping != null) + { +#pragma warning disable 612,618 + AddFolder(portalSettings, parentFolder, newFolder, folderMapping.FolderMappingID); +#pragma warning restore 612,618 + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a Folder with a specificed unique identifier + /// + /// The Portal Settings + /// The parent folder + /// The new folder name + /// The storage location + /// + /// [vnguyen] 06/04/2010 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.AddFolder(FolderMappingInfo folderMapping, string folderPath) ")] + public static void AddFolder(PortalSettings portalSettings, string parentFolder, string newFolder, int storageLocation) + { +#pragma warning disable 612,618 + AddFolder(portalSettings, parentFolder, newFolder, storageLocation, new Guid()); +#pragma warning restore 612,618 + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.AddFolder(FolderMappingInfo folderMapping, string folderPath) ")] + public static void AddFolder(PortalSettings portalSettings, string parentFolder, string newFolder, int storageLocation, Guid uniqueId) + { + FolderMappingInfo folderMapping; + + switch (storageLocation) + { + case (int)FolderController.StorageLocationTypes.InsecureFileSystem: + folderMapping = FolderMappingController.Instance.GetFolderMapping(portalSettings.PortalId, "Standard"); + break; + case (int)FolderController.StorageLocationTypes.SecureFileSystem: + folderMapping = FolderMappingController.Instance.GetFolderMapping(portalSettings.PortalId, "Secure"); + break; + case (int)FolderController.StorageLocationTypes.DatabaseSecure: + folderMapping = FolderMappingController.Instance.GetFolderMapping(portalSettings.PortalId, "Database"); + break; + default: + folderMapping = FolderMappingController.Instance.GetDefaultFolderMapping(portalSettings.PortalId); + break; + } + + if (folderMapping != null) + { + var folderManager = FolderManager.Instance; + + //get relative folder path. + var folderPath = PathUtils.Instance.GetRelativePath(folderMapping.PortalID, parentFolder) + newFolder; + + if (Path.IsPathRooted(folderPath)) + { + folderPath = folderPath.TrimStart(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }); + } + + folderPath = folderPath.Replace("\\", "/"); + + var folder = folderManager.AddFolder(folderMapping, folderPath); + folder.UniqueId = uniqueId; + + folderManager.UpdateFolder(folder); + } + } + + + /// ----------------------------------------------------------------------------- + /// + /// Creates a User Folder + /// + /// Portal Settings for the Portal + /// The Parent Folder Name + /// The UserID, in order to generate the path/foldername + /// The Storage Location + /// + /// + /// + /// [jlucarino] 02/26/2010 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void AddUserFolder(PortalSettings portalSettings, string parentFolder, int storageLocation, int userID) + { + var user = UserController.GetUserById(portalSettings.PortalId, userID); + var folderManager = new FolderManager(); + folderManager.AddUserFolder(user); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.GetUserFolderPath(UserInfo user) ")] + public static string GetUserFolderPath(int userID) + { + var user = UserController.GetUserById(PortalController.GetCurrentPortalSettings().PortalId, userID); + return PathUtils.Instance.GetUserFolderPath(user); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a File to a Zip File + /// + /// + /// [cnurse] 12/4/2004 Created + /// + /// ----------------------------------------------------------------------------- + public static void AddToZip(ref ZipOutputStream ZipFile, string filePath, string fileName, string folder) + { + FileStream fs = null; + try + { + //Open File Stream + var crc = new Crc32(); + fs = File.OpenRead(filePath); + + //Read file into byte array buffer + var buffer = new byte[fs.Length]; + + fs.Read(buffer, 0, buffer.Length); + + //Create Zip Entry + var entry = new ZipEntry(Path.Combine(folder, fileName)); + entry.DateTime = DateTime.Now; + entry.Size = fs.Length; + fs.Close(); + crc.Reset(); + crc.Update(buffer); + entry.Crc = crc.Value; + + //Compress file and add to Zip file + ZipFile.PutNextEntry(entry); + ZipFile.Write(buffer, 0, buffer.Length); + } + finally + { + if (fs != null) + { + fs.Close(); + fs.Dispose(); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Trys to copy a file in the file system + /// + /// The name of the source file + /// The name of the destination file + /// + /// [cnurse] 06/27/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void CopyFile(string sourceFileName, string destFileName) + { + if (File.Exists(destFileName)) + { + File.SetAttributes(destFileName, FileAttributes.Normal); + } + File.Copy(sourceFileName, destFileName, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Copies a File + /// + /// The original File Name + /// The new File Name + /// The Portal Settings for the Portal/Host Account + /// + /// + /// + /// [cnurse] 12/2/2004 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.CopyFile(IFileInfo file, IFolderInfo destinationFolder) ")] + public static string CopyFile(string strSourceFile, string strDestFile, PortalSettings settings) + { + var folderManager = FolderManager.Instance; + var fileManager = FileManager.Instance; + + var portalID = GetFolderPortalID(settings); + + var folderPath = Globals.GetSubFolderPath(strSourceFile, portalID); + var folder = folderManager.GetFolder(portalID, folderPath); + + if (folder != null) + { + var file = fileManager.GetFile(folder, GetFileName(strSourceFile)); + + if (file != null) + { + var destFolderPath = Globals.GetSubFolderPath(strDestFile, portalID); + var destFolder = folderManager.GetFolder(portalID, destFolderPath); + + if (destFolder != null) + { + fileManager.CopyFile(file, destFolder); + } + } + } + + return ""; + } + + /// ----------------------------------------------------------------------------- + /// + /// UploadFile pocesses a single file + /// + /// The folder where the file will be put + /// The file name + /// Content of the file + /// Type of content, ie: text/html + /// + /// + /// + /// + /// + /// [cnurse] 16/9/2004 Updated for localization, Help and 508 + /// [Philip Beadle] 10/06/2004 Moved to Globals from WebUpload.ascx.vb so can be accessed by URLControl.ascx + /// [cnurse] 04/26/2006 Updated for Secure Storage + /// [sleupold] 08/14/2007 Added NewFileName + /// [sdarkis] 10/19/2009 Creates a file from a string + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite, bool checkPermissions, string contentType) ")] + public static string CreateFileFromString(string rootPath, string fileName, string fileData, string contentType, string newFileName, bool unzip) + { + var returnValue = string.Empty; + MemoryStream memStream = null; + + try + { + memStream = new MemoryStream(); + byte[] fileDataBytes = Encoding.UTF8.GetBytes(fileData); + memStream.Write(fileDataBytes, 0, fileDataBytes.Length); + memStream.Flush(); + memStream.Position = 0; + + var fileManager = FileManager.Instance; + var folderManager = FolderManager.Instance; + + var settings = PortalController.GetCurrentPortalSettings(); + var portalID = GetFolderPortalID(settings); + + if (newFileName != Null.NullString) + { + fileName = newFileName; + } + + fileName = Path.GetFileName(fileName); + + var folderPath = Globals.GetSubFolderPath(rootPath + fileName, portalID); + + var folder = folderManager.GetFolder(portalID, folderPath); + + returnValue = CreateFile(folder, fileName, ((FileManager)fileManager).GetContentType(Path.GetExtension(fileName)), memStream, unzip, true, true); + } + catch (Exception ex) + { + Logger.Error(ex); + returnValue = ex.Message; + } + finally + { + if (((memStream != null))) + { + memStream.Close(); + memStream.Dispose(); + } + } + + return returnValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// This checks to see if the folder is a protected type of folder + /// + /// String + /// Boolean + /// + /// + /// + /// [cpaterra] 4/7/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by PathUtils.Instance.IsDefaultProtectedPath(string folderPath) ")] + public static bool DefaultProtectedFolders(string folderPath) + { + return PathUtils.Instance.IsDefaultProtectedPath(folderPath); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes file in areas with a high degree of concurrent file access (i.e. caching, logging) + /// This solves file concurrency issues under heavy load. + /// + /// String + /// Int16 + /// Int16 + /// Boolean + /// + /// + /// + /// [dcaron] 9/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static bool DeleteFileWithWait(string filename, Int16 waitInMilliseconds, Int16 maxAttempts) + { + if (!File.Exists(filename)) + { + return true; + } + bool fileDeleted = false; + int i = 0; + while (fileDeleted != true) + { + if (i > maxAttempts) + { + break; + } + i = i + 1; + try + { + if (File.Exists(filename)) + { + File.Delete(filename); + } + fileDeleted = true; //we don't care if it didn't exist...the operation didn't fail, that's what we care about + } + catch (Exception exc) + { + Logger.Error(exc); + fileDeleted = false; + } + if (fileDeleted == false) + { + Thread.Sleep(waitInMilliseconds); + } + } + return fileDeleted; + } + + /// ----------------------------------------------------------------------------- + /// + /// Trys to delete a file from the file system + /// + /// The name of the file + /// + /// [cnurse] 04/26/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteFile(string fileName) + { + if (File.Exists(fileName)) + { + File.SetAttributes(fileName, FileAttributes.Normal); + File.Delete(fileName); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a file + /// + /// The File to delete + /// The Portal Settings for the Portal/Host Account + /// + /// + /// + /// [Jon Henning] 11/1/2004 Created + /// [cnurse] 12/6/2004 delete file from db + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.DeleteFile(IFileInfo file) ")] + public static string DeleteFile(string sourceFile, PortalSettings settings) + { +#pragma warning disable 612,618 + return DeleteFile(sourceFile, settings, true); +#pragma warning restore 612,618 + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a file + /// + /// The File to delete + /// The Portal Settings for the Portal/Host Account + /// + /// + /// + /// + /// [Jon Henning] 11/1/2004 Created + /// [cnurse] 12/6/2004 delete file from db + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.DeleteFile(IFileInfo file) ")] + public static string DeleteFile(string sourceFile, PortalSettings settings, bool clearCache) + { + string retValue = ""; + + var fileManager = FileManager.Instance; + var folderManager = FolderManager.Instance; + + var fileName = GetFileName(sourceFile); + var portalID = GetFolderPortalID(settings); + var folderPath = Globals.GetSubFolderPath(sourceFile, portalID); + + var folder = folderManager.GetFolder(portalID, folderPath); + + if (folder != null) + { + var file = fileManager.GetFile(folder, fileName); + + if (file != null) + { + try + { + //try and delete the Insecure file + fileManager.DeleteFile(file); + } + catch (PermissionsNotMetException) + { + retValue += "
" + string.Format(Localization.GetString("InsufficientFolderPermission"), folderPath); + } + catch (Exception ex) + { + Logger.Error(ex); + + if (ex.InnerException != null && ex.InnerException.GetType() == typeof(IOException)) + { + retValue += "
" + string.Format(Localization.GetString("FileInUse"), sourceFile); + } + else + { + retValue = ex.Message; + } + } + } + } + + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a folder + /// + /// The Id of the Portal + /// The Directory Info object to delete + /// The Name of the folder relative to the Root of the Portal + /// + /// + /// + /// [cnurse] 12/4/2004 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.DeleteFolder(IFolderInfo folder) ")] + public static void DeleteFolder(int PortalId, DirectoryInfo folder, string folderName) + { + var folderManager = FolderManager.Instance; + var folderPath = PathUtils.Instance.GetRelativePath(PortalId, folder.FullName); + var folderInfo = folderManager.GetFolder(PortalId, folderPath); + + if (folderInfo != null) + { + folderManager.DeleteFolder(folderInfo); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Moved directly from FileManager code, probably should make extension lookup more generic + /// + /// File Location + /// + /// + /// + /// [Jon Henning] 11/1/2004 Created + /// [Jon Henning] 1/4/2005 Fixed extension comparison, added content length header - DNN-386 + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void DownloadFile(string fileLoc) + { + var objFile = new System.IO.FileInfo(fileLoc); + HttpResponse objResponse = HttpContext.Current.Response; + string filename = objFile.Name; + + if (objFile.Exists) + { + objResponse.ClearContent(); + objResponse.ClearHeaders(); + objResponse.AppendHeader("content-disposition", "attachment; filename=\"" + filename + "\""); + objResponse.AppendHeader("Content-Length", objFile.Length.ToString()); + objResponse.ContentType = new FileManager().GetContentType(objFile.Extension.Replace(".", "")); +#pragma warning disable 612,618 + WriteFile(objFile.FullName); +#pragma warning restore 612,618 + objResponse.Flush(); + objResponse.End(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Streams a file to the output stream if the user has the proper permissions + /// + /// Portal Settings + /// FileId identifying file in database + /// Cache file in client browser - true/false + /// Force Download File dialog box - true/false + /// + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.WriteFileToResponse(IFileInfo file, ContentDisposition contentDisposition) ")] + public static bool DownloadFile(PortalSettings settings, int FileId, bool ClientCache, bool ForceDownload) + { + return DownloadFile(GetFolderPortalID(settings), FileId, ClientCache, ForceDownload); + } + + /// ----------------------------------------------------------------------------- + /// + /// Streams a file to the output stream if the user has the proper permissions + /// + /// The Id of the Portal to which the file belongs + /// FileId identifying file in database + /// Cache file in client browser - true/false + /// Force Download File dialog box - true/false + /// + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.WriteFileToResponse(IFileInfo file, ContentDisposition contentDisposition) ")] + public static bool DownloadFile(int PortalId, int FileId, bool ClientCache, bool ForceDownload) + { + var download = false; + var fileManager = FileManager.Instance; + var file = fileManager.GetFile(FileId); + var contentDisposition = ForceDownload ? ContentDisposition.Attachment : ContentDisposition.Inline; + + if (file != null) + { + try + { + fileManager.WriteFileToResponse(file, contentDisposition); + download = true; + } + catch(Exception ex) + { + Logger.Error(ex); + } + } + + return download; + } + + /// ----------------------------------------------------------------------------- + /// + /// gets the content type based on the extension + /// + /// The extension + /// + /// + /// + /// [cnurse] 04/26/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string GetContentType(string extension) + { + return new FileManager().GetContentType(extension); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.GetFileContent(IFileInfo file) ")] + public static byte[] GetFileContent(FileInfo file) + { + return null; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.GetFileContent(IFileInfo file) ")] + public static Stream GetFileStream(FileInfo objFile) + { + return FileManager.Instance.GetFileContent(objFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFiles(IFolderInfo folder) ")] + public static ArrayList GetFilesByFolder(int PortalId, int folderId) + { + var filesArray = new ArrayList(); + + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(folderId); + + if (folder != null) + { + var files = folderManager.GetFiles(folder); + foreach (var file in files) + { + filesArray.Add((FileInfo)file); + } + } + + return filesArray; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static int GetFolderPortalId(PortalSettings settings) + { + return GetFolderPortalID(settings); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the folders for a Portal + /// + /// The Id of the Portal + /// + /// + /// + /// [cnurse] 04/22/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolders(int portalID) ")] + public static ArrayList GetFolders(int portalID) + { + var folders = FolderManager.Instance.GetFolders(portalID); + var foldersArray = new ArrayList(); + + foreach (var folder in folders) + { + foldersArray.Add(folder); + } + + return foldersArray; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolder(int portalID, string folderPath) ")] + public static FolderInfo GetFolder(int portalID, string folderPath) + { + return (FolderInfo)FolderManager.Instance.GetFolder(portalID, folderPath); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the subFolders for a Parent + /// + /// The Id of the Portal + /// + /// + /// + /// + /// [cnurse] 04/22/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolders(IFolderInfo parentFolder) ")] + public static ArrayList GetFoldersByParentFolder(int portalId, string parentFolder) + { + var folder = FolderManager.Instance.GetFolder(portalId, parentFolder); + var folders = FolderManager.Instance.GetFolders(folder); + + var subFolders = new ArrayList(); + + foreach (var subfolder in folders) + { + subFolders.Add((FolderInfo)subfolder); + } + + return subFolders; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolders(UserInfo user, string permissions) or FolderManager.Instance.GetFileSystemFolders(UserInfo user, string permissions) ")] + public static ArrayList GetFoldersByUser(int portalID, bool includeSecure, bool includeDatabase, string permissions) + { + var userFoldersArray = new ArrayList(); + + var user = UserController.GetCurrentUserInfo(); + + //Create Home folder if it doesn't exist + var userFolders = (!includeSecure && !includeDatabase) ? FolderManager.Instance.GetFileSystemFolders(user, permissions) : + FolderManager.Instance.GetFolders(user, permissions); + + foreach (var userFolder in userFolders) + { + //Add User folder + userFoldersArray.Add((FolderInfo)userFolder); + } + + return userFoldersArray; + } + + /// ----------------------------------------------------------------------------- + /// + /// Moves (Renames) a File + /// + /// The original File Name + /// The new File Name + /// The Portal Settings for the Portal/Host Account + /// + /// + /// + /// [cnurse] 12/2/2004 Created + /// host dnnhost + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.MoveFile(IFileInfo file, IFolderInfo destinationFolder) ")] + public static string MoveFile(string strSourceFile, string strDestFile, PortalSettings settings) + { + var folderManager = FolderManager.Instance; + var fileManager = FileManager.Instance; + + var portalID = GetFolderPortalID(settings); + + var folderPath = Globals.GetSubFolderPath(strSourceFile, portalID); + var folder = folderManager.GetFolder(portalID, folderPath); + + if (folder != null) + { + var file = fileManager.GetFile(folder, GetFileName(strSourceFile)); + + if (file != null) + { + var destFolderPath = Globals.GetSubFolderPath(strDestFile, portalID); + var destFolder = folderManager.GetFolder(portalID, destFolderPath); + var destFileName = GetFileName(strDestFile); + + if (destFolder != null) + { + fileManager.MoveFile(file, destFolder); + + fileManager.RenameFile(file, destFileName); + + } + } + } + + return ""; + } + + public static string ReadFile(string filePath) + { + StreamReader reader = null; + string fileContent = string.Empty; + try + { + reader = File.OpenText(filePath); + fileContent = reader.ReadToEnd(); + } + finally + { + if (reader != null) + { + reader.Close(); + reader.Dispose(); + } + } + return fileContent; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void RemoveOrphanedFolders(int portalId) + { + var folderManager = FolderManager.Instance; + var databaseMapping = FolderMappingController.Instance.GetFolderMapping(portalId, "Database"); + + foreach (FolderInfo objFolder in folderManager.GetFolders(portalId)) + { + if (objFolder.FolderMappingID != databaseMapping.FolderMappingID) + { + if (Directory.Exists(objFolder.PhysicalPath) == false) + { + RemoveOrphanedFiles(objFolder, portalId); + folderManager.DeleteFolder(objFolder); + } + } + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void SaveFile(string fullFileName, byte[] buffer) + { + if (File.Exists(fullFileName)) + { + File.SetAttributes(fullFileName, FileAttributes.Normal); + } + FileStream fs = null; + try + { + fs = new FileStream(fullFileName, FileMode.Create, FileAccess.Write); + fs.Write(buffer, 0, buffer.Length); + } + finally + { + if (fs != null) + { + fs.Close(); + fs.Dispose(); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Assigns 1 or more attributes to a file + /// + /// File Location + /// Pass in Attributes you wish to switch on (i.e. FileAttributes.Hidden + FileAttributes.ReadOnly) + /// + /// + /// + /// [Jon Henning] 11/1/2004 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void SetFileAttributes(string fileLoc, int fileAttributesOn) + { + File.SetAttributes(fileLoc, (FileAttributes)fileAttributesOn); + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets a Folders Permissions to the Administrator Role + /// + /// The Id of the Portal + /// The Id of the Folder + /// The Id of the Administrator Role + /// The folder's Relative Path + /// + /// + /// + /// [cnurse] 12/4/2004 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.SetFolderPermissions(IFolderInfo folder, int administratorRoleId) ")] + public static void SetFolderPermissions(int portalId, int folderId, int administratorRoleId, string relativePath) + { + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(folderId); + folderManager.SetFolderPermissions(folder, administratorRoleId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.CopyParentFolderPermissions(IFolderInfo folder) ")] + public static void SetFolderPermissions(int portalId, int folderId, string relativePath) + { + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(folderId); + folderManager.CopyParentFolderPermissions(folder); + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets a Folders Permissions the same as the Folders parent folder + /// + /// The Id of the Portal + /// The Id of the Folder + /// + /// + /// The folder's Relative Path + /// + /// + /// + /// [cnurse] 08/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.SetFolderPermission(IFolderInfo folder, int permissionId, int roleId) ")] + public static void SetFolderPermission(int portalId, int folderId, int permissionId, int roleId, string relativePath) + { + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(folderId); + folderManager.SetFolderPermission(folder, permissionId, roleId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.SetFolderPermission(IFolderInfo folder, int permissionId, int roleId, int userId) ")] + public static void SetFolderPermission(int PortalId, int FolderId, int PermissionId, int RoleId, int UserId, string relativePath) + { + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(FolderId); + folderManager.SetFolderPermission(folder, PermissionId, RoleId, UserId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.Synchronize(int portalID) ")] + public static void Synchronize(int PortalId, int AdministratorRoleId, string HomeDirectory, bool hideSystemFolders) + { + FolderManager.Instance.Synchronize(PortalId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.Synchronize(int portalID, string relativePath, bool isRecursive, bool syncFiles) ")] + public static void SynchronizeFolder(int PortalId, string physicalPath, string relativePath, bool isRecursive, bool hideSystemFolders) + { + FolderManager.Instance.Synchronize(PortalId, relativePath, isRecursive, true); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.Synchronize(int portalID, string relativePath, bool isRecursive, bool syncFiles) ")] + public static void SynchronizeFolder(int PortalId, string physicalPath, string relativePath, bool isRecursive, bool syncFiles, bool forceFolderSync, bool hideSystemFolders) + { + FolderManager.Instance.Synchronize(PortalId, relativePath, isRecursive, syncFiles); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.UnzipFile(IFileInfo file, IFolderInfo destinationFolder) ")] + public static string UnzipFile(string fileName, string DestFolder, PortalSettings settings) + { + var folderManager = FolderManager.Instance; + var fileManager = FileManager.Instance; + + var portalID = settings.PortalId; + + var folderPath = PathUtils.Instance.GetRelativePath(portalID, DestFolder); + var folder = folderManager.GetFolder(portalID, folderPath); + + if (folder != null) + { + var file = fileManager.GetFile(folder, GetFileName(fileName)); + + if (file != null) + { + fileManager.UnzipFile(file, folder); + } + } + + return ""; + } + + public static void UnzipResources(ZipInputStream zipStream, string destPath) + { + try + { + ZipEntry objZipEntry; + string LocalFileName; + string RelativeDir; + string FileNamePath; + objZipEntry = zipStream.GetNextEntry(); + while (objZipEntry != null) + { + LocalFileName = objZipEntry.Name; + RelativeDir = Path.GetDirectoryName(objZipEntry.Name); + if ((RelativeDir != string.Empty) && (!Directory.Exists(Path.Combine(destPath, RelativeDir)))) + { + Directory.CreateDirectory(Path.Combine(destPath, RelativeDir)); + } + if ((!objZipEntry.IsDirectory) && (!String.IsNullOrEmpty(LocalFileName))) + { + FileNamePath = Path.Combine(destPath, LocalFileName).Replace("/", "\\"); + try + { + if (File.Exists(FileNamePath)) + { + File.SetAttributes(FileNamePath, FileAttributes.Normal); + File.Delete(FileNamePath); + } + FileStream objFileStream = null; + try + { + objFileStream = File.Create(FileNamePath); + int intSize = 2048; + var arrData = new byte[2048]; + intSize = zipStream.Read(arrData, 0, arrData.Length); + while (intSize > 0) + { + objFileStream.Write(arrData, 0, intSize); + intSize = zipStream.Read(arrData, 0, arrData.Length); + } + } + finally + { + if (objFileStream != null) + { + objFileStream.Close(); + objFileStream.Dispose(); + } + } + } + catch(Exception ex) + { + Logger.Error(ex); + } + } + objZipEntry = zipStream.GetNextEntry(); + } + } + finally + { + if (zipStream != null) + { + zipStream.Close(); + zipStream.Dispose(); + } + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string UploadFile(string RootPath, HttpPostedFile objHtmlInputFile) + { + return UploadFile(RootPath, objHtmlInputFile, Null.NullString, false); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string UploadFile(string RootPath, HttpPostedFile objHtmlInputFile, bool Unzip) + { + return UploadFile(RootPath, objHtmlInputFile, Null.NullString, Unzip); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string UploadFile(string RootPath, HttpPostedFile objHtmlInputFile, string NewFileName) + { + return UploadFile(RootPath, objHtmlInputFile, NewFileName, false); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string UploadFile(string RootPath, HttpPostedFile objHtmlInputFile, string NewFileName, bool Unzip) + { + var fileManager = FileManager.Instance; + var folderManager = FolderManager.Instance; + + var settings = PortalController.GetCurrentPortalSettings(); + var portalID = GetFolderPortalID(settings); + + var fileName = objHtmlInputFile.FileName; + + if (NewFileName != Null.NullString) + { + fileName = NewFileName; + } + + fileName = Path.GetFileName(fileName); + + var folderPath = Globals.GetSubFolderPath(RootPath + fileName, portalID); + + var folder = folderManager.GetFolder(portalID, folderPath); + + return CreateFile(folder, fileName, ((FileManager)fileManager).GetContentType(Path.GetExtension(fileName)), objHtmlInputFile.InputStream, Unzip, true, true); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public static string UploadFile(string RootPath, UploadedFile objHtmlInputFile, string NewFileName) + { + var fileManager = FileManager.Instance; + var folderManager = FolderManager.Instance; + + var settings = PortalController.GetCurrentPortalSettings(); + var portalID = GetFolderPortalID(settings); + + var fileName = objHtmlInputFile.FileName; + + if (NewFileName != Null.NullString) + { + fileName = NewFileName; + } + + fileName = Path.GetFileName(fileName); + + var folderPath = Globals.GetSubFolderPath(RootPath + fileName, portalID); + + var folder = folderManager.GetFolder(portalID, folderPath); + + return CreateFile(folder, fileName, ((FileManager)fileManager).GetContentType(Path.GetExtension(fileName)), objHtmlInputFile.InputStream, false, true, true); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static void WriteFile(string strFileName) + { + HttpResponse objResponse = HttpContext.Current.Response; + Stream objStream = null; + try + { + objStream = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read); + WriteStream(objResponse, objStream); + } + catch (Exception ex) + { + Logger.Error(ex); + objResponse.Write("Error : " + ex.Message); + } + finally + { + if (objStream != null) + { + objStream.Close(); + objStream.Dispose(); + } + } + } + + public static string DeleteFiles(Array arrPaths) + { + string strExceptions = ""; + for (int i = 0; i < arrPaths.Length; i++) + { + string strPath = arrPaths.GetValue(i).ToString(); + if (strPath.IndexOf("'") != -1) + { + strPath = strPath.Substring(0, strPath.IndexOf("'")); + } + if (!String.IsNullOrEmpty(strPath.Trim())) + { + strPath = Globals.ApplicationMapPath + "\\" + strPath; + if (strPath.EndsWith("\\")) + { + if (Directory.Exists(strPath)) + { + try + { + Globals.DeleteFolderRecursive(strPath); + } + catch (Exception ex) + { + Logger.Error(ex); + strExceptions += "Error: " + ex.Message + Environment.NewLine; + } + } + } + else + { + if (File.Exists(strPath)) + { + try + { + File.SetAttributes(strPath, FileAttributes.Normal); + File.Delete(strPath); + } + catch (Exception ex) + { + Logger.Error(ex); + strExceptions += "Error: " + ex.Message + Environment.NewLine; + } + } + } + } + } + return strExceptions; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string SendFile(string URL, string FilePath) + { + string strMessage = ""; + try + { + var objWebClient = new WebClient(); + byte[] responseArray = objWebClient.UploadFile(URL, "POST", FilePath); + } + catch (Exception ex) + { + Logger.Error(ex); + strMessage = ex.Message; + } + return strMessage; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string ReceiveFile(HttpRequest Request, string FolderPath) + { + string strMessage = ""; + try + { + if (Request.Files.AllKeys.Length != 0) + { + string strKey = Request.Files.AllKeys[0]; + HttpPostedFile objFile = Request.Files[strKey]; + objFile.SaveAs(FolderPath + objFile.FileName); + } + } + catch (Exception ex) + { + Logger.Error(ex); + strMessage = ex.Message; + } + return strMessage; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string PullFile(string URL, string FilePath) + { + string strMessage = ""; + try + { + var objWebClient = new WebClient(); + objWebClient.DownloadFile(URL, FilePath); + } + catch (Exception ex) + { + Logger.Error(ex); + strMessage = ex.Message; + } + return strMessage; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string GetHash(byte[] bytes) + { + var stream = new MemoryStream(bytes); + return ((FileManager)FileManager.Instance).GetHash(stream); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static string GetHash(Stream stream) + { + return ((FileManager)FileManager.Instance).GetHash(stream); + } + + #region Obsolete Methods + +#pragma warning disable 612,618 + + //Overload to preserve backwards compatability + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by Synchronize(PortalId, AdministratorRoleId, HomeDirectory, hideSystemFolders). Deprecated in DotNetNuke 5.3.0")] + public static void Synchronize(int PortalId, int AdministratorRoleId, string HomeDirectory) + { + Synchronize(PortalId, AdministratorRoleId, HomeDirectory, false); + } + + //Overload to preserve backwards compatability + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by SynchronizeFolder(PortalId, physicalPath, relativePath, isRecursive, hideSystemFolders). Deprecated in DotNetNuke 5.3.0")] + public static void SynchronizeFolder(int PortalId, string physicalPath, string relativePath, bool isRecursive) + { + SynchronizeFolder(PortalId, physicalPath, relativePath, isRecursive, false); + } + + //Overload to preserve backwards compatability + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by SynchronizeFolder(PortalId, physicalPath, relativePath, isRecursive, syncFiles, forceFolderSync, hideSystemFolders). Deprecated in DotNetNuke 5.3.0")] + public static void SynchronizeFolder(int PortalId, string physicalPath, string relativePath, bool isRecursive, bool syncFiles, bool forceFolderSync) + { + SynchronizeFolder(PortalId, physicalPath, relativePath, isRecursive, syncFiles, forceFolderSync, false); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFileContent(FileInfo)")] + public static byte[] GetFileContent(FileInfo file, int PortalId, string HomeDirectory) + { + return GetFileContent(file); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFilesByFolder(PortalId, FolderId)")] + public static ArrayList GetFilesByFolder(int PortalId, string folderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, folderPath, false); + if (objFolder == null) + { + return null; + } + return GetFilesByFolder(PortalId, objFolder.FolderID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFileStream(FileInfo)")] + public static Stream GetFileStream(FileInfo objFile, int PortalId, string HomeDirectory) + { + return GetFileStream(objFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFoldersByUser(ByVal PortalID As Integer, ByVal IncludeSecure As Boolean, ByVal IncludeDatabase As Boolean, ByVal Permissions As String)")] + public static ArrayList GetFoldersByUser(int PortalID, bool IncludeSecure, bool IncludeDatabase, bool AllowAccess, string Permissions) + { + return GetFoldersByUser(PortalID, IncludeSecure, IncludeDatabase, Permissions); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 5.1. Use FolderPermissionController.GetFolderPermissionsCollectionByFolder(PortalId, Folder).ToString(Permission) ")] + public static string GetRoles(string Folder, int PortalId, string Permission) + { + return FolderPermissionController.GetFolderPermissionsCollectionByFolder(PortalId, Folder).ToString(Permission); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by SynchronizeFolder(Integer, Integer, String, String, Boolean)")] + public static void SynchronizeFolder(int PortalId, int AdministratorRoleId, string HomeDirectory, string physicalPath, string relativePath, bool isRecursive) + { + SynchronizeFolder(PortalId, physicalPath, relativePath, isRecursive, true, true, false); + } + +#pragma warning restore 612,618 + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/HtmlUtils.cs b/DNN Platform/Library/Common/Utilities/HtmlUtils.cs new file mode 100644 index 00000000000..b9b00ff2b23 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/HtmlUtils.cs @@ -0,0 +1,780 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Upgrade; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Common.Utilities + /// Project: DotNetNuke + /// Class: HtmlUtils + /// ----------------------------------------------------------------------------- + /// + /// HtmlUtils is a Utility class that provides Html Utility methods + /// + /// + /// + /// + /// [cnurse] 11/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public class HtmlUtils + { + private static readonly Regex HtmlDetectionRegex = new Regex("<(.*\\s*)>", RegexOptions.Compiled | RegexOptions.IgnoreCase); + + /// ----------------------------------------------------------------------------- + /// + /// Clean removes any HTML Tags, Entities (and optionally any punctuation) from + /// a string + /// + /// + /// Encoded Tags are getting decoded, as they are part of the content! + /// + /// The Html to clean + /// A flag indicating whether to remove punctuation + /// The cleaned up string + /// + /// [cnurse] 11/16/2004 created + /// [galatrash] 05/31/2013 added fix for double html-encoding + /// + /// ----------------------------------------------------------------------------- + public static string Clean(string HTML, bool RemovePunctuation) + { + if (string.IsNullOrWhiteSpace(HTML)) + { + return string.Empty; + } + + if (HTML.Contains("<")) + { + // Fix when it is a double-encoded document + HTML = HttpUtility.HtmlDecode(HTML); + } + + //First remove any HTML Tags ("<....>") + HTML = StripTags(HTML, true); + + //Second replace any HTML entities (  < etc) through their char symbol + HTML = HttpUtility.HtmlDecode(HTML); + + //Thirdly remove any punctuation + if (RemovePunctuation) + { + HTML = StripPunctuation(HTML, true); + // When RemovePunctuation is false, HtmlDecode() would have already had removed these + //Finally remove extra whitespace + HTML = StripWhiteSpace(HTML, true); + } + + return HTML; + } + + /// ----------------------------------------------------------------------------- + /// + /// CleanWithTagInfo removes unspecified HTML Tags, Entities (and optionally any punctuation) from a string. + /// + /// + /// + /// + /// The cleaned up string + /// + /// + /// + /// [vnguyen] 09/02/2010 Created + /// + /// ----------------------------------------------------------------------------- + public static string CleanWithTagInfo(string html, string tagsFilter, bool removePunctuation) + { + //First remove unspecified HTML Tags ("<....>") + html = StripUnspecifiedTags(html, tagsFilter, true); + + //Second replace any HTML entities (  < etc) through their char symbol + html = HttpUtility.HtmlDecode(html); + + //Thirdly remove any punctuation + if (removePunctuation) + { + html = StripPunctuation(html, true); + } + + //Finally remove extra whitespace + html = StripWhiteSpace(html, true); + + return html; + } + + + /// ----------------------------------------------------------------------------- + /// + /// Formats an Email address + /// + /// The email address to format + /// The formatted email address + /// + /// [cnurse] 09/29/2005 moved from Globals + /// + /// ----------------------------------------------------------------------------- + public static string FormatEmail(string Email) + { + return FormatEmail(Email, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Formats an Email address + /// + /// The email address to format + /// A flag that indicates whether the text should be cloaked + /// The formatted email address + /// + /// [cnurse] 09/29/2005 moved from Globals + /// + /// ----------------------------------------------------------------------------- + public static string FormatEmail(string Email, bool cloak) + { + string formatEmail = ""; + if (!string.IsNullOrEmpty(Email) && !string.IsNullOrEmpty(Email.Trim())) + { + if (Email.IndexOf("@") != -1) + { + formatEmail = "" + Email + ""; + } + else + { + formatEmail = Email; + } + } + if (cloak) + { + formatEmail = Globals.CloakText(formatEmail); + } + return formatEmail; + } + + /// ----------------------------------------------------------------------------- + /// + /// FormatText replaces
tags by LineFeed characters + ///
+ /// + /// + /// The HTML content to clean up + /// Whether ratain Space + /// The cleaned up string + /// + /// [cnurse] 12/13/2004 created + /// + /// ----------------------------------------------------------------------------- + public static string FormatText(string HTML, bool RetainSpace) + { + //Match all variants of
tag (
,
,
, including embedded space + string brMatch = "\\s*<\\s*[bB][rR]\\s*/\\s*>\\s*"; + //Replace Tags by replacement String and return mofified string + return Regex.Replace(HTML, brMatch, Environment.NewLine); + } + + /// ----------------------------------------------------------------------------- + /// + /// Formats String as Html by replacing linefeeds by
+ ///
+ /// + /// + /// Text to format + /// The formatted html + /// + /// [cnurse] 12/13/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string ConvertToHtml(string strText) + { + string strHtml = strText; + + if (!string.IsNullOrEmpty(strHtml)) + { + strHtml = strHtml.Replace("\r\n", "
"); + strHtml = strHtml.Replace("\n", "
"); + strHtml = strHtml.Replace("\r", "
"); + } + + return strHtml; + } + + /// ----------------------------------------------------------------------------- + /// + /// Formats Html as text by removing
tags and replacing by linefeeds + ///
+ /// + /// + /// Html to format + /// The formatted text + /// + /// [cnurse] 12/13/2004 Documented and modified to use HtmlUtils methods + /// + /// ----------------------------------------------------------------------------- + public static string ConvertToText(string strHtml) + { + string strText = strHtml; + + if (!string.IsNullOrEmpty(strText)) + { + //First remove white space (html does not render white space anyway and it screws up the conversion to text) + //Replace it by a single space + strText = StripWhiteSpace(strText, true); + + //Replace all variants of
by Linefeeds + strText = FormatText(strText, false); + } + + + return strText; + } + + /// ----------------------------------------------------------------------------- + /// + /// Format a domain name including link + /// + /// The domain name to format + /// The formatted domain name + /// + /// [cnurse] 09/29/2005 moved from Globals + /// + /// ----------------------------------------------------------------------------- + public static string FormatWebsite(object Website) + { + string formatWebsite = ""; + if (Website != DBNull.Value) + { + if (!String.IsNullOrEmpty(Website.ToString().Trim())) + { + if (Website.ToString().IndexOf(".") > -1) + { + formatWebsite = " -1 ? "" : "http://") + Website + "\">" + Website + ""; + } + else + { + formatWebsite = Website.ToString(); + } + } + } + return formatWebsite; + } + + /// ----------------------------------------------------------------------------- + /// + /// Shorten returns the first (x) characters of a string + /// + /// + /// + /// The text to reduces + /// The max number of characters to return + /// An optional suffic to append to the shortened string + /// The shortened string + /// + /// [cnurse] 11/16/2004 created + /// + /// ----------------------------------------------------------------------------- + public static string Shorten(string txt, int length, string suffix) + { + string results; + if (txt.Length > length) + { + results = txt.Substring(0, length) + suffix; + } + else + { + results = txt; + } + return results; + } + + /// ----------------------------------------------------------------------------- + /// + /// StripEntities removes the HTML Entities from the content + /// + /// + /// + /// The HTML content to clean up + /// Indicates whether to replace the Entity by a space (true) or nothing (false) + /// The cleaned up string + /// + /// [cnurse] 11/16/2004 created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("This method has been deprecated. Please use System.Web.HtmlUtility.HtmlDecode")] + public static string StripEntities(string HTML, bool RetainSpace) + { + string RepString; + if (RetainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + //Replace Entities by replacement String and return mofified string + return Regex.Replace(HTML, "&[^;]*;", RepString); + } + + /// ----------------------------------------------------------------------------- + /// + /// StripTags removes the HTML Tags from the content + /// + /// + /// + /// The HTML content to clean up + /// Indicates whether to replace the Tag by a space (true) or nothing (false) + /// The cleaned up string + /// + /// [cnurse] 11/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string StripTags(string HTML, bool RetainSpace) + { + //Set up Replacement String + string RepString; + if (RetainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + //Replace Tags by replacement String and return mofified string + return Regex.Replace(HTML, "<[^>]*>", RepString); + } + + /// ----------------------------------------------------------------------------- + /// + /// StripUnspecifiedTags removes the HTML tags from the content -- leaving behind the info + /// for the specified HTML tags. + /// + /// + /// + /// + /// The cleaned up string + /// + /// + /// + /// [vnguyen] 09/02/2010 Created + /// + /// ----------------------------------------------------------------------------- + public static string StripUnspecifiedTags(string html, string specifiedTags, bool retainSpace) + { + var result = new StringBuilder(); + + //Set up Replacement String + string RepString = null; + if (retainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + + //Stripped HTML + result.Append(Regex.Replace(html, "<[^>]*>", RepString)); + + //Adding Tag info from specified tags + foreach (Match m in Regex.Matches(html, "(?<=(" + specifiedTags + ")=)\"(?.*?)\"")) + { + if (m.Value.Length > 0) + { + result.Append(" " + m.Value); + } + } + + return result.ToString(); + } + + + /// ----------------------------------------------------------------------------- + /// + /// StripPunctuation removes the Punctuation from the content + /// + /// + /// + /// The HTML content to clean up + /// Indicates whether to replace the Punctuation by a space (true) or nothing (false) + /// The cleaned up string + /// + /// [cnurse] 11/16/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string StripPunctuation(string HTML, bool RetainSpace) + { + //Create Regular Expression objects + string punctuationMatch = "[~!#\\$%\\^&*\\(\\)-+=\\{\\[\\}\\]\\|;:\\x22'<,>\\.\\?\\\\\\t\\r\\v\\f\\n]"; + var afterRegEx = new Regex(punctuationMatch + "\\s"); + var beforeRegEx = new Regex("\\s" + punctuationMatch); + + //Define return string + string retHTML = HTML + " "; //Make sure any punctuation at the end of the String is removed + + //Set up Replacement String + string RepString; + if (RetainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + while (beforeRegEx.IsMatch(retHTML)) + { + retHTML = beforeRegEx.Replace(retHTML, RepString); + } + while (afterRegEx.IsMatch(retHTML)) + { + retHTML = afterRegEx.Replace(retHTML, RepString); + } + // Return modified string after trimming leading and ending quotation marks + return retHTML.Trim('"'); + } + + /// ----------------------------------------------------------------------------- + /// + /// StripWhiteSpace removes the WhiteSpace from the content + /// + /// + /// + /// The HTML content to clean up + /// Indicates whether to replace the WhiteSpace by a space (true) or nothing (false) + /// The cleaned up string + /// + /// [cnurse] 12/13/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static string StripWhiteSpace(string HTML, bool RetainSpace) + { + //Set up Replacement String + string RepString; + if (RetainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + + //Replace Tags by replacement String and return mofified string + if (HTML == Null.NullString) + { + return Null.NullString; + } + else + { + return Regex.Replace(HTML, "\\s+", RepString); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// StripNonWord removes any Non-Word Character from the content + /// + /// + /// + /// The HTML content to clean up + /// Indicates whether to replace the Non-Word Character by a space (true) or nothing (false) + /// The cleaned up string + /// + /// [cnurse] 1/28/2005 created + /// + /// ----------------------------------------------------------------------------- + public static string StripNonWord(string HTML, bool RetainSpace) + { + //Set up Replacement String + string RepString; + if (RetainSpace) + { + RepString = " "; + } + else + { + RepString = ""; + } + if (HTML == null) + { + //Replace Tags by replacement String and return modified string + return HTML; + } + else + { + return Regex.Replace(HTML, "\\W*", RepString); + } + } + + /// + /// Determines wether or not the passed in string contains any HTML tags + /// + /// Text to be inspected + /// True for HTML and False for plain text + /// + /// + public static bool IsHtml(string text) + { + if ((string.IsNullOrEmpty(text))) + { + return false; + } + + return HtmlDetectionRegex.IsMatch(text); + } + + /// ----------------------------------------------------------------------------- + /// + /// WriteError outputs an Error Message during Install/Upgrade etc + /// + /// + /// + /// The ASP.Net Response object + /// The filename where the Error Occurred + /// The error message + /// + /// [cnurse] 02/21/2005 created + /// + /// ----------------------------------------------------------------------------- + public static void WriteError(HttpResponse response, string file, string message) + { + response.Write("

Error Details

"); + response.Write(""); + response.Write(""); + response.Write(""); + response.Write("
File" + file + "
Error  " + message + "
"); + response.Write("

"); + response.Flush(); + } + + /// ----------------------------------------------------------------------------- + /// + /// WriteFeedback outputs a Feedback Line during Install/Upgrade etc + /// + /// + /// + /// The ASP.Net Response object + /// The indent for this feedback message + /// The feedback message + /// + /// [cnurse] 02/21/2005 created + /// [gve] 07/14/2006 added extra overload (showtime) to show or hide the upgrade runtime + /// + /// ----------------------------------------------------------------------------- + public static void WriteFeedback(HttpResponse response, Int32 indent, string message) + { + WriteFeedback(response, indent, message, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// WriteFeedback outputs a Feedback Line during Install/Upgrade etc + /// + /// + /// + /// The ASP.Net Response object + /// The indent for this feedback message + /// The feedback message + /// Show the timespan before the message + /// + /// [cnurse] 02/21/2005 created + /// [gve] 07/14/2006 added extra overload (showtime) to show or hide the upgrade runtime + /// + /// ----------------------------------------------------------------------------- + public static void WriteFeedback(HttpResponse response, Int32 indent, string message, bool showtime) + { + bool showInstallationMessages = true; + string ConfigSetting = Config.GetSetting("ShowInstallationMessages"); + if (ConfigSetting != null) + { + showInstallationMessages = bool.Parse(ConfigSetting); + } + if (showInstallationMessages) + { + //Get the time of the feedback + TimeSpan timeElapsed = Upgrade.RunTime; + string strMessage = ""; + if (showtime) + { + strMessage += timeElapsed.ToString().Substring(0, timeElapsed.ToString().LastIndexOf(".") + 4) + " -"; + } + for (int i = 0; i <= indent; i++) + { + strMessage += " "; + } + strMessage += message; + response.Write(strMessage); + response.Flush(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// WriteFooter outputs the Footer during Install/Upgrade etc + /// + /// + /// + /// The ASP.Net Response object + /// + /// [cnurse] 02/21/2005 created + /// + /// ----------------------------------------------------------------------------- + public static void WriteFooter(HttpResponse response) + { + response.Write(""); + response.Write(""); + response.Flush(); + } + + /// ----------------------------------------------------------------------------- + /// + /// WriteHeader outputs the Header during Install/Upgrade etc + /// + /// + /// + /// The ASP.Net Response object + /// The mode Install/Upgrade etc + /// + /// [cnurse] 02/21/2005 created + /// + /// ----------------------------------------------------------------------------- + public static void WriteHeader(HttpResponse response, string mode) + { + //Set Response buffer to False + response.Buffer = false; + + //create an install page if it does not exist already + if (!File.Exists(HttpContext.Current.Server.MapPath("~/Install/Install.htm"))) + { + if (File.Exists(HttpContext.Current.Server.MapPath("~/Install/Install.template.htm"))) + { + File.Copy(HttpContext.Current.Server.MapPath("~/Install/Install.template.htm"), HttpContext.Current.Server.MapPath("~/Install/Install.htm")); + } + } + //read install page and insert into response stream + if (File.Exists(HttpContext.Current.Server.MapPath("~/Install/Install.htm"))) + { + response.Write(FileSystemUtils.ReadFile(HttpContext.Current.Server.MapPath("~/Install/Install.htm"))); + } + switch (mode) + { + case "install": + response.Write("

Installing DotNetNuke

"); + break; + case "upgrade": + response.Write("

Upgrading DotNetNuke

"); + break; + case "addPortal": + response.Write("

Adding New Portal

"); + break; + case "installResources": + response.Write("

Installing Resources

"); + break; + case "executeScripts": + response.Write("

Executing Scripts

"); + break; + case "none": + response.Write("

Nothing To Install At This Time

"); + break; + case "noDBVersion": + response.Write("

New DotNetNuke Database

"); + break; + case "error": + response.Write("

Error Installing DotNetNuke

"); + break; + default: + response.Write("

" + mode + "

"); + break; + } + response.Flush(); + } + + public static void WriteSuccessError(HttpResponse response, bool bSuccess) + { + if (bSuccess) + { + WriteFeedback(response, 0, "Success
", false); + } + else + { + WriteFeedback(response, 0, "Error!
", false); + } + } + + public static void WriteScriptSuccessError(HttpResponse response, bool bSuccess, string strLogFile) + { + if (bSuccess) + { + WriteFeedback(response, 0, "Success
", false); + } + else + { + WriteFeedback(response, 0, "Error! (see " + strLogFile + " for more information)
", false); + } + } + + /// + /// Searches the provided html for absolute hrefs that match the provided aliases and converts them to relative urls + /// + /// The input html + /// a list of aliases that should be made into relative urls + /// html string + public static string AbsoluteToRelativeUrls(string html, IEnumerable aliases) + { + foreach (string portalAlias in aliases) + { + string searchAlias = portalAlias; + if (!portalAlias.EndsWith("/")) + { + searchAlias = string.Format("{0}/", portalAlias); + } + string protocol = PortalSettings.Current.SSLEnabled ? "https://" : "http://"; + Regex exp = new Regex(string.Format("(href="){0}{1}(.*?")", protocol, searchAlias)); + + if(portalAlias.Contains("/")) + { + html = exp.Replace(html, "$1" + portalAlias.Substring(portalAlias.IndexOf("/", StringComparison.InvariantCultureIgnoreCase)) + "/$2"); + } + else + { + html = exp.Replace(html, "$1/$2"); + } + } + + return html; + } + + } +} diff --git a/DNN Platform/Library/Common/Utilities/IPathUtils.cs b/DNN Platform/Library/Common/Utilities/IPathUtils.cs new file mode 100644 index 00000000000..d129bcee66d --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/IPathUtils.cs @@ -0,0 +1,109 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Common.Utilities +{ + public interface IPathUtils + { + /// + /// Adds backslash to the specified source. + /// + /// The source string to be modified. + /// The original string plus a backslash. + string AddTrailingSlash(string source); + + /// + /// Formats the provided folder path by adding a slash if needed. + /// + /// The folder path to format. + /// The formatted path. + string FormatFolderPath(string folderPath); + + /// + /// Gets the physical path for the specified relative path. + /// + string GetPhysicalPath(int portalID, string relativePath); + + /// + /// Gets the relative path for the specified physical path. + /// + string GetRelativePath(int portalID, string physicalPath); + + /// + /// Gets the physical root folder path for the specified portal + /// + string GetRootFolderMapPath(int portalID); + + /// + /// Gets the path to a user folder. + /// + /// The user info. + /// The path to a user folder. + [Obsolete("Deprecated in 6.2.0. Replaced by FolderManager.Instance.GetUserFolder(UserInfo)")] + string GetUserFolderPath(UserInfo user); + + /// + /// Get elements from the user folder path. + /// + /// The user identifier. + /// The UserFolderElement to get. + /// The element from the user folder path. + [Obsolete("Deprecated in DNN 6.2. No replacement, this should have been internal only")] + string GetUserFolderPathElement(int userID, PathUtils.UserFolderElement mode); + + /// + /// Checks if a folder is a default protected folder. + /// + /// The folder path. + /// True if the folderPath is a default protected folder. False otherwise. + bool IsDefaultProtectedPath(string folderPath); + + /// + /// The MapPath method maps the specified relative or virtual path to the corresponding physical directory on the server. + /// + /// Specifies the relative or virtual path to map to a physical directory. If Path starts with either + /// a forward (/) or backward slash (\), the MapPath method returns a path as if Path were a full, virtual path. If Path + /// doesn't start with a slash, the MapPath method returns a path relative to the directory of the .asp file being processed + /// + /// + /// If path is a null reference (Nothing in Visual Basic), then the MapPath method returns the full physical path + /// of the directory that contains the current application + /// + string MapPath(string path); + + /// + /// Removes the trailing slash or backslash from the specified source. + /// + /// The source string to be modified. + /// The original string minus the trailing slash. + string RemoveTrailingSlash(string source); + + /// + /// Strips the original path by removing starting 0 or 0\\. + /// + /// The original path. + /// The stripped path. + string StripFolderPath(string originalPath); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/ImageUtils.cs b/DNN Platform/Library/Common/Utilities/ImageUtils.cs new file mode 100644 index 00000000000..7b18480e0fd --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/ImageUtils.cs @@ -0,0 +1,377 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; + +using DotNetNuke.Services.FileSystem.Internal; + +namespace DotNetNuke.Common.Utilities +{ + public class ImageUtils + { + private static int _imgHeight; + private static int _imgWidth; + + public static Size GetSize(string sPath) + { + Image g = Image.FromFile(sPath); + Size s = g.Size; + g.Dispose(); + return s; + } + + /// + /// return height of image + /// + /// file path of image + /// + public static int GetHeight(string sPath) + { + Image g = Image.FromFile(sPath); + int h = g.Height; + g.Dispose(); + return h; + } + + /// + /// return width of image + /// + /// file path of image + /// + public static int GetWidth(string sPath) + { + Image g = Image.FromFile(sPath); + int w = g.Width; + g.Dispose(); + return w; + } + + /// + /// return height of image + /// + /// Stream of image + /// + public static int GetHeightFromStream(Stream sFile) + { + Image g = Image.FromStream(sFile, true); + return g.Height; + } + + /// + /// width of image + /// + /// Steam of image + /// + public static int GetWidthFromStream(Stream sFile) + { + Image g = Image.FromStream(sFile, true); + int w = g.Width; + g.Dispose(); + return w; + } + + /// + /// create an image + /// + /// path of load image file - will be resized according to height and width set + /// + public static string CreateImage(string sFile) + { + Image g = Image.FromFile(sFile); + int h = g.Height; + int w = g.Width; + g.Dispose(); + return CreateImage(sFile, h, w); + } + + /// + /// create an image + /// + /// path of image file + /// height + /// width + /// + public static string CreateImage(string sFile, int intHeight, int intWidth) + { + var fi = new FileInfo(sFile); + string tmp = fi.FullName.Replace(fi.Extension, "_TEMP" + fi.Extension); + if (FileWrapper.Instance.Exists(tmp)) + { + FileWrapper.Instance.SetAttributes(tmp, FileAttributes.Normal); + FileWrapper.Instance.Delete(tmp); + } + + File.Copy(sFile, tmp); + var original = new Bitmap(tmp); + + PixelFormat format = original.PixelFormat; + if (format.ToString().Contains("Indexed")) + { + format = PixelFormat.Format24bppRgb; + } + + int newHeight = intHeight; + int newWidth = intWidth; + Size imgSize; + if (original.Width > newWidth || original.Height > newHeight) + { + imgSize = NewImageSize(original.Width, original.Height, newWidth, newHeight); + _imgHeight = imgSize.Height; + _imgWidth = imgSize.Width; + } + else + { + imgSize = new Size(original.Width, original.Height); + _imgHeight = original.Height; + _imgWidth = original.Width; + } + + string sFileExt = fi.Extension; + string sFileNoExtension = Path.GetFileNameWithoutExtension(sFile); + string sPath = Path.GetDirectoryName(sFile); + if (sPath != null) + { + sPath = sPath.Replace("/", "\\"); + } + if (sPath != null && !sPath.EndsWith("\\")) + { + sPath += "\\"; + } + Image img = Image.FromFile(tmp); + var newImg = new Bitmap(_imgWidth, _imgHeight, format); + newImg.SetResolution(img.HorizontalResolution, img.VerticalResolution); + + Graphics canvas = Graphics.FromImage(newImg); + canvas.SmoothingMode = SmoothingMode.None; + canvas.InterpolationMode = InterpolationMode.HighQualityBicubic; + canvas.PixelOffsetMode = PixelOffsetMode.HighQuality; + + if (sFileExt.ToLowerInvariant() != ".png") + { + canvas.Clear(Color.White); + canvas.FillRectangle(Brushes.White, 0, 0, imgSize.Width, imgSize.Height); + } + canvas.DrawImage(img, 0, 0, imgSize.Width, imgSize.Height); + img.Dispose(); + sFile = sPath; + + sFile += sFileNoExtension + sFileExt; + if (FileWrapper.Instance.Exists(sFile)) + { + FileWrapper.Instance.SetAttributes(sFile, FileAttributes.Normal); + FileWrapper.Instance.Delete(sFile); + } + + //newImg.Save + var arrData = new byte[2048]; + Stream content = new MemoryStream(); + ImageFormat imgFormat = ImageFormat.Bmp; + if (sFileExt.ToLowerInvariant() == ".png") + { + imgFormat = ImageFormat.Png; + } + else if (sFileExt.ToLowerInvariant() == ".gif") + { + imgFormat = ImageFormat.Gif; + } + else if (sFileExt.ToLowerInvariant() == ".jpg") + { + imgFormat = ImageFormat.Jpeg; + } + newImg.Save(content, imgFormat); + using (Stream outStream = FileWrapper.Instance.Create(sFile)) + { + long originalPosition = content.Position; + content.Position = 0; + + try + { + int intLength = content.Read(arrData, 0, arrData.Length); + + while (intLength > 0) + { + outStream.Write(arrData, 0, intLength); + intLength = content.Read(arrData, 0, arrData.Length); + } + } + finally + { + content.Position = originalPosition; + } + } + + newImg.Dispose(); + original.Dispose(); + + canvas.Dispose(); + if (FileWrapper.Instance.Exists(tmp)) + { + FileWrapper.Instance.SetAttributes(tmp, FileAttributes.Normal); + FileWrapper.Instance.Delete(tmp); + } + + + return sFile; + } + + /// + /// create a JPG image + /// + /// name of image + /// bitmap of image + /// image quality + /// + public static string CreateJPG(string sFile, Bitmap img, int compressionLevel) + { + Graphics bmpOutput = Graphics.FromImage(img); + bmpOutput.InterpolationMode = InterpolationMode.HighQualityBicubic; + bmpOutput.SmoothingMode = SmoothingMode.HighQuality; + var compressionRectange = new Rectangle(0, 0, _imgWidth, _imgHeight); + bmpOutput.DrawImage(img, compressionRectange); + + ImageCodecInfo myImageCodecInfo = GetEncoderInfo("image/jpeg"); + Encoder myEncoder = Encoder.Quality; + var myEncoderParameters = new EncoderParameters(1); + var myEncoderParameter = new EncoderParameter(myEncoder, compressionLevel); + myEncoderParameters.Param[0] = myEncoderParameter; + if (File.Exists(sFile)) + { + File.Delete(sFile); + } + try + { + img.Save(sFile, myImageCodecInfo, myEncoderParameters); + } + catch (Exception) + { + //suppress unexpected exceptions + } + + + img.Dispose(); + bmpOutput.Dispose(); + return sFile; + } + + /// + /// create an image based on a stream (read from a database) + /// + /// image name + /// height + /// width + /// steam + public static MemoryStream CreateImageForDB(Stream sFile, int intHeight, int intWidth) + { + var newStream = new MemoryStream(); + Image g = Image.FromStream(sFile); + //Dim thisFormat = g.RawFormat + if (intHeight > 0 & intWidth > 0) + { + int newHeight = intHeight; + int newWidth = intWidth; + if (g.Width > newWidth | g.Height > newHeight) + { + Size imgSize = NewImageSize(g.Width, g.Height, newWidth, newHeight); + _imgHeight = imgSize.Height; + _imgWidth = imgSize.Width; + } + else + { + _imgHeight = g.Height; + _imgWidth = g.Width; + } + } + else + { + _imgWidth = g.Width; + _imgHeight = g.Height; + } + + var imgOutput1 = new Bitmap(g, _imgWidth, _imgHeight); + Graphics bmpOutput = Graphics.FromImage(imgOutput1); + bmpOutput.InterpolationMode = InterpolationMode.HighQualityBicubic; + bmpOutput.SmoothingMode = SmoothingMode.HighQuality; + var compressionRectange = new Rectangle(0, 0, _imgWidth, _imgHeight); + bmpOutput.DrawImage(g, compressionRectange); + ImageCodecInfo myImageCodecInfo = GetEncoderInfo("image/jpeg"); + Encoder myEncoder = Encoder.Quality; + var myEncoderParameters = new EncoderParameters(1); + var myEncoderParameter = new EncoderParameter(myEncoder, 90); + myEncoderParameters.Param[0] = myEncoderParameter; + imgOutput1.Save(newStream, myImageCodecInfo, myEncoderParameters); + g.Dispose(); + imgOutput1.Dispose(); + bmpOutput.Dispose(); + return newStream; + } + + /// + /// return the approriate encoded for the mime-type of the image being created + /// + /// mime type (e.g jpg/png) + /// + public static ImageCodecInfo GetEncoderInfo(string myMimeType) + { + try + { + int i; + ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders(); + for (i = 0; i <= (encoders.Length - 1); i++) + { + if ((encoders[i].MimeType == myMimeType)) + { + return encoders[i]; + } + } + return null; + } + catch + { + return null; + } + } + + /// + /// scale an image based on existing dimensions and updated requirement + /// + /// current width + /// current height + /// new width + /// new height + /// updated calculated height/width minesions + public static Size NewImageSize(int currentWidth, int currentHeight, int newWidth, int newHeight) + { + decimal decScale = ((decimal)currentWidth / (decimal)newWidth) > ((decimal)currentHeight / (decimal)newHeight) ? Convert.ToDecimal((decimal)currentWidth / (decimal)newWidth) : Convert.ToDecimal((decimal)currentHeight / (decimal)newHeight); + newWidth = Convert.ToInt32(Math.Floor((decimal)currentWidth / decScale)); + newHeight = Convert.ToInt32(Math.Floor((decimal)currentHeight / decScale)); + + var newSize = new Size(newWidth, newHeight); + + return newSize; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/JavaScriptObjectDictionary.cs b/DNN Platform/Library/Common/Utilities/JavaScriptObjectDictionary.cs new file mode 100644 index 00000000000..c996bb59c3f --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/JavaScriptObjectDictionary.cs @@ -0,0 +1,144 @@ +using System; +using System.Text; +using System.Web; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +public class JavaScriptObjectDictionary : IEnumerable> +{ + private OrderedDictionary _dictionary = null; + + internal OrderedDictionary Dictionary + { + get + { + return _dictionary ?? (_dictionary = new OrderedDictionary()); + } + } + + public void AddMethodBody(string name, string methodBody) + { + AddMethod(name, "function() { " + methodBody + "; }"); + } + + public void AddMethod(string name, string method) + { + Dictionary[name] = method; + } + + private static string ToJsonString(IEnumerable> methods) + { + if (methods == null) + { + return "null"; + } + var builder = new StringBuilder(); + builder.Append('{'); + var isFirstPair = true; + foreach (var keyValuePair in methods) + { + if (isFirstPair) + { + isFirstPair = false; + } + else + { + builder.Append(','); + } + builder.Append('"'); + builder.Append(HttpUtility.JavaScriptStringEncode(keyValuePair.Key)); + builder.Append('"'); + builder.Append(':'); + var methodValue = string.IsNullOrEmpty(keyValuePair.Value) ? "null" : keyValuePair.Value; + builder.Append(methodValue); + } + builder.Append('}'); + return builder.ToString(); + } + + public string ToJsonString() + { + return ToJsonString(this); + } + + public static string ToJavaScriptArrayString(IEnumerable> methods) + { + if (methods == null) + { + return "null"; + } + var builder = new StringBuilder(); + builder.Append('['); + var isFirstPair = true; + foreach (var keyValuePair in methods) + { + if (isFirstPair) + { + isFirstPair = false; + } + else + { + builder.Append(','); + } + var methodValue = string.IsNullOrEmpty(keyValuePair.Value) ? "null" : keyValuePair.Value; + builder.Append(methodValue); + } + builder.Append(']'); + return builder.ToString(); + } + + public static string ToJavaScriptArrayString(IEnumerable methods) + { + if (methods == null) + { + return "null"; + } + var builder = new StringBuilder(); + builder.Append('['); + var isFirstPair = true; + foreach (var method in methods) + { + if (isFirstPair) + { + isFirstPair = false; + } + else + { + builder.Append(','); + } + var methodValue = string.IsNullOrEmpty(method) ? "null" : method; + builder.Append(methodValue); + } + builder.Append(']'); + return builder.ToString(); + } + + public string ToJavaScriptArrayString() + { + return ToJavaScriptArrayString(this); + } + + public IEnumerator> GetEnumerator() + { + var enumerator = Dictionary.GetEnumerator(); + while (enumerator.MoveNext()) + { + yield return new KeyValuePair(enumerator.Key.ToString(), enumerator.Value.ToString()); + } + } + + private IEnumerator GetEnumeratorPrivate() + { + return GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumeratorPrivate(); + } + + public override string ToString() + { + return _dictionary == null ? string.Empty : _dictionary.ToString(); + } +} diff --git a/DNN Platform/Library/Common/Utilities/Json.cs b/DNN Platform/Library/Common/Utilities/Json.cs new file mode 100644 index 00000000000..6ac6a5d8079 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/Json.cs @@ -0,0 +1,61 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.IO; +using System.Runtime.Serialization.Json; +using System.Text; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// + /// Serialize or Deserialize Json + /// + public static class Json + { + public static T Deserialize(string json) + { + var obj = Activator.CreateInstance(); + using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json))) + { + var serializer = new DataContractJsonSerializer(obj.GetType()); + obj = (T) serializer.ReadObject(ms); + return obj; + } + } + + public static string Serialize(T obj) + { + var serializer = new DataContractJsonSerializer(obj.GetType()); + using (var ms = new MemoryStream()) + { + serializer.WriteObject(ms, obj); + return Encoding.Default.GetString(ms.ToArray()); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/JsonExtensions.cs b/DNN Platform/Library/Common/Utilities/JsonExtensions.cs new file mode 100644 index 00000000000..49354e4035f --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/JsonExtensions.cs @@ -0,0 +1,102 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.Script.Serialization; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// + /// Json Extensions based on the JavaScript Serializer in System.web + /// + public static class JsonExtensionsWeb + { + private static JavaScriptSerializer SerializerFactory() + { + // Allow large JSON strings to be serialized and deserialized. + return new JavaScriptSerializer {MaxJsonLength = Int32.MaxValue}; + } + + /// + /// Serializes a type to Json. Note the type must be marked Serializable + /// or include a DataContract attribute. + /// + /// + /// + public static string ToJsonString(object value) + { + var ser = SerializerFactory(); + string json = ser.Serialize(value); + return json; + } + + /// + /// Extension method on object that serializes the value to Json. + /// Note the type must be marked Serializable or include a DataContract attribute. + /// + /// + /// + public static string ToJson(this object value) + { + return ToJsonString(value); + } + + /// + /// Deserializes a json string into a specific type. + /// Note that the type specified must be serializable. + /// + /// + /// + /// + public static object FromJsonString(string json, Type type) + { + // *** Have to use Reflection with a 'dynamic' non constant type instance + var ser = SerializerFactory(); + + object result = ser.GetType().GetMethod("Deserialize").MakeGenericMethod(type).Invoke(ser, new object[1] {json}); + return result; + } + + /// + /// Extension method to string that deserializes a json string + /// into a specific type. + /// Note that the type specified must be serializable. + /// + /// + /// + /// + public static object FromJson(this string json, Type type) + { + return FromJsonString(json, type); + } + + public static TType FromJson(this string json) + { + var ser = SerializerFactory(); + + var result = ser.Deserialize(json); + return result; + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/NetworkUtils.cs b/DNN Platform/Library/Common/Utilities/NetworkUtils.cs new file mode 100644 index 00000000000..ecedf8c602c --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/NetworkUtils.cs @@ -0,0 +1,222 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Net; +using System.Net.Sockets; + +#endregion + +namespace DotNetNuke.Common.Utils +{ + public class NetworkUtils + { + public static string GetAddress(string Host, AddressType AddressFormat) + { + string IPAddress = string.Empty; + AddressFamily addrFamily = AddressFamily.InterNetwork; + switch (AddressFormat) + { + case AddressType.IPv4: + addrFamily = AddressFamily.InterNetwork; + break; + case AddressType.IPv6: + addrFamily = AddressFamily.InterNetworkV6; + break; + } + IPHostEntry IPE = Dns.GetHostEntry(Host); + if (Host != IPE.HostName) + { + IPE = Dns.GetHostEntry(IPE.HostName); + } + foreach (IPAddress IPA in IPE.AddressList) + { + if (IPA.AddressFamily == addrFamily) + { + return IPA.ToString(); + } + } + return string.Empty; + } + public static long IPtoLong(IPAddress ip) + { + //convert IP to number + + byte[] addressBytes = ip.GetAddressBytes(); + //get the octets + long addr = 0; + //accumulator for address + + for (int x = 0; x <= 3; x++) + { + addr = addr | (Convert.ToInt64(addressBytes[x]) << (3 - x) * 8); + } + return addr; + } + + public static string LongToIp(long ip) + { + //convert number back to IP + + var ipByte = new byte[4]; + //4 octets + string addr = ""; + //accumulator for address + + long mask8 = MaskFromCidr(8); + //create eight bit mask + + //get the octets + for (int x = 0; x <= 3; x++) + { + ipByte[x] = Convert.ToByte((ip & mask8) >> ((3 - x) * 8)); + mask8 = mask8 >> 8; + addr += ipByte[x].ToString() + "."; + //add current octet to string + } + return addr.TrimEnd('.'); + } + + private static long MaskFromCidr(int cidr) + { + return Convert.ToInt64(Math.Pow(2, ((32 - cidr))) - 1) ^ 4294967295L; + } + + public static string FormatAsCidr(string startIP, string subnetMask) + { + if (String.IsNullOrEmpty(subnetMask)) + { + return startIP; + } + + IPAddress ipAddress = IPAddress.Parse(startIP); + IPAddress mask = IPAddress.Parse(subnetMask); + + long ipL = IPtoLong(ipAddress); + long maskL = IPtoLong(mask); + + //Convert Mask to CIDR(1-30) + long oneBit = 0x80000000L; + int cidr = 0; + + for (int x = 31; x >= 0; x += -1) + { + if ((maskL & oneBit) == oneBit) + cidr += 1; + else + break; + oneBit = oneBit >> 1; + } + + string answer = LongToIp(ipL & maskL) + " /" + cidr.ToString(); + return answer; + } + + public static void Network2IpRange(string sNetwork, out uint startIP, out uint endIP) + { + try + { + string[] elements = sNetwork.Split(new[] { '/' }); + + uint ip = IP2Int(elements[0]); + int bits = Convert.ToInt32(elements[1]); + + uint mask = ~(0xffffffff >> bits); + + uint network = ip & mask; + uint broadcast = network + ~mask; + + uint usableIps = (bits > 30) ? 0 : (broadcast - network - 1); + + if (usableIps <= 0) + { + startIP = endIP = 0; + } + else + { + startIP = network + 1; + endIP = broadcast - 1; + } + } + catch (Exception) + { + //catch case where IP cannot be resolved such as when debugger is attached + startIP = 0; + endIP = 0; + } + } + + public static uint IP2Int(string ipNumber) + { + uint ip = 0; + string[] elements = ipNumber.Split(new[] { '.' }); + if (elements.Length == 4) + { + ip = Convert.ToUInt32(elements[0]) << 24; + ip += Convert.ToUInt32(elements[1]) << 16; + ip += Convert.ToUInt32(elements[2]) << 8; + ip += Convert.ToUInt32(elements[3]); + } + return ip; + } + + public static bool IsIPInRange(string currentIP, string startIP, string subnetmask) + { + try + { + //handle case where local adapter is localhost + if (currentIP=="::1") + { + currentIP = "127.0.0.1"; + } + + //handle case where we are matching on a single IP + if (String.IsNullOrEmpty(subnetmask)) if (currentIP == startIP) return true; + + //handle case where we have to build a CIDR, convert to an IP range and compare + string cidr = FormatAsCidr(startIP, subnetmask); + uint fromIP, toIP; + Network2IpRange(cidr, out fromIP, out toIP); + IPAddress currentIPAsInt = IPAddress.Parse(currentIP); + long myip = IPtoLong(currentIPAsInt); + if (myip >= fromIP & myip <= toIP) + { + return true; + } + } + catch (Exception) + { + //catch case where IP cannot be resolved such as when debugger is attached + return false; + } + return false; + } + } + + public enum AddressType + { + IPv4, + IPv6 + } + + +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/Null.cs b/DNN Platform/Library/Common/Utilities/Null.cs new file mode 100644 index 00000000000..5b7bd375ad8 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/Null.cs @@ -0,0 +1,408 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class Null + { + public static short NullShort + { + get + { + return -1; + } + } + + public static int NullInteger + { + get + { + return -1; + } + } + + public static byte NullByte + { + get + { + return 255; + } + } + + public static float NullSingle + { + get + { + return float.MinValue; + } + } + + public static double NullDouble + { + get + { + return double.MinValue; + } + } + + public static decimal NullDecimal + { + get + { + return decimal.MinValue; + } + } + + public static DateTime NullDate + { + get + { + return DateTime.MinValue; + } + } + + public static string NullString + { + get + { + return ""; + } + } + + public static bool NullBoolean + { + get + { + return false; + } + } + + public static Guid NullGuid + { + get + { + return Guid.Empty; + } + } + + //sets a field to an application encoded null value ( used in BLL layer ) + public static object SetNull(object objValue, object objField) + { + object returnValue = null; + if (objValue == DBNull.Value) + { + if (objField is short) + { + returnValue = NullShort; + } + else if (objField is byte) + { + returnValue = NullByte; + } + else if (objField is int) + { + returnValue = NullInteger; + } + else if (objField is float) + { + returnValue = NullSingle; + } + else if (objField is double) + { + returnValue = NullDouble; + } + else if (objField is decimal) + { + returnValue = NullDecimal; + } + else if (objField is DateTime) + { + returnValue = NullDate; + } + else if (objField is string) + { + returnValue = NullString; + } + else if (objField is bool) + { + returnValue = NullBoolean; + } + else if (objField is Guid) + { + returnValue = NullGuid; + } + else //complex object + { + returnValue = null; + } + } + else //return value + { + returnValue = objValue; + } + return returnValue; + } + + //sets a field to an application encoded null value ( used in BLL layer ) + public static object SetNull(PropertyInfo objPropertyInfo) + { + object returnValue = null; + switch (objPropertyInfo.PropertyType.ToString()) + { + case "System.Int16": + returnValue = NullShort; + break; + case "System.Int32": + case "System.Int64": + returnValue = NullInteger; + break; + case "system.Byte": + returnValue = NullByte; + break; + case "System.Single": + returnValue = NullSingle; + break; + case "System.Double": + returnValue = NullDouble; + break; + case "System.Decimal": + returnValue = NullDecimal; + break; + case "System.DateTime": + returnValue = NullDate; + break; + case "System.String": + case "System.Char": + returnValue = NullString; + break; + case "System.Boolean": + returnValue = NullBoolean; + break; + case "System.Guid": + returnValue = NullGuid; + break; + default: + //Enumerations default to the first entry + Type pType = objPropertyInfo.PropertyType; + if (pType.BaseType.Equals(typeof (Enum))) + { + Array objEnumValues = Enum.GetValues(pType); + Array.Sort(objEnumValues); + returnValue = Enum.ToObject(pType, objEnumValues.GetValue(0)); + } + else //complex object + { + returnValue = null; + } + break; + } + return returnValue; + } + + public static bool SetNullBoolean(object objValue) + { + return objValue != DBNull.Value ? Convert.ToBoolean(objValue) : NullBoolean; + } + + public static DateTime SetNullDateTime(object objValue) + { + return objValue != DBNull.Value ? Convert.ToDateTime(objValue) : NullDate; + } + + public static int SetNullInteger(object objValue) + { + return objValue != DBNull.Value ? Convert.ToInt32(objValue) : NullInteger; + } + + public static float SetNullSingle(object objValue) + { + return objValue != DBNull.Value ? Convert.ToSingle(objValue) : NullSingle; + } + + public static string SetNullString(object objValue) + { + return objValue != DBNull.Value ? Convert.ToString(objValue) : NullString; + } + + public static Guid SetNullGuid(object objValue) + { + if ((!(objValue == DBNull.Value)) && !string.IsNullOrEmpty(objValue.ToString())) + { + return new Guid(objValue.ToString()); + } + return Guid.Empty; + } + + //convert an application encoded null value to a database null value ( used in DAL ) + public static object GetNull(object objField, object objDBNull) + { + object returnValue = objField; + if (objField == null) + { + returnValue = objDBNull; + } + else if (objField is byte) + { + if (Convert.ToByte(objField) == NullByte) + { + returnValue = objDBNull; + } + } + else if (objField is short) + { + if (Convert.ToInt16(objField) == NullShort) + { + returnValue = objDBNull; + } + } + else if (objField is int) + { + if (Convert.ToInt32(objField) == NullInteger) + { + returnValue = objDBNull; + } + } + else if (objField is float) + { + if (Convert.ToSingle(objField) == NullSingle) + { + returnValue = objDBNull; + } + } + else if (objField is double) + { + if (Convert.ToDouble(objField) == NullDouble) + { + returnValue = objDBNull; + } + } + else if (objField is decimal) + { + if (Convert.ToDecimal(objField) == NullDecimal) + { + returnValue = objDBNull; + } + } + else if (objField is DateTime) + { + //compare the Date part of the DateTime with the DatePart of the NullDate ( this avoids subtle time differences ) + if (Convert.ToDateTime(objField).Date == NullDate.Date) + { + returnValue = objDBNull; + } + } + else if (objField is string) + { + if (objField == null) + { + returnValue = objDBNull; + } + else + { + if (objField.ToString() == NullString) + { + returnValue = objDBNull; + } + } + } + else if (objField is bool) + { + if (Convert.ToBoolean(objField) == NullBoolean) + { + returnValue = objDBNull; + } + } + else if (objField is Guid) + { + if (((Guid) objField).Equals(NullGuid)) + { + returnValue = objDBNull; + } + } + return returnValue; + } + + //checks if a field contains an application encoded null value + public static bool IsNull(object objField) + { + bool isNull = false; + if (objField != null) + { + if (objField is int) + { + isNull = objField.Equals(NullInteger); + } + else if (objField is short) + { + isNull = objField.Equals(NullShort); + } + else if (objField is byte) + { + isNull = objField.Equals(NullByte); + } + else if (objField is float) + { + isNull = objField.Equals(NullSingle); + } + else if (objField is double) + { + isNull = objField.Equals(NullDouble); + } + else if (objField is decimal) + { + isNull = objField.Equals(NullDecimal); + } + else if (objField is DateTime) + { + var objDate = (DateTime) objField; + isNull = objDate.Date.Equals(NullDate.Date); + } + else if (objField is string) + { + isNull = objField.Equals(NullString); + } + else if (objField is bool) + { + isNull = objField.Equals(NullBoolean); + } + else if (objField is Guid) + { + isNull = objField.Equals(NullGuid); + } + else //complex object + { + isNull = false; + } + } + else + { + isNull = true; + } + return isNull; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/ObjectMappingInfo.cs b/DNN Platform/Library/Common/Utilities/ObjectMappingInfo.cs new file mode 100644 index 00000000000..d31eee5a872 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/ObjectMappingInfo.cs @@ -0,0 +1,236 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Reflection; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Common.Utilities + /// Class: ObjectMappingInfo + /// ----------------------------------------------------------------------------- + /// + /// The ObjectMappingInfo class is a helper class that holds the mapping information + /// for a particular type. This information is in two parts: + /// - Information about the Database Table that the object is mapped to + /// - Information about how the object is cached. + /// For each object, when it is first accessed, reflection is used on the class and + /// an instance of ObjectMappingInfo is created, which is cached for performance. + /// + /// + /// [cnurse] 12/01/2007 created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ObjectMappingInfo + { + private const string RootCacheKey = "ObjectCache_"; + private readonly Dictionary _ColumnNames; + private readonly Dictionary _Properties; + private string _CacheByProperty; + private int _CacheTimeOutMultiplier; + private string _ObjectType; + private string _PrimaryKey; + private string _TableName; + + ///----------------------------------------------------------------------------- + /// + /// Constructs a new ObjectMappingInfo Object + /// + /// + /// [cnurse] 01/12/2008 created + /// + ///----------------------------------------------------------------------------- + public ObjectMappingInfo() + { + _Properties = new Dictionary(); + _ColumnNames = new Dictionary(); + } + + /// ----------------------------------------------------------------------------- + /// + /// CacheKey gets the root value of the key used to identify the cached collection + /// in the ASP.NET Cache. + /// + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string CacheKey + { + get + { + string _CacheKey = RootCacheKey + TableName + "_"; + if (!string.IsNullOrEmpty(CacheByProperty)) + { + _CacheKey += CacheByProperty + "_"; + } + return _CacheKey; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// CacheByProperty gets and sets the property that is used to cache collections + /// of the object. For example: Modules are cached by the "TabId" proeprty. Tabs + /// are cached by the PortalId property. + /// + /// If empty, a collection of all the instances of the object is cached. + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string CacheByProperty + { + get + { + return _CacheByProperty; + } + set + { + _CacheByProperty = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// CacheTimeOutMultiplier gets and sets the multiplier used to determine how long + /// the cached collection should be cached. It is multiplied by the Performance + /// Setting - which in turn can be modified by the Host Account. + /// + /// Defaults to 20. + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public int CacheTimeOutMultiplier + { + get + { + return _CacheTimeOutMultiplier; + } + set + { + _CacheTimeOutMultiplier = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ColumnNames gets a dictionary of Database Column Names for the Object + /// + /// + /// [cnurse] 12/02/2007 Created + /// + /// ----------------------------------------------------------------------------- + public Dictionary ColumnNames + { + get + { + return _ColumnNames; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ObjectType gets and sets the type of the object + /// + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string ObjectType + { + get + { + return _ObjectType; + } + set + { + _ObjectType = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// PrimaryKey gets and sets the property of the object that corresponds to the + /// primary key in the database + /// + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string PrimaryKey + { + get + { + return _PrimaryKey; + } + set + { + _PrimaryKey = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Properties gets a dictionary of Properties for the Object + /// + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Properties + { + get + { + return _Properties; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// TableName gets and sets the name of the database table that is used to + /// persist the object. + /// + /// + /// [cnurse] 12/01/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string TableName + { + get + { + return _TableName; + } + set + { + _TableName = value; + } + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/PathUtils.cs b/DNN Platform/Library/Common/Utilities/PathUtils.cs new file mode 100644 index 00000000000..becc83e1acb --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/PathUtils.cs @@ -0,0 +1,308 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem; + +namespace DotNetNuke.Common.Utilities +{ + public class PathUtils : ComponentBase, IPathUtils + { + #region Constructor + + internal PathUtils() + { + } + + #endregion + + #region Public Enums + + public enum UserFolderElement + { + Root = 0, + SubFolder = 1 + } + + #endregion + + #region Public Methods + + /// + /// Adds backslash to the specified source. + /// + /// The source string to be modified. + /// The original string plus a backslash. + public virtual string AddTrailingSlash(string source) + { + Requires.NotNull("source", source); + + return source.EndsWith("\\") ? source : source + "\\"; + } + + /// + /// Formats the provided folder path by adding a slash if needed. + /// + /// The folder path to format. + /// The formatted path. + public virtual string FormatFolderPath(string folderPath) + { + //Can not call trim on folderpath since folder passed in might have a legit space + //at the begingin of its name " MyFolder/Test" is not same physical folder as "MyFoler/Test" + if (String.IsNullOrEmpty(folderPath) || String.IsNullOrEmpty(folderPath.Trim())) + { + return ""; + } + + return folderPath.EndsWith("/") ? folderPath : folderPath + "/"; + } + + /// + /// Gets the physical path for the specified relative path. + /// + public virtual string GetPhysicalPath(int portalID, string relativePath) + { + Requires.NotNull("relativePath", relativePath); + + var path1 = GetRootFolderMapPath(portalID); + var path2 = relativePath.Replace("/", "\\"); + + if (Path.IsPathRooted(path2)) + { + path2 = path2.TrimStart(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }); + } + + var physicalPath = Path.Combine(path1, path2); + + return RemoveTrailingSlash(physicalPath); + } + + /// + /// Gets the relative path for the specified physical path. + /// + public virtual string GetRelativePath(int portalID, string physicalPath) + { + Requires.NotNull("physicalPath", physicalPath); + + if (!Directory.Exists(physicalPath)) + { + throw new ArgumentException("The argument 'physicalPath' is not a valid path. " + physicalPath); + } + + var rootFolderMapPath = RemoveTrailingSlash(GetRootFolderMapPath(portalID)); + + string relativePath; + + if (physicalPath.StartsWith(rootFolderMapPath, StringComparison.InvariantCultureIgnoreCase)) + { + relativePath = physicalPath.Substring(rootFolderMapPath.Length); + + if (Path.IsPathRooted(relativePath)) + { + relativePath = relativePath.TrimStart(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }); + } + + relativePath = relativePath.Replace("\\", "/"); + } + else + { + throw new ArgumentException("The argument 'physicalPath' is not a valid path."); + } + + return FormatFolderPath(relativePath); + } + + /// + /// Gets the physical root folder path for the specified portal + /// + public virtual string GetRootFolderMapPath(int portalID) + { + return (portalID == Null.NullInteger) ? GetHostMapPath() : GetPortalMapPath(portalID); + } + + /// + /// Gets the path to a user folder. + /// + /// The user info. + /// The path to a user folder. + public virtual string GetUserFolderPath(UserInfo user) + { + return FolderManager.Instance.GetUserFolder(user).FolderPath; + } + + /// + /// Get elements from the user folder path. + /// + /// The user identifier. + /// The UserFolderElement to get. + /// The element from the user folder path. + public virtual string GetUserFolderPathElement(int userID, UserFolderElement mode) + { + return GetUserFolderPathElementInternal(userID, mode); + } + + internal string GetUserFolderPathElementInternal(int userId, UserFolderElement mode) + { + const int subfolderSeedLength = 2; + const int byteOffset = 255; + var element = ""; + + switch (mode) + { + case UserFolderElement.Root: + element = (Convert.ToInt32(userId) & byteOffset).ToString("000"); + break; + case UserFolderElement.SubFolder: + element = userId.ToString("00").Substring(userId.ToString("00").Length - subfolderSeedLength, subfolderSeedLength); + break; + } + + return element; + } + + internal string GetUserFolderPathInternal(UserInfo user) + { + var rootFolder = GetUserFolderPathElementInternal(user.UserID, UserFolderElement.Root); + var subFolder = GetUserFolderPathElementInternal(user.UserID, UserFolderElement.SubFolder); + + var fullPath = Path.Combine(Path.Combine(rootFolder, subFolder), user.UserID.ToString(CultureInfo.InvariantCulture)); + + return String.Format("Users/{0}/", fullPath.Replace("\\", "/")); + } + + /// + /// Checks if a folder is a default protected folder. + /// + /// The folder path. + /// True if the folderPath is a default protected folder. False otherwise. + public virtual bool IsDefaultProtectedPath(string folderPath) + { + return String.IsNullOrEmpty(folderPath) || + folderPath.ToLower() == "skins" || + folderPath.ToLower() == "containers" || + folderPath.ToLower().StartsWith("skins/") || + folderPath.ToLower().StartsWith("containers/"); + } + + /// + /// The MapPath method maps the specified relative or virtual path to the corresponding physical directory on the server. + /// + /// Specifies the relative or virtual path to map to a physical directory. If Path starts with either + /// a forward (/) or backward slash (\), the MapPath method returns a path as if Path were a full, virtual path. If Path + /// doesn't start with a slash, the MapPath method returns a path relative to the directory of the .asp file being processed + /// + /// + /// If path is a null reference (Nothing in Visual Basic), then the MapPath method returns the full physical path + /// of the directory that contains the current application + /// + public virtual string MapPath(string path) + { + Requires.NotNull("path", path); + + var convertedPath = path; + + var applicationPath = Globals.ApplicationPath; + var applicationMapPath = Globals.ApplicationMapPath; + + if (applicationPath.Length > 1 && convertedPath.StartsWith(applicationPath)) + { + convertedPath = convertedPath.Substring(applicationPath.Length); + } + + convertedPath = convertedPath.Replace("/", "\\"); + + if (path.StartsWith("~") | path.StartsWith(".") | path.StartsWith("/")) + { + convertedPath = convertedPath.Length > 1 ? string.Concat(AddTrailingSlash(applicationMapPath), convertedPath.Substring(1)) : applicationMapPath; + } + + convertedPath = Path.GetFullPath(convertedPath); + + if (!convertedPath.StartsWith(applicationMapPath)) + { + throw new HttpException(); + } + + return convertedPath; + } + + /// + /// Removes the trailing slash or backslash from the specified source. + /// + /// The source string to be modified. + /// The original string minus the trailing slash. + public virtual string RemoveTrailingSlash(string source) + { + if (String.IsNullOrEmpty(source)) + { + return ""; + } + + if (source.EndsWith("\\") || source.EndsWith("/")) + { + return source.Substring(0, source.Length - 1); + } + + return source; + } + + /// + /// Strips the original path by removing starting 0 or 0\\. + /// + /// The original path. + /// The stripped path. + public virtual string StripFolderPath(string originalPath) + { + Requires.NotNull("originalPath", originalPath); + + if (originalPath.IndexOf("\\") != -1) + { + return Regex.Replace(originalPath, "^0\\\\", ""); + } + + return originalPath.StartsWith("0") ? originalPath.Substring(1) : originalPath; + } + + #endregion + + #region Private Methods + + private static string GetHostMapPath() + { + return Globals.HostMapPath; + } + + private static string GetPortalMapPath(int portalID) + { + var portalInfo = new PortalController().GetPortal(portalID); + return portalInfo.HomeDirectoryMapPath; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Common/Utilities/RetryableAction.cs b/DNN Platform/Library/Common/Utilities/RetryableAction.cs new file mode 100644 index 00000000000..9860743f4ae --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/RetryableAction.cs @@ -0,0 +1,133 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Threading; + +using DotNetNuke.Instrumentation; + +namespace DotNetNuke.Common.Utilities.Internal +{ + /// + /// Allows an action to be run and retried after a delay when an exception is thrown. + /// If the action never succeeds the final exception will be re-thrown for the caller to catch. + /// + public class RetryableAction + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (RetryableAction)); + /// + /// The Action to execute + /// + public Action Action { get; set; } + + /// + /// A message describing the action. The primary purpose is to make the action identifiable in the log output. + /// + public string Description { get; set; } + + /// + /// The maximum number of retries to attempt + /// + public int MaxRetries { get; set; } + + /// + /// The number of milliseconds to wait between retries. + /// The delay period is approximate and will be affected by the demands of other threads on the system. + /// + public TimeSpan Delay { get; set; } + + /// + /// A factor by which the delay is adjusted after each retry. Default is 1. + /// To double the delay with every retry use a factor of 2, retrys will be 1s, 2s, 4s, 8s... + /// To quarter the delay with every retry use a factor of 0.25, retrys will be 1s, 0.25, 0.0625, 0.015625s... + /// + public float DelayMultiplier { get; set; } + + public static void RetryEverySecondFor30Seconds(Action action, string description) + { + new RetryableAction(action, description, 30, TimeSpan.FromSeconds(1)).TryIt(); + } + + /// + /// Method that allows thread to sleep until next retry meant for unit testing purposes + /// + public static Action SleepAction { get; set; } + + static RetryableAction() + { + SleepAction = GoToSleep; + } + + private static void GoToSleep(int delay) + { + Thread.Sleep(delay); + } + + public RetryableAction(Action action, string description, int maxRetries, TimeSpan delay) : this(action, description, maxRetries, delay, 1) {} + + public RetryableAction(Action action, string description, int maxRetries, TimeSpan delay, float delayMultiplier) + { + if(delay.TotalMilliseconds > int.MaxValue) + { + throw new ArgumentException(string.Format("delay must be less than {0} milliseconds", int.MaxValue)); + } + + Action = action; + Description = description; + MaxRetries = maxRetries; + Delay = delay; + DelayMultiplier = delayMultiplier; + } + + public void TryIt() + { + var currentDelay = (int) Delay.TotalMilliseconds; + int retrysRemaining = MaxRetries; + + do + { + try + { + Action(); + Logger.TraceFormat("Action succeeded - {0}", Description); + return; + } + catch(Exception) + { + if (retrysRemaining <= 0) + { + Logger.WarnFormat("All retries of action failed - {0}", Description); + throw; + } + + Logger.TraceFormat("Retrying action {0} - {1}", retrysRemaining, Description); + SleepAction.Invoke(currentDelay); + + const double epsilon = 0.0001; + if(Math.Abs(DelayMultiplier - 1) > epsilon) + { + currentDelay = (int)(currentDelay * DelayMultiplier); + } + } + retrysRemaining--; + } while (true); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/SessionVariable.cs b/DNN Platform/Library/Common/Utilities/SessionVariable.cs new file mode 100644 index 00000000000..74ef3c5c056 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/SessionVariable.cs @@ -0,0 +1,72 @@ +using System; +using System.Web; +using System.Web.SessionState; + +namespace DotNetNuke.Common.Utilities +{ + + /// + /// Wrapper class for + /// + /// The type of the value to be stored + public class SessionVariable : StateVariable + { + + /// + /// Initializes a new HttpContext.Session item variable + /// + /// + /// The key to use for storing the value in the items + /// + public SessionVariable(string key) : base(key) + { + } + + /// + /// Initializes a new HttpContext.Session item variable with a initializer + /// + /// The key to use for storing the value in the HttpContext.Current.Session + /// A function that is called in order to create a default value per HttpContext.Current.Session + /// + public SessionVariable(string key, Func initializer) : base(key, initializer) + { + } + + private static HttpSessionState CurrentItems + { + get + { + var current = HttpContext.Current; + if (current == null) + { + throw new InvalidOperationException("No HttpContext is not available."); + } + var items = current.Session; + if (items == null) + { + throw new InvalidOperationException("No Session State available on current HttpContext."); + } + return items; + } + } + + protected override object this[string key] + { + get + { + return CurrentItems[key]; + } + set + { + CurrentItems[key] = value; + } + } + + protected override void Remove(string key) + { + CurrentItems.Remove(key); + } + + } + +} diff --git a/DNN Platform/Library/Common/Utilities/SqlUtils.cs b/DNN Platform/Library/Common/Utilities/SqlUtils.cs new file mode 100644 index 00000000000..a755bad1062 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/SqlUtils.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Data.SqlClient; +using System.Text; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// + /// The SqlUtils class provides Shared/Static methods for working with SQL Server related code + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class SqlUtils + { + #region "Public Methods" + + #endregion + + /// + /// function to translate sql exceptions to readable messages. + /// It also captures cases where sql server is not available and guards against + /// database connection details being leaked + /// + /// + /// + /// + /// + public static string TranslateSQLException(SqlException exc) + { + int i = 0; + var errorMessages = new StringBuilder(); + for (i = 0; i <= exc.Errors.Count - 1; i++) + { + SqlError sqlError = exc.Errors[i]; + string filteredMessage = string.Empty; + switch (sqlError.Number) + { + case 17: + filteredMessage = "Sql server does not exist or access denied"; + break; + case 4060: + filteredMessage = "Invalid Database"; + break; + case 18456: + filteredMessage = "Sql login failed"; + break; + case 1205: + filteredMessage = "Sql deadlock victim"; + break; + default: + filteredMessage = exc.ToString(); + break; + } + + errorMessages.Append("Index #: " + i + "
" + "Source: " + sqlError.Source + "
" + "Class: " + sqlError.Class + "
" + "Number: " + + sqlError.Number + "
" + "Procedure: " + sqlError.Procedure + "
" + "Message: " + filteredMessage + "
"); + } + return errorMessages.ToString(); + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/StateVariable.cs b/DNN Platform/Library/Common/Utilities/StateVariable.cs new file mode 100644 index 00000000000..2d506b6b2cb --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/StateVariable.cs @@ -0,0 +1,134 @@ +using System; + +namespace DotNetNuke.Common.Utilities +{ + + /// + /// Wrapper class for any object that maps string key onto the object value (like Dictionary). + /// + /// + /// + public abstract class StateVariable + { + + private readonly string _key; + private readonly Func _initializer; + + /// + /// Initializes a new item variable + /// + /// + /// The key to use for storing the value in the items + /// + protected StateVariable(string key) + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentNullException("key"); + } + _key = key + GetType().FullName; + } + + /// + /// Initializes a new item variable with a initializer + /// + /// The key to use for storing the value in the dictionary + /// A function that is called in order to create a default value per dictionary + /// + protected StateVariable(string key, Func initializer) : this(key) + { + if (initializer == null) + { + throw new ArgumentNullException("initializer"); + } + this._initializer = initializer; + } + + private object GetInitializedInternalValue() + { + var value = this[_key]; + if (value == null && _initializer != null) + { + value = _initializer(); + this[_key] = value; + } + return value; + } + + /// + /// Get/sets the value in associated dictionary/map + /// + /// Value key + /// + /// + /// + protected abstract object this[string key] { get; set; } + + /// + /// Removes the value in associated dictionary according + /// + /// Value key + /// + protected abstract void Remove(string key); + + /// + /// Indicates wether there is a value present or not + /// + public bool HasValue + { + get + { + return this[_key] != null; + } + } + + /// + /// Sets or gets the value in the current items + /// + /// + /// If you try to get a value while none is set use for safe access + /// + public T Value + { + get + { + var returnedValue = GetInitializedInternalValue(); + if (returnedValue == null) + { + throw new InvalidOperationException("There is no value for the '" + _key + "' key."); + } + return (T)returnedValue; + } + set + { + this[_key] = value; + } + } + + /// + /// Gets the value in the current items or if none is available default(T) + /// + public T ValueOrDefault + { + get + { + var returnedValue = GetInitializedInternalValue(); + if (returnedValue == null) + { + return default(T); + } + return (T)returnedValue; + } + } + + /// + /// Clears the value in the current items + /// + public void Clear() + { + Remove(_key); + } + + } + +} diff --git a/DNN Platform/Library/Common/Utilities/StringExtensions.cs b/DNN Platform/Library/Common/Utilities/StringExtensions.cs new file mode 100644 index 00000000000..91d0fcb40e7 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/StringExtensions.cs @@ -0,0 +1,28 @@ +using System; + +namespace DotNetNuke.Common.Utilities +{ + public static class StringExtensions + { + + public static string Append(this string stringValue, string stringToLink, string delimiter) + { + if (string.IsNullOrEmpty(stringValue)) + { + return stringToLink; + } + if (string.IsNullOrEmpty(stringToLink)) + { + return stringValue; + } + return stringValue + delimiter + stringToLink; + } + + public static string ValueOrEmpty(this string stringValue) + { + return stringValue ?? string.Empty; + } + + } + +} diff --git a/DNN Platform/Library/Common/Utilities/UrlController.cs b/DNN Platform/Library/Common/Utilities/UrlController.cs new file mode 100644 index 00000000000..bf51a9572f0 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/UrlController.cs @@ -0,0 +1,132 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; + +using DotNetNuke.Data; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem; + +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class UrlController + { + public ArrayList GetUrls(int PortalID) + { + return CBO.FillCollection(DataProvider.Instance().GetUrls(PortalID), typeof (UrlInfo)); + } + + public UrlInfo GetUrl(int PortalID, string Url) + { + return (UrlInfo) CBO.FillObject(DataProvider.Instance().GetUrl(PortalID, Url), typeof (UrlInfo)); + } + + public UrlTrackingInfo GetUrlTracking(int PortalID, string Url, int ModuleId) + { + return (UrlTrackingInfo) CBO.FillObject(DataProvider.Instance().GetUrlTracking(PortalID, Url, ModuleId), typeof (UrlTrackingInfo)); + } + + public void UpdateUrl(int PortalID, string Url, string UrlType, bool LogActivity, bool TrackClicks, int ModuleID, bool NewWindow) + { + UpdateUrl(PortalID, Url, UrlType, 0, Null.NullDate, Null.NullDate, LogActivity, TrackClicks, ModuleID, NewWindow); + } + + public void UpdateUrl(int PortalID, string Url, string UrlType, int Clicks, DateTime LastClick, DateTime CreatedDate, bool LogActivity, bool TrackClicks, int ModuleID, bool NewWindow) + { + if (!String.IsNullOrEmpty(Url)) + { + if (UrlType == "U") + { + if (GetUrl(PortalID, Url) == null) + { + DataProvider.Instance().AddUrl(PortalID, Url); + } + } + UrlTrackingInfo objURLTracking = GetUrlTracking(PortalID, Url, ModuleID); + if (objURLTracking == null) + { + DataProvider.Instance().AddUrlTracking(PortalID, Url, UrlType, LogActivity, TrackClicks, ModuleID, NewWindow); + } + else + { + DataProvider.Instance().UpdateUrlTracking(PortalID, Url, LogActivity, TrackClicks, ModuleID, NewWindow); + } + } + } + + public void DeleteUrl(int PortalID, string Url) + { + DataProvider.Instance().DeleteUrl(PortalID, Url); + } + + public void UpdateUrlTracking(int PortalID, string Url, int ModuleId, int UserID) + { + TabType UrlType = Globals.GetURLType(Url); + if (UrlType == TabType.File && Url.ToLower().StartsWith("fileid=") == false) + { + //to handle legacy scenarios before the introduction of the FileServerHandler + var fileName = Path.GetFileName(Url); + + var folderPath = Url.Substring(0, Url.LastIndexOf(fileName)); + var folder = FolderManager.Instance.GetFolder(PortalID, folderPath); + + var file = FileManager.Instance.GetFile(folder, fileName); + + Url = "FileID=" + file.FileId; + } + UrlTrackingInfo objUrlTracking = GetUrlTracking(PortalID, Url, ModuleId); + if (objUrlTracking != null) + { + if (objUrlTracking.TrackClicks) + { + DataProvider.Instance().UpdateUrlTrackingStats(PortalID, Url, ModuleId); + if (objUrlTracking.LogActivity) + { + if (UserID == -1) + { + UserID = UserController.GetCurrentUserInfo().UserID; + } + DataProvider.Instance().AddUrlLog(objUrlTracking.UrlTrackingID, UserID); + } + } + } + } + + public ArrayList GetUrlLog(int PortalID, string Url, int ModuleId, DateTime StartDate, DateTime EndDate) + { + ArrayList arrUrlLog = null; + UrlTrackingInfo objUrlTracking = GetUrlTracking(PortalID, Url, ModuleId); + if (objUrlTracking != null) + { + arrUrlLog = CBO.FillCollection(DataProvider.Instance().GetUrlLog(objUrlTracking.UrlTrackingID, StartDate, EndDate), typeof (UrlLogInfo)); + } + return arrUrlLog; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/UrlInfo.cs b/DNN Platform/Library/Common/Utilities/UrlInfo.cs new file mode 100644 index 00000000000..16bf8eb898c --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/UrlInfo.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Common.Utilities +{ + public class UrlInfo + { + public int UrlID { get; set; } + + public int PortalID { get; set; } + + public string Url { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/UrlLogInfo.cs b/DNN Platform/Library/Common/Utilities/UrlLogInfo.cs new file mode 100644 index 00000000000..1ef564e0a07 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/UrlLogInfo.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class UrlLogInfo + { + public int UrlLogID { get; set; } + + public int UrlTrackingID { get; set; } + + public DateTime ClickDate { get; set; } + + public int UserID { get; set; } + + public string FullName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/UrlTrackingInfo.cs b/DNN Platform/Library/Common/Utilities/UrlTrackingInfo.cs new file mode 100644 index 00000000000..aa564c91af2 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/UrlTrackingInfo.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class UrlTrackingInfo + { + public int UrlTrackingID { get; set; } + + public int PortalID { get; set; } + + public string Url { get; set; } + + public string UrlType { get; set; } + + public int Clicks { get; set; } + + public DateTime LastClick { get; set; } + + public DateTime CreatedDate { get; set; } + + public bool LogActivity { get; set; } + + public bool TrackClicks { get; set; } + + public int ModuleID { get; set; } + + public bool NewWindow { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/Utilities/UrlUtils.cs b/DNN Platform/Library/Common/Utilities/UrlUtils.cs new file mode 100644 index 00000000000..e6d42396dcd --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/UrlUtils.cs @@ -0,0 +1,311 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; + +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security; +using DotNetNuke.UI; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + public class UrlUtils + { + public static string Combine(string baseUrl, string relativeUrl) + { + if (baseUrl.Length == 0) + return relativeUrl; + if (relativeUrl.Length == 0) + return baseUrl; + return string.Format("{0}/{1}", baseUrl.TrimEnd(new[] { '/', '\\' }), relativeUrl.TrimStart(new[] { '/', '\\' })); + } + + public static string DecodeParameter(string value) + { + value = value.Replace("-", "+").Replace("_", "/").Replace("$", "="); + byte[] arrBytes = Convert.FromBase64String(value); + return Encoding.UTF8.GetString(arrBytes); + } + + public static string DecryptParameter(string value) + { + return DecryptParameter(value, PortalController.GetCurrentPortalSettings().GUID.ToString()); + } + + public static string DecryptParameter(string value, string encryptionKey) + { + var objSecurity = new PortalSecurity(); + //[DNN-8257] - Can't do URLEncode/URLDecode as it introduces issues on decryption (with / = %2f), so we use a modifed Base64 + value = value.Replace("_", "/"); + value = value.Replace("-", "+"); + value = value.Replace("%3d", "="); + return objSecurity.Decrypt(encryptionKey, value); + } + + public static string EncodeParameter(string value) + { + byte[] arrBytes = Encoding.UTF8.GetBytes(value); + value = Convert.ToBase64String(arrBytes); + value = value.Replace("+", "-").Replace("/", "_").Replace("=", "$"); + return value; + } + + public static string EncryptParameter(string value) + { + return EncryptParameter(value, PortalController.GetCurrentPortalSettings().GUID.ToString()); + } + + public static string EncryptParameter(string value, string encryptionKey) + { + var objSecurity = new PortalSecurity(); + string strParameter = objSecurity.Encrypt(encryptionKey, value); + + //[DNN-8257] - Can't do URLEncode/URLDecode as it introduces issues on decryption (with / = %2f), so we use a modifed Base64 + strParameter = strParameter.Replace("/", "_"); + strParameter = strParameter.Replace("+", "-"); + strParameter = strParameter.Replace("=", "%3d"); + return strParameter; + } + + public static string GetParameterName(string pair) + { + string[] nameValues = pair.Split('='); + return nameValues[0]; + } + + public static string GetParameterValue(string pair) + { + string[] nameValues = pair.Split('='); + if (nameValues.Length > 1) + { + return nameValues[1]; + } + return ""; + } + + /// + /// getQSParamsForNavigateURL builds up a new querystring. This is necessary + /// in order to prep for navigateUrl. + /// we don't ever want a tabid, a ctl and a language parameter in the qs + /// either, the portalid param is not allowed when the tab is a supertab + /// (because NavigateUrl adds the portalId param to the qs) + /// + /// + /// [erikvb] 20070814 added + /// + public static string[] GetQSParamsForNavigateURL() + { + string returnValue = ""; + var coll = HttpContext.Current.Request.QueryString; + string[] keys = coll.AllKeys; + for (var i = 0; i <= keys.GetUpperBound(0); i++) + { + if (keys[i] != null) + { + switch (keys[i].ToLower()) + { + case "tabid": + case "ctl": + case "language": + //skip parameter + break; + default: + if ((keys[i].ToLower() == "portalid") && Globals.GetPortalSettings().ActiveTab.IsSuperTab) + { + //skip parameter + //navigateURL adds portalid to querystring if tab is superTab + + } + else + { + string[] values = coll.GetValues(i); + for (int j = 0; j <= values.GetUpperBound(0); j++) + { + if (!String.IsNullOrEmpty(returnValue)) + { + returnValue += "&"; + } + returnValue += keys[i] + "=" + values[j]; + } + } + break; + } + } + } + //return the new querystring as a string array + return returnValue.Split('&'); + + } + + /// + /// check if connection is HTTPS + /// or is HTTP but with ssloffload enabled on a secure page + /// + /// current request + /// true if HTTPS or if HTTP with an SSL offload header value, false otherwise + public static bool IsSecureConnectionOrSslOffload(HttpRequest request) + { + if (request.IsSecureConnection) + { + return true; + } + string ssloffloadheader = HostController.Instance.GetString("SSLOffloadHeader", ""); + //if the ssloffloadheader variable has been set check to see if a request header with that type exists + if (!string.IsNullOrEmpty(ssloffloadheader)) + { + string ssloffload = request.Headers[ssloffloadheader]; + if (!string.IsNullOrEmpty(ssloffload)) + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings.ActiveTab.IsSecure) + { + return true; + } + } + } + return false; + } + + public static void OpenNewWindow(Page page, Type type, string url) + { + page.ClientScript.RegisterStartupScript(type, "DotNetNuke.NewWindow", string.Format("", url)); + } + + public static string PopUpUrl(string url, Control control, PortalSettings portalSettings, bool onClickEvent, bool responseRedirect) + { + return PopUpUrl(url, control, portalSettings, onClickEvent, responseRedirect, 550, 950); + } + + public static string PopUpUrl(string url, Control control, PortalSettings portalSettings, bool onClickEvent, bool responseRedirect, int windowHeight, int windowWidth) + { + return PopUpUrl(url, control, portalSettings, onClickEvent, responseRedirect, windowHeight, windowWidth, true, string.Empty); + } + + public static string PopUpUrl(string url, PortalSettings portalSettings, bool onClickEvent, bool responseRedirect, int windowHeight, int windowWidth) + { + return PopUpUrl(url, null, portalSettings, onClickEvent, responseRedirect, windowHeight, windowWidth, true, string.Empty); + } + + public static string PopUpUrl(string url, Control control, PortalSettings portalSettings, bool onClickEvent, bool responseRedirect, int windowHeight, int windowWidth, bool refresh, string closingUrl) + { + var popUpUrl = url; + //ensure delimiters are not used + if (!popUpUrl.Contains("dnnModal.show")) + { + popUpUrl = Uri.EscapeUriString(url); + popUpUrl = popUpUrl.Replace("\"", ""); + popUpUrl = popUpUrl.Replace("'", ""); + } + + var delimiter = popUpUrl.Contains("?") ? "&" : "?"; + var popUpScriptFormat = String.Empty; + + //create a the querystring for use on a Response.Redirect + if (responseRedirect) + { + popUpScriptFormat = "{0}{1}popUp=true"; + popUpUrl = String.Format(popUpScriptFormat, popUpUrl, delimiter); + } + else + { + if (!popUpUrl.Contains("dnnModal.show")) + { + popUpScriptFormat = "dnnModal.show('{0}{1}popUp=true',/*showReturn*/{2},{3},{4},{5},'{6}')"; + closingUrl = (closingUrl != Null.NullString) ? closingUrl : String.Empty; + popUpUrl = "javascript:" + String.Format(popUpScriptFormat, popUpUrl, delimiter, onClickEvent.ToString().ToLower(), windowHeight, windowWidth, refresh.ToString().ToLower(), closingUrl); + } + else + { + //Determines if the resulting JS call should return or not. + if (popUpUrl.Contains("/*showReturn*/false")) + { + popUpUrl = popUpUrl.Replace("/*showReturn*/false", "/*showReturn*/" + onClickEvent.ToString().ToLower()); + } + else + { + popUpUrl = popUpUrl.Replace("/*showReturn*/true", "/*showReturn*/" + onClickEvent.ToString().ToLower()); + } + } + } + + // Removes the javascript txt for onClick scripts + if (onClickEvent && popUpUrl.StartsWith("javascript:")) popUpUrl = popUpUrl.Replace("javascript:", ""); + + return popUpUrl; + } + + public static string ClosePopUp(Boolean refresh, string url, bool onClickEvent) + { + var closePopUpStr = "dnnModal.closePopUp({0}, {1})"; + closePopUpStr = "javascript:" + string.Format(closePopUpStr, refresh.ToString().ToLower(), "'" + url + "'"); + + // Removes the javascript txt for onClick scripts) + if (onClickEvent && closePopUpStr.StartsWith("javascript:")) closePopUpStr = closePopUpStr.Replace("javascript:", ""); + + return closePopUpStr; + } + + public static string ReplaceQSParam(string url, string param, string newValue) + { + if (Host.UseFriendlyUrls) + { + return Regex.Replace(url, "(.*)(" + param + "/)([^/]+)(/.*)", "$1$2" + newValue + "$4", RegexOptions.IgnoreCase); + } + else + { + return Regex.Replace(url, "(.*)(&|\\?)(" + param + "=)([^&\\?]+)(.*)", "$1$2$3" + newValue + "$5", RegexOptions.IgnoreCase); + } + } + + public static string StripQSParam(string url, string param) + { + if (Host.UseFriendlyUrls) + { + return Regex.Replace(url, "(.*)(" + param + "/[^/]+/)(.*)", "$1$3", RegexOptions.IgnoreCase); + } + else + { + return Regex.Replace(url, "(.*)(&|\\?)(" + param + "=)([^&\\?]+)([&\\?])?(.*)", "$1$2$6", RegexOptions.IgnoreCase).Replace("(.*)([&\\?]$)", "$1"); + } + } + + public static string ValidReturnUrl(string url) + { + //redirect url should never contain a protocol ( if it does, it is likely a cross-site request forgery attempt ) + if (url != null && url.Contains("://")) + { + url = ""; + } + return url; + } + } +} diff --git a/DNN Platform/Library/Common/Utilities/XmlUtils.cs b/DNN Platform/Library/Common/Utilities/XmlUtils.cs new file mode 100644 index 00000000000..879fba30e65 --- /dev/null +++ b/DNN Platform/Library/Common/Utilities/XmlUtils.cs @@ -0,0 +1,737 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using System.Xml.XPath; +using System.Xml.Xsl; + +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Common.Utilities +{ + /// ----------------------------------------------------------------------------- + /// + /// The XmlUtils class provides Shared/Static methods for manipulating xml files + /// + /// + /// + /// + /// [cnurse] 11/08/2004 created + /// + /// ----------------------------------------------------------------------------- + public class XmlUtils + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (XmlUtils)); + public static void AppendElement(ref XmlDocument objDoc, XmlNode objNode, string attName, string attValue, bool includeIfEmpty) + { + AppendElement(ref objDoc, objNode, attName, attValue, includeIfEmpty, false); + } + + public static void AppendElement(ref XmlDocument objDoc, XmlNode objNode, string attName, string attValue, bool includeIfEmpty, bool cdata) + { + if (String.IsNullOrEmpty(attValue) && !includeIfEmpty) + { + return; + } + if (cdata) + { + objNode.AppendChild(CreateCDataElement(objDoc, attName, attValue)); + } + else + { + objNode.AppendChild(CreateElement(objDoc, attName, attValue)); + } + } + + public static XmlAttribute CreateAttribute(XmlDocument objDoc, string attName, string attValue) + { + XmlAttribute attribute = objDoc.CreateAttribute(attName); + attribute.Value = attValue; + return attribute; + } + + public static void CreateAttribute(XmlDocument objDoc, XmlNode objNode, string attName, string attValue) + { + XmlAttribute attribute = objDoc.CreateAttribute(attName); + attribute.Value = attValue; + objNode.Attributes.Append(attribute); + } + + [Obsolete("Removed in DotNetNuke 5.5")] + public static XmlElement CreateElement(XmlDocument document, string nodeName) + { + return document.CreateElement(nodeName); + } + + public static XmlElement CreateElement(XmlDocument document, string nodeName, string nodeValue) + { + XmlElement element = document.CreateElement(nodeName); + element.InnerText = nodeValue; + return element; + } + + public static XmlElement CreateCDataElement(XmlDocument document, string nodeName, string nodeValue) + { + XmlElement element = document.CreateElement(nodeName); + element.AppendChild(document.CreateCDataSection(nodeValue)); + return element; + } + + [Obsolete("Replaced in DotNetNuke 5.5 with CBO.DeserializeObject")] + public static object Deserialize(string xmlObject, Type type) + { + var ser = new XmlSerializer(type); + var sr = new StringReader(xmlObject); + object obj = ser.Deserialize(sr); + sr.Close(); + return obj; + } + + public static object Deserialize(Stream objStream, Type type) + { + object obj = Activator.CreateInstance(type); + var tabDic = obj as Dictionary; + if (tabDic != null) + { + obj = DeSerializeDictionary(objStream, "dictionary"); + return obj; + } + var moduleDic = obj as Dictionary; + if (moduleDic != null) + { + obj = DeSerializeDictionary(objStream, "dictionary"); + return obj; + } + var tabPermDic = obj as Dictionary; + if (tabPermDic != null) + { + obj = DeSerializeDictionary(objStream, "dictionary"); + return obj; + } + var modPermDic = obj as Dictionary; + if (modPermDic != null) + { + obj = DeSerializeDictionary(objStream, "dictionary"); + return obj; + } + var serializer = new XmlSerializer(type); + TextReader tr = new StreamReader(objStream); + obj = serializer.Deserialize(tr); + tr.Close(); + return obj; + } + + public static Dictionary DeSerializeDictionary(Stream objStream, string rootname) + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(objStream); + + var objDictionary = new Dictionary(); + + foreach (XmlElement xmlItem in xmlDoc.SelectNodes(rootname + "/item")) + { + int key = Convert.ToInt32(xmlItem.GetAttribute("key")); + + var objValue = Activator.CreateInstance(); + + //Create the XmlSerializer + var xser = new XmlSerializer(objValue.GetType()); + + //A reader is needed to read the XML document. + var reader = new XmlTextReader(new StringReader(xmlItem.InnerXml)); + + //Use the Deserialize method to restore the object's state, and store it + //in the Hashtable + objDictionary.Add(key, (TValue)xser.Deserialize(reader)); + } + return objDictionary; + } + + public static Hashtable DeSerializeHashtable(string xmlSource, string rootname) + { + var hashTable = new Hashtable(); + + if (!String.IsNullOrEmpty(xmlSource)) + { + try + { + var xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlSource); + + foreach (XmlElement xmlItem in xmlDoc.SelectNodes(rootname + "/item")) + { + string key = xmlItem.GetAttribute("key"); + string typeName = xmlItem.GetAttribute("type"); + + //Create the XmlSerializer + var xser = new XmlSerializer(Type.GetType(typeName)); + + //A reader is needed to read the XML document. + var reader = new XmlTextReader(new StringReader(xmlItem.InnerXml)); + + //Use the Deserialize method to restore the object's state, and store it + //in the Hashtable + hashTable.Add(key, xser.Deserialize(reader)); + } + } + catch (Exception) + { + //Logger.Error(ex); /*Ignore Log because if failed on profile this will log on every request.*/ + } + } + + return hashTable; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of an attribute + /// + /// Parent XPathNavigator + /// Thename of the Attribute + /// + /// + /// [cnurse] 05/14/2008 created + /// + /// ----------------------------------------------------------------------------- + public static string GetAttributeValue(XPathNavigator nav, string attributeName) + { + return nav.GetAttribute(attributeName, ""); + } + + public static bool GetAttributeValueAsBoolean(XPathNavigator navigator, string attributeName, bool defaultValue) + { + bool boolValue = defaultValue; + string strValue = GetAttributeValue(navigator, attributeName); + if (!string.IsNullOrEmpty(strValue)) + { + boolValue = Convert.ToBoolean(strValue); + } + return boolValue; + } + + public static int GetAttributeValueAsInteger(XPathNavigator navigator, string attributeName, int defaultValue) + { + int intValue = defaultValue; + string strValue = GetAttributeValue(navigator, attributeName); + if (!string.IsNullOrEmpty(strValue)) + { + intValue = Convert.ToInt32(strValue); + } + return intValue; + } + + public static long GetAttributeValueAsLong(XPathNavigator navigator, string attributeName, long defaultValue) + { + long intValue = defaultValue; + + string strValue = GetAttributeValue(navigator, attributeName); + if (!string.IsNullOrEmpty(strValue)) + { + intValue = Convert.ToInt64(strValue); + } + + return intValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of a node + /// + /// Parent XPathNavigator + /// The Xpath expression to the value + /// + /// + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static string GetNodeValue(XPathNavigator navigator, string path) + { + string strValue = Null.NullString; + XPathNavigator elementNav = navigator.SelectSingleNode(path); + if (elementNav != null) + { + strValue = elementNav.Value; + } + return strValue; + } + + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + public static string GetNodeValue(XmlNode objNode, string nodeName) + { + return GetNodeValue(objNode, nodeName, String.Empty); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// Default value to return + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Created + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static string GetNodeValue(XmlNode objNode, string nodeName, string defaultValue) + { + string strValue = defaultValue; + if ((objNode[nodeName] != null)) + { + strValue = objNode[nodeName].InnerText; + if (String.IsNullOrEmpty(strValue) && !String.IsNullOrEmpty(defaultValue)) + { + strValue = defaultValue; + } + } + return strValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// + /// + /// If the node does not exist or it causes any error the default value (False) will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static bool GetNodeValueBoolean(XmlNode objNode, string nodeName) + { + return GetNodeValueBoolean(objNode, nodeName, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// Default value to return + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static bool GetNodeValueBoolean(XmlNode objNode, string nodeName, bool defaultValue) + { + bool bValue = defaultValue; + if ((objNode[nodeName] != null)) + { + string strValue = objNode[nodeName].InnerText; + if (!string.IsNullOrEmpty(strValue)) + { + bValue = Convert.ToBoolean(strValue); + } + } + return bValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// Default value to return + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static DateTime GetNodeValueDate(XmlNode objNode, string nodeName, DateTime defaultValue) + { + DateTime dateValue = defaultValue; + if ((objNode[nodeName] != null)) + { + string strValue = objNode[nodeName].InnerText; + if (!string.IsNullOrEmpty(strValue)) + { + dateValue = Convert.ToDateTime(strValue); + if (dateValue.Date.Equals(Null.NullDate.Date)) + { + dateValue = Null.NullDate; + } + } + } + return dateValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// + /// + /// If the node does not exist or it causes any error the default value (0) will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static int GetNodeValueInt(XmlNode node, string nodeName) + { + return GetNodeValueInt(node, nodeName, 0); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// Default value to return + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static int GetNodeValueInt(XmlNode node, string nodeName, int defaultValue) + { + int intValue = defaultValue; + if ((node[nodeName] != null)) + { + string strValue = node[nodeName].InnerText; + if (!string.IsNullOrEmpty(strValue)) + { + intValue = Convert.ToInt32(strValue); + } + } + return intValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// + /// + /// If the node does not exist or it causes any error the default value (0) will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static float GetNodeValueSingle(XmlNode node, string nodeName) + { + return GetNodeValueSingle(node, nodeName, 0); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the value of node + /// + /// Parent node + /// Child node to look for + /// Default value to return + /// + /// + /// If the node does not exist or it causes any error the default value will be returned. + /// + /// + /// [VMasanas] 09/09/2004 Added new method to return converted values + /// [cnurse] 11/08/2004 moved from PortalController and made Public Shared + /// + /// ----------------------------------------------------------------------------- + public static float GetNodeValueSingle(XmlNode node, string nodeName, float defaultValue) + { + float sValue = defaultValue; + if ((node[nodeName] != null)) + { + string strValue = node[nodeName].InnerText; + if (!string.IsNullOrEmpty(strValue)) + { + sValue = Convert.ToSingle(strValue, CultureInfo.InvariantCulture); + } + } + return sValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlWriterSettings object + /// + /// Conformance Level + /// An XmlWriterSettings + /// + /// [cnurse] 08/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static XmlWriterSettings GetXmlWriterSettings(ConformanceLevel conformance) + { + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = conformance; + settings.OmitXmlDeclaration = true; + settings.Indent = true; + return settings; + } + + public static string SerializeDictionary(IDictionary source, string rootName) + { + string strString; + if (source.Count != 0) + { + XmlSerializer xser; + StringWriter sw; + + var xmlDoc = new XmlDocument(); + XmlElement xmlRoot = xmlDoc.CreateElement(rootName); + xmlDoc.AppendChild(xmlRoot); + + foreach (var key in source.Keys) + { + //Create the item Node + XmlElement xmlItem = xmlDoc.CreateElement("item"); + + //Save the key name and the object type + xmlItem.SetAttribute("key", Convert.ToString(key)); + xmlItem.SetAttribute("type", source[key].GetType().AssemblyQualifiedName); + + //Serialize the object + var xmlObject = new XmlDocument(); + xser = new XmlSerializer(source[key].GetType()); + sw = new StringWriter(); + xser.Serialize(sw, source[key]); + xmlObject.LoadXml(sw.ToString()); + + //import and append the node to the root + xmlItem.AppendChild(xmlDoc.ImportNode(xmlObject.DocumentElement, true)); + xmlRoot.AppendChild(xmlItem); + } + //Return the OuterXml of the profile + strString = xmlDoc.OuterXml; + } + else + { + strString = ""; + } + return strString; + } + + public static void SerializeHashtable(Hashtable hashtable, XmlDocument xmlDocument, XmlNode rootNode, string elementName, string keyField, string valueField) + { + XmlNode nodeSetting; + XmlNode nodeSettingName; + XmlNode nodeSettingValue; + + string outerElementName = elementName + "s"; + string innerElementName = elementName; + + XmlNode nodeSettings = rootNode.AppendChild(xmlDocument.CreateElement(outerElementName)); + foreach (string key in hashtable.Keys) + { + nodeSetting = nodeSettings.AppendChild(xmlDocument.CreateElement(innerElementName)); + nodeSettingName = nodeSetting.AppendChild(xmlDocument.CreateElement(keyField)); + nodeSettingName.InnerText = key; + nodeSettingValue = nodeSetting.AppendChild(xmlDocument.CreateElement(valueField)); + nodeSettingValue.InnerText = hashtable[key].ToString(); + } + } + + + public static void UpdateAttribute(XmlNode node, string attName, string attValue) + { + if ((node != null)) + { + XmlAttribute attrib = node.Attributes[attName]; + attrib.InnerText = attValue; + } + } + + ///----------------------------------------------------------------------------- + /// + /// Xml Encodes HTML + /// + ///The HTML to encode + /// + /// + /// [cnurse] 09/29/2005 moved from Globals + /// + ///----------------------------------------------------------------------------- + public static string XMLEncode(string html) + { + return ""; + } + + + public static void XSLTransform(XmlDocument doc, ref StreamWriter writer, string xsltUrl) + { + var xslt = new XslCompiledTransform(); + xslt.Load(xsltUrl); + //Transform the file. + xslt.Transform(doc, null, writer); + } + + public static string Serialize(object obj) + { + string xmlObject; + var dic = obj as IDictionary; + if ((dic != null)) + { + xmlObject = SerializeDictionary(dic, "dictionary"); + } + else + { + var xmlDoc = new XmlDocument(); + var xser = new XmlSerializer(obj.GetType()); + var sw = new StringWriter(); + + xser.Serialize(sw, obj); + + xmlDoc.LoadXml(sw.GetStringBuilder().ToString()); + XmlNode xmlDocEl = xmlDoc.DocumentElement; + xmlDocEl.Attributes.Remove(xmlDocEl.Attributes["xmlns:xsd"]); + xmlDocEl.Attributes.Remove(xmlDocEl.Attributes["xmlns:xsi"]); + + xmlObject = xmlDocEl.OuterXml; + } + return xmlObject; + } + + /// + /// Produce an XPath literal equal to the value if possible; if not, produce + /// an XPath expression that will match the value. + /// + /// Note that this function will produce very long XPath expressions if a value + /// contains a long run of double quotes. + /// + /// The value to match. + /// If the value contains only single or double quotes, an XPath + /// literal equal to the value. If it contains both, an XPath expression, + /// using concat(), that evaluates to the value. + /// From Stack Overflow () + public static string XPathLiteral(string value) + { + // if the value contains only single or double quotes, construct + // an XPath literal + if (!value.Contains("\"")) + { + return "\"" + value + "\""; + } + if (!value.Contains("'")) + { + return "'" + value + "'"; + } + + // if the value contains both single and double quotes, construct an + // expression that concatenates all non-double-quote substrings with + // the quotes, e.g.: + // + // concat("foo", '"', "bar") + StringBuilder sb = new StringBuilder(); + sb.Append("concat("); + string[] substrings = value.Split('\"'); + for (int i = 0; i < substrings.Length; i++) + { + bool needComma = i > 0; + if (substrings[i] != string.Empty) + { + if (i > 0) + { + sb.Append(", "); + } + sb.Append("\""); + sb.Append(substrings[i]); + sb.Append("\""); + needComma = true; + } + if (i < substrings.Length - 1) + { + if (needComma) + { + sb.Append(", "); + } + sb.Append("'\"'"); + } + } + sb.Append(")"); + return sb.ToString(); + } + [Obsolete("This method is obsolete.")] + public static XmlDocument GetXMLContent(string contentUrl) + { + //This function reads an Xml document via a Url and returns it as an XmlDocument object + + var functionReturnValue = new XmlDocument(); + var req = WebRequest.Create(contentUrl); + var result = req.GetResponse(); + var objXmlReader = new XmlTextReader(result.GetResponseStream()); + functionReturnValue.Load(objXmlReader); + return functionReturnValue; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Common/XmlValidatorBase.cs b/DNN Platform/Library/Common/XmlValidatorBase.cs new file mode 100644 index 00000000000..cbd8c50f09e --- /dev/null +++ b/DNN Platform/Library/Common/XmlValidatorBase.cs @@ -0,0 +1,137 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.IO; +using System.Xml; +using System.Xml.Schema; + +#endregion + +namespace DotNetNuke.Common +{ + /// + /// Base class od XmlValidator + /// + public class XmlValidatorBase + { + private readonly XmlSchemaSet _schemaSet; + private ArrayList _errs; + private XmlTextReader _reader; + + public XmlValidatorBase() + { + _errs = new ArrayList(); + _schemaSet = new XmlSchemaSet(); + } + + /// + /// Gets or sets the errors. + /// + /// + /// The errors. + /// + public ArrayList Errors + { + get + { + return _errs; + } + set + { + _errs = value; + } + } + + /// + /// Gets the schema set. + /// + public XmlSchemaSet SchemaSet + { + get + { + return _schemaSet; + } + } + + /// + /// Validations the call back. + /// + /// The sender. + /// The instance containing the event data. + protected void ValidationCallBack(object sender, ValidationEventArgs args) + { + _errs.Add(args.Message); + } + + /// + /// Determines whether this instance is valid. + /// + /// + /// true if this instance is valid; otherwise, false. + /// + public bool IsValid() + { + //There is a bug here which I haven't been able to fix. + //If the XML Instance does not include a reference to the + //schema, then the validation fails. If the reference exists + //the the validation works correctly. + + //Create a validating reader + var settings = new XmlReaderSettings(); + settings.Schemas = _schemaSet; + settings.ValidationType = ValidationType.Schema; + //Set the validation event handler. + settings.ValidationEventHandler += ValidationCallBack; + XmlReader vreader = XmlReader.Create(_reader, settings); + //Read and validate the XML data. + while (vreader.Read()) + { + } + vreader.Close(); + return (_errs.Count == 0); + } + + /// + /// Validates the specified XML stream. + /// + /// The XML stream. + /// + public virtual bool Validate(Stream xmlStream) + { + xmlStream.Seek(0, SeekOrigin.Begin); + _reader = new XmlTextReader(xmlStream); + return IsValid(); + } + + /// + /// Validates the specified filename. + /// + /// The filename. + /// + public virtual bool Validate(string filename) + { + _reader = new XmlTextReader(filename); + return IsValid(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/AbstractContainer.cs b/DNN Platform/Library/ComponentModel/AbstractContainer.cs new file mode 100644 index 00000000000..a1ca360eae3 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/AbstractContainer.cs @@ -0,0 +1,164 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public abstract class AbstractContainer : IContainer + { + #region IContainer Members + + public abstract string Name { get; } + + public abstract object GetComponent(string name); + + public abstract object GetComponent(string name, Type contractType); + + public abstract object GetComponent(Type contractType); + + public virtual TContract GetComponent() + { + return (TContract) GetComponent(typeof (TContract)); + } + + public virtual TContract GetComponent(string name) + { + return (TContract) GetComponent(name, typeof (TContract)); + } + + public abstract string[] GetComponentList(Type contractType); + + public virtual string[] GetComponentList() + { + return GetComponentList(typeof (TContract)); + } + + public abstract IDictionary GetComponentSettings(string name); + + public virtual IDictionary GetComponentSettings(Type component) + { + return GetComponentSettings(component.FullName); + } + + public IDictionary GetComponentSettings() + { + return GetComponentSettings(typeof (TComponent).FullName); + } + + public abstract void RegisterComponent(string name, Type contractType, Type componentType, ComponentLifeStyleType lifestyle); + + public virtual void RegisterComponent(string name, Type contractType, Type componentType) + { + RegisterComponent(name, contractType, componentType, ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent(string name, Type componentType) + { + RegisterComponent(name, componentType, componentType, ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent(Type contractType, Type componentType) + { + RegisterComponent(componentType.FullName, contractType, componentType, ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent(Type contractType, Type componentType, ComponentLifeStyleType lifestyle) + { + RegisterComponent(componentType.FullName, contractType, componentType, lifestyle); + } + + public virtual void RegisterComponent(Type componentType) + { + RegisterComponent(componentType.FullName, componentType, componentType, ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent() where TComponent : class + { + RegisterComponent(typeof (TComponent)); + } + + public virtual void RegisterComponent(string name) where TComponent : class + { + RegisterComponent(name, typeof (TComponent), typeof (TComponent), ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent(string name, ComponentLifeStyleType lifestyle) where TComponent : class + { + RegisterComponent(name, typeof (TComponent), typeof (TComponent), lifestyle); + } + + public virtual void RegisterComponent() where TComponent : class + { + RegisterComponent(typeof (TContract), typeof (TComponent)); + } + + public virtual void RegisterComponent(string name) where TComponent : class + { + RegisterComponent(name, typeof (TContract), typeof (TComponent), ComponentLifeStyleType.Singleton); + } + + public virtual void RegisterComponent(string name, ComponentLifeStyleType lifestyle) where TComponent : class + { + RegisterComponent(name, typeof (TContract), typeof (TComponent), lifestyle); + } + + public abstract void RegisterComponentSettings(string name, IDictionary dependencies); + + public virtual void RegisterComponentSettings(Type component, IDictionary dependencies) + { + RegisterComponentSettings(component.FullName, dependencies); + } + + public virtual void RegisterComponentSettings(IDictionary dependencies) + { + RegisterComponentSettings(typeof (TComponent).FullName, dependencies); + } + + public abstract void RegisterComponentInstance(string name, Type contractType, object instance); + + public void RegisterComponentInstance(string name, object instance) + { + RegisterComponentInstance(name, instance.GetType(), instance); + } + + public void RegisterComponentInstance(object instance) + { + RegisterComponentInstance(instance.GetType().FullName, typeof (TContract), instance); + } + + public void RegisterComponentInstance(string name, object instance) + { + RegisterComponentInstance(name, typeof (TContract), instance); + } + + #endregion + + public virtual IDictionary GetCustomDependencies() + { + return GetComponentSettings(typeof (TComponent).FullName); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/ComponentBase.cs b/DNN Platform/Library/ComponentModel/ComponentBase.cs new file mode 100644 index 00000000000..4fb2e5d3d33 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentBase.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public abstract class ComponentBase where TType : class, TContract + { + public static TContract Instance + { + get + { + var component = ComponentFactory.GetComponent(); + + if (component == null) + { + component = (TContract) Activator.CreateInstance(typeof (TType), true); + ComponentFactory.RegisterComponentInstance(component); + } + + return component; + } + } + + public static void RegisterInstance(TContract instance) + { + if ((ComponentFactory.GetComponent() == null)) + { + ComponentFactory.RegisterComponentInstance(instance); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/ComponentBuilderCollection.cs b/DNN Platform/Library/ComponentModel/ComponentBuilderCollection.cs new file mode 100644 index 00000000000..2733f3f1d3f --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentBuilderCollection.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Collections.Internal; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + internal class ComponentBuilderCollection : SharedDictionary + { + internal IComponentBuilder DefaultBuilder { get; set; } + + internal void AddBuilder(IComponentBuilder builder, bool setDefault) + { + if (!ContainsKey(builder.Name)) + { + this[builder.Name] = builder; + + if (setDefault && DefaultBuilder == null) + { + DefaultBuilder = builder; + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/ComponentFactory.cs b/DNN Platform/Library/ComponentModel/ComponentFactory.cs new file mode 100644 index 00000000000..020eb1c5aa5 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentFactory.cs @@ -0,0 +1,221 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public static class ComponentFactory + { + public static IContainer Container { get; set; } + + public static void InstallComponents(params IComponentInstaller[] installers) + { + if (installers == null) + { + throw new ArgumentNullException("installers"); + } + VerifyContainer(); + foreach (IComponentInstaller installer in installers) + { + if (installer == null) + { + throw new ArgumentNullException("installers"); + } + installer.InstallComponents(Container); + } + } + + private static void VerifyContainer() + { + if (Container == null) + { + Container = new SimpleContainer(); + } + } + + public static object GetComponent(string name) + { + VerifyContainer(); + return Container.GetComponent(name); + } + + public static TContract GetComponent() + { + VerifyContainer(); + return Container.GetComponent(); + } + + public static object GetComponent(Type contractType) + { + VerifyContainer(); + return Container.GetComponent(contractType); + } + + public static TContract GetComponent(string name) + { + VerifyContainer(); + return Container.GetComponent(name); + } + + public static object GetComponent(string name, Type contractType) + { + VerifyContainer(); + return Container.GetComponent(name, contractType); + } + + public static string[] GetComponentList(Type contractType) + { + VerifyContainer(); + return Container.GetComponentList(contractType); + } + + public static string[] GetComponentList() + { + VerifyContainer(); + return Container.GetComponentList(); + } + + public static Dictionary GetComponents() + { + VerifyContainer(); + var components = new Dictionary(); + foreach (string componentName in GetComponentList()) + { + components[componentName] = GetComponent(componentName); + } + return components; + } + + public static IDictionary GetComponentSettings(string name) + { + VerifyContainer(); + return Container.GetComponentSettings(name); + } + + public static IDictionary GetComponentSettings(Type component) + { + VerifyContainer(); + return Container.GetComponentSettings(component); + } + + public static IDictionary GetComponentSettings() + { + VerifyContainer(); + return Container.GetComponentSettings(); + } + + public static void RegisterComponent() where TComponent : class + { + VerifyContainer(); + Container.RegisterComponent(); + } + + public static void RegisterComponent() where TComponent : class + { + VerifyContainer(); + Container.RegisterComponent(); + } + + public static void RegisterComponent(Type componentType) + { + VerifyContainer(); + Container.RegisterComponent(componentType); + } + + public static void RegisterComponent(Type contractType, Type componentType) + { + VerifyContainer(); + Container.RegisterComponent(contractType, componentType); + } + + public static void RegisterComponent(string name) where TComponent : class + { + VerifyContainer(); + Container.RegisterComponent(name); + } + + public static void RegisterComponent(string name) where TComponent : class + { + VerifyContainer(); + Container.RegisterComponent(name); + } + + public static void RegisterComponent(string name, Type componentType) + { + VerifyContainer(); + Container.RegisterComponent(name, componentType); + } + + public static void RegisterComponent(string name, Type contractType, Type componentType) + { + VerifyContainer(); + Container.RegisterComponent(name, contractType, componentType); + } + + public static void RegisterComponentInstance(string name, Type contractType, object instance) + { + VerifyContainer(); + Container.RegisterComponentInstance(name, contractType, instance); + } + + public static void RegisterComponentInstance(string name, object instance) + { + VerifyContainer(); + Container.RegisterComponentInstance(name, instance); + } + + public static void RegisterComponentInstance(string name, object instance) + { + VerifyContainer(); + Container.RegisterComponentInstance(name, instance); + } + + public static void RegisterComponentInstance(object instance) + { + VerifyContainer(); + Container.RegisterComponentInstance(instance); + } + + public static void RegisterComponentSettings(string name, IDictionary dependencies) + { + VerifyContainer(); + Container.RegisterComponentSettings(name, dependencies); + } + + public static void RegisterComponentSettings(Type component, IDictionary dependencies) + { + VerifyContainer(); + Container.RegisterComponentSettings(component, dependencies); + } + + public static void RegisterComponentSettings(IDictionary dependencies) + { + VerifyContainer(); + Container.RegisterComponentSettings(dependencies); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/ComponentLifeStyleType.cs b/DNN Platform/Library/ComponentModel/ComponentLifeStyleType.cs new file mode 100644 index 00000000000..9468ab2bf14 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentLifeStyleType.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.ComponentModel +{ + public enum ComponentLifeStyleType + { + Singleton, + Transient + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/ComponentType.cs b/DNN Platform/Library/ComponentModel/ComponentType.cs new file mode 100644 index 00000000000..947795461ff --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentType.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + internal class ComponentType + { + private readonly Type _BaseType; + private readonly ComponentBuilderCollection _ComponentBuilders = new ComponentBuilderCollection(); + + /// + /// Initializes a new instance of the ComponentType class. + /// + /// The base type of Components of this ComponentType + public ComponentType(Type baseType) + { + _BaseType = baseType; + } + + public Type BaseType + { + get + { + return _BaseType; + } + } + + public ComponentBuilderCollection ComponentBuilders + { + get + { + return _ComponentBuilders; + } + } + } +} diff --git a/DNN Platform/Library/ComponentModel/ComponentTypeCollection.cs b/DNN Platform/Library/ComponentModel/ComponentTypeCollection.cs new file mode 100644 index 00000000000..afce352932a --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ComponentTypeCollection.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Collections.Internal; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + internal class ComponentTypeCollection : SharedDictionary + { + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/CacheableAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/CacheableAttribute.cs new file mode 100644 index 00000000000..d8b45ff2a65 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/CacheableAttribute.cs @@ -0,0 +1,84 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Web.Caching; + +#endregion + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class CacheableAttribute : Attribute + { + /// + /// Construct a new CacheableAttribute + /// + public CacheableAttribute() + { + } + + /// + /// Construct a new CacheableAttribute + /// + /// The cacheKey to use + public CacheableAttribute(string cacheKey) : this(cacheKey, CacheItemPriority.Default, 20) {} + + /// + /// Construct a new CacheableAttribute + /// + /// The cacheKey to use + /// The priority of the cached item + public CacheableAttribute(string cacheKey, CacheItemPriority priority) : this(cacheKey, priority, 20) { } + + /// + /// Construct a new CacheableAttribute + /// + /// The cacheKey to use + /// The priority of the cached item + /// The timeout multiplier used to cache the item + public CacheableAttribute(string cacheKey, CacheItemPriority priority, int timeOut) + { + CacheKey = cacheKey; + CachePriority = priority; + CacheTimeOut = timeOut; + } + + /// + /// The root key to use for the cache + /// + public string CacheKey { get; set; } + + /// + /// The priority of the cached item. The default value is CacheItemPriority.Default + /// + public CacheItemPriority CachePriority { get; set; } + + /// + /// The timeout multiplier used to cache the item. This value is multiple by the Host + /// Performance Setting to determine the actual timeout value. The default value is 20. + /// + public int CacheTimeOut { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/ColumnNameAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/ColumnNameAttribute.cs new file mode 100644 index 00000000000..72b88e507e6 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/ColumnNameAttribute.cs @@ -0,0 +1,41 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class ColumnNameAttribute : Attribute + { + public ColumnNameAttribute(string columnName) + { + ColumnName = columnName; + } + + public string ColumnName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/DeclareColumnsAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/DeclareColumnsAttribute.cs new file mode 100644 index 00000000000..b18d8b5af5d --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/DeclareColumnsAttribute.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class DeclareColumnsAttribute : Attribute + { + } +} diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/IgnoreColumnAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/IgnoreColumnAttribute.cs new file mode 100644 index 00000000000..92402fda84a --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/IgnoreColumnAttribute.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class IgnoreColumnAttribute : Attribute + { + } +} diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/IncludeColumnAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/IncludeColumnAttribute.cs new file mode 100644 index 00000000000..3efa84ca7fd --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/IncludeColumnAttribute.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class IncludeColumnAttribute : Attribute + { + } +} diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/PrimaryKeyAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/PrimaryKeyAttribute.cs new file mode 100644 index 00000000000..e74568f44f5 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/PrimaryKeyAttribute.cs @@ -0,0 +1,50 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class PrimaryKeyAttribute : Attribute + { + public PrimaryKeyAttribute(string columnName) : this(columnName, columnName) + { + } + + public PrimaryKeyAttribute(string columnName, string propertyName) + { + ColumnName = columnName; + PropertyName = propertyName; + AutoIncrement = true; + } + + public bool AutoIncrement { get; set; } + public string ColumnName { get; set; } + public string PropertyName { get; set; } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/ReadOnlyColumnAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/ReadOnlyColumnAttribute.cs new file mode 100644 index 00000000000..b037a9539cd --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/ReadOnlyColumnAttribute.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class ReadOnlyColumnAttribute : Attribute + { + } +} diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/ScopeAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/ScopeAttribute.cs new file mode 100644 index 00000000000..d8debe0f17e --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/ScopeAttribute.cs @@ -0,0 +1,42 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class ScopeAttribute : Attribute + { + + public ScopeAttribute(string scope) + { + Scope = scope; + } + + /// + /// The property to use to scope the cache. The default is an empty string. + /// + public string Scope { get; set; } + + } +} diff --git a/DNN Platform/Library/ComponentModel/DataAnnotations/TableNameAttribute.cs b/DNN Platform/Library/ComponentModel/DataAnnotations/TableNameAttribute.cs new file mode 100644 index 00000000000..4f71d220a78 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/DataAnnotations/TableNameAttribute.cs @@ -0,0 +1,41 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.ComponentModel.DataAnnotations +{ + public class TableNameAttribute : Attribute + { + public TableNameAttribute(string tableName) + { + TableName = tableName; + } + + public string TableName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/IComponentBuilder.cs b/DNN Platform/Library/ComponentModel/IComponentBuilder.cs new file mode 100644 index 00000000000..22bdb3f8f6a --- /dev/null +++ b/DNN Platform/Library/ComponentModel/IComponentBuilder.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.ComponentModel +{ + public interface IComponentBuilder + { + string Name { get; } + + object BuildComponent(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/IComponentInstaller.cs b/DNN Platform/Library/ComponentModel/IComponentInstaller.cs new file mode 100644 index 00000000000..7d3891ac3ba --- /dev/null +++ b/DNN Platform/Library/ComponentModel/IComponentInstaller.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.ComponentModel +{ + public interface IComponentInstaller + { + void InstallComponents(IContainer container); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/IContainer.cs b/DNN Platform/Library/ComponentModel/IContainer.cs new file mode 100644 index 00000000000..ecb24de36bc --- /dev/null +++ b/DNN Platform/Library/ComponentModel/IContainer.cs @@ -0,0 +1,92 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public interface IContainer + { + string Name { get; } + + void RegisterComponent() where TComponent : class; + + void RegisterComponent(string name) where TComponent : class; + + void RegisterComponent(string name, ComponentLifeStyleType lifestyle) where TComponent : class; + + void RegisterComponent() where TComponent : class; + + void RegisterComponent(string name) where TComponent : class; + + void RegisterComponent(string name, ComponentLifeStyleType lifestyle) where TComponent : class; + + void RegisterComponent(Type componentType); + + void RegisterComponent(Type contractType, Type componentType); + + void RegisterComponent(Type contractType, Type componentType, ComponentLifeStyleType lifestyle); + + void RegisterComponent(string name, Type componentType); + + void RegisterComponent(string name, Type contractType, Type componentType); + + void RegisterComponent(string name, Type contractType, Type componentType, ComponentLifeStyleType lifestyle); + + void RegisterComponentInstance(string name, object instance); + + void RegisterComponentInstance(string name, Type contractType, object instance); + + void RegisterComponentInstance(object instance); + + void RegisterComponentInstance(string name, object instance); + + void RegisterComponentSettings(string name, IDictionary dependencies); + + void RegisterComponentSettings(Type component, IDictionary dependencies); + + void RegisterComponentSettings(IDictionary dependencies); + + object GetComponent(string name); + + TContract GetComponent(); + + object GetComponent(Type contractType); + + TContract GetComponent(string name); + + object GetComponent(string name, Type contractType); + + string[] GetComponentList(); + + string[] GetComponentList(Type contractType); + + IDictionary GetComponentSettings(string name); + + IDictionary GetComponentSettings(Type component); + + IDictionary GetComponentSettings(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/InstanceComponentBuilder.cs b/DNN Platform/Library/ComponentModel/InstanceComponentBuilder.cs new file mode 100644 index 00000000000..c59e2678a5f --- /dev/null +++ b/DNN Platform/Library/ComponentModel/InstanceComponentBuilder.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.ComponentModel +{ + internal class InstanceComponentBuilder : IComponentBuilder + { + private readonly object _Instance; + private readonly string _Name; + + /// + /// Initializes a new instance of the InstanceComponentBuilder class. + /// + /// + /// + public InstanceComponentBuilder(string name, object instance) + { + _Name = name; + _Instance = instance; + } + + #region IComponentBuilder Members + + public object BuildComponent() + { + return _Instance; + } + + public string Name + { + get + { + return _Name; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/ComponentModel/ProviderInstaller.cs b/DNN Platform/Library/ComponentModel/ProviderInstaller.cs new file mode 100644 index 00000000000..d8e232241c8 --- /dev/null +++ b/DNN Platform/Library/ComponentModel/ProviderInstaller.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Web.Compilation; + +using DotNetNuke.Framework.Providers; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public class ProviderInstaller : IComponentInstaller + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ProviderInstaller)); + private readonly ComponentLifeStyleType _ComponentLifeStyle; + private readonly Type _ProviderInterface; + private readonly string _ProviderType; + private Type _defaultProvider; + + public ProviderInstaller(string providerType, Type providerInterface) + { + _ComponentLifeStyle = ComponentLifeStyleType.Singleton; + _ProviderType = providerType; + _ProviderInterface = providerInterface; + } + + public ProviderInstaller(string providerType, Type providerInterface, Type defaultProvider) + { + _ComponentLifeStyle = ComponentLifeStyleType.Singleton; + _ProviderType = providerType; + _ProviderInterface = providerInterface; + _defaultProvider = defaultProvider; + } + + public ProviderInstaller(string providerType, Type providerInterface, ComponentLifeStyleType lifeStyle) + { + _ComponentLifeStyle = lifeStyle; + _ProviderType = providerType; + _ProviderInterface = providerInterface; + } + + #region IComponentInstaller Members + + public void InstallComponents(IContainer container) + { + ProviderConfiguration config = ProviderConfiguration.GetProviderConfiguration(_ProviderType); + //Register the default provider first (so it is the first component registered for its service interface + if (config != null) + { + InstallProvider(container, (Provider) config.Providers[config.DefaultProvider]); + + //Register the others + foreach (Provider provider in config.Providers.Values) + { + //Skip the default because it was registered above + if (!config.DefaultProvider.Equals(provider.Name, StringComparison.OrdinalIgnoreCase)) + { + InstallProvider(container, provider); + } + } + } + } + + #endregion + + private void InstallProvider(IContainer container, Provider provider) + { + if (provider != null) + { + Type type = null; + + //Get the provider type + try + { + type = BuildManager.GetType(provider.Type, false, true); + } + catch (TypeLoadException) + { + if (_defaultProvider != null) + { + type = _defaultProvider; + } + } + + if (type == null) + { + Logger.Error(new ConfigurationErrorsException(string.Format("Could not load provider {0}", provider.Type))); + } + else + { + //Register the component + container.RegisterComponent(provider.Name, _ProviderInterface, type, _ComponentLifeStyle); + + //Load the settings into a dictionary + var settingsDict = new Dictionary { { "providerName", provider.Name } }; + foreach (string key in provider.Attributes.Keys) + { + settingsDict.Add(key, provider.Attributes.Get(key)); + } + //Register the settings as dependencies + container.RegisterComponentSettings(type.FullName, settingsDict); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ComponentModel/SimpleContainer.cs b/DNN Platform/Library/ComponentModel/SimpleContainer.cs new file mode 100644 index 00000000000..a2635422b7a --- /dev/null +++ b/DNN Platform/Library/ComponentModel/SimpleContainer.cs @@ -0,0 +1,275 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Collections.Internal; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + public class SimpleContainer : AbstractContainer + { + private readonly string _name; + private readonly ComponentBuilderCollection _componentBuilders = new ComponentBuilderCollection(); + + private readonly SharedDictionary _componentDependencies = new SharedDictionary(); + + private readonly ComponentTypeCollection _componentTypes = new ComponentTypeCollection(); + + private readonly SharedDictionary _registeredComponents = new SharedDictionary(); + + #region "Constructors" + + /// + /// Initializes a new instance of the SimpleContainer class. + /// + public SimpleContainer() : this(string.Format("Container_{0}", Guid.NewGuid())) + { + } + + /// + /// Initializes a new instance of the SimpleContainer class. + /// + /// + public SimpleContainer(string name) + { + _name = name; + } + + #endregion + + #region "Private Methods" + + private void AddBuilder(Type contractType, IComponentBuilder builder) + { + ComponentType componentType = GetComponentType(contractType); + if (componentType != null) + { + ComponentBuilderCollection builders = componentType.ComponentBuilders; + + using (builders.GetWriteLock()) + { + builders.AddBuilder(builder, true); + } + + using (_componentBuilders.GetWriteLock()) + { + _componentBuilders.AddBuilder(builder, false); + } + } + } + + private void AddComponentType(Type contractType) + { + ComponentType componentType = GetComponentType(contractType); + + if (componentType == null) + { + componentType = new ComponentType(contractType); + + using (_componentTypes.GetWriteLock()) + { + _componentTypes[componentType.BaseType] = componentType; + } + } + } + + private object GetComponent(IComponentBuilder builder) + { + object component; + if (builder == null) + { + component = null; + } + else + { + component = builder.BuildComponent(); + } + return component; + } + + private IComponentBuilder GetComponentBuilder(string name) + { + IComponentBuilder builder; + + using (_componentBuilders.GetReadLock()) + { + _componentBuilders.TryGetValue(name, out builder); + } + + return builder; + } + + private IComponentBuilder GetDefaultComponentBuilder(ComponentType componentType) + { + IComponentBuilder builder; + + using (componentType.ComponentBuilders.GetReadLock()) + { + builder = componentType.ComponentBuilders.DefaultBuilder; + } + + return builder; + } + + private ComponentType GetComponentType(Type contractType) + { + ComponentType componentType; + + using (_componentTypes.GetReadLock()) + { + _componentTypes.TryGetValue(contractType, out componentType); + } + + return componentType; + } + + public override void RegisterComponent(string name, Type type) + { + using (_registeredComponents.GetWriteLock()) + { + _registeredComponents[type] = name; + } + } + + #endregion + + public override string Name + { + get + { + return _name; + } + } + + public override object GetComponent(string name) + { + IComponentBuilder builder = GetComponentBuilder(name); + + return GetComponent(builder); + } + + public override object GetComponent(Type contractType) + { + ComponentType componentType = GetComponentType(contractType); + object component = null; + + if (componentType != null) + { + int builderCount; + + using (componentType.ComponentBuilders.GetReadLock()) + { + builderCount = componentType.ComponentBuilders.Count; + } + + if (builderCount > 0) + { + IComponentBuilder builder = GetDefaultComponentBuilder(componentType); + + component = GetComponent(builder); + } + } + + return component; + } + + public override object GetComponent(string name, Type contractType) + { + ComponentType componentType = GetComponentType(contractType); + object component = null; + + if (componentType != null) + { + IComponentBuilder builder = GetComponentBuilder(name); + + component = GetComponent(builder); + } + return component; + } + + public override string[] GetComponentList(Type contractType) + { + var components = new List(); + + using (_registeredComponents.GetReadLock()) + { + foreach (KeyValuePair kvp in _registeredComponents) + { + if (contractType.IsAssignableFrom(kvp.Key)) + { + components.Add(kvp.Value); + } + } + } + return components.ToArray(); + } + + public override IDictionary GetComponentSettings(string name) + { + IDictionary settings; + using (_componentDependencies.GetReadLock()) + { + settings = _componentDependencies[name]; + } + return settings; + } + + public override void RegisterComponent(string name, Type contractType, Type type, ComponentLifeStyleType lifestyle) + { + AddComponentType(contractType); + + IComponentBuilder builder = null; + switch (lifestyle) + { + case ComponentLifeStyleType.Transient: + builder = new TransientComponentBuilder(name, type); + break; + case ComponentLifeStyleType.Singleton: + builder = new SingletonComponentBuilder(name, type); + break; + } + AddBuilder(contractType, builder); + + RegisterComponent(name, type); + } + + public override void RegisterComponentInstance(string name, Type contractType, object instance) + { + AddComponentType(contractType); + + AddBuilder(contractType, new InstanceComponentBuilder(name, instance)); + } + + public override void RegisterComponentSettings(string name, IDictionary dependencies) + { + using (_componentDependencies.GetWriteLock()) + { + _componentDependencies[name] = dependencies; + } + } + } +} diff --git a/DNN Platform/Library/ComponentModel/SingletonComponentBuilder.cs b/DNN Platform/Library/ComponentModel/SingletonComponentBuilder.cs new file mode 100644 index 00000000000..1ff856d882a --- /dev/null +++ b/DNN Platform/Library/ComponentModel/SingletonComponentBuilder.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + internal class SingletonComponentBuilder : IComponentBuilder + { + private readonly string _Name; + private readonly Type _Type; + private object _Instance; + + /// + /// Initializes a new instance of the SingletonComponentBuilder class. + /// + /// The name of the component + /// The type of the component + public SingletonComponentBuilder(string name, Type type) + { + _Name = name; + _Type = type; + } + + #region IComponentBuilder Members + + public object BuildComponent() + { + if (_Instance == null) + { + CreateInstance(); + } + return _Instance; + } + + public string Name + { + get + { + return _Name; + } + } + + #endregion + + private void CreateInstance() + { + _Instance = Reflection.CreateObject(_Type); + } + } +} diff --git a/DNN Platform/Library/ComponentModel/TransientComponentBuilder.cs b/DNN Platform/Library/ComponentModel/TransientComponentBuilder.cs new file mode 100644 index 00000000000..1f4a99e3dfb --- /dev/null +++ b/DNN Platform/Library/ComponentModel/TransientComponentBuilder.cs @@ -0,0 +1,64 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.ComponentModel +{ + internal class TransientComponentBuilder : IComponentBuilder + { + private readonly string _Name; + private readonly Type _Type; + + /// + /// Initializes a new instance of the TransientComponentBuilder class. + /// + /// The name of the component + /// The type of the component + public TransientComponentBuilder(string name, Type type) + { + _Name = name; + _Type = type; + } + + #region IComponentBuilder Members + + public object BuildComponent() + { + return Reflection.CreateObject(_Type); + } + + public string Name + { + get + { + return _Name; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Data/DataContext.cs b/DNN Platform/Library/Data/DataContext.cs new file mode 100644 index 00000000000..b4dda429f45 --- /dev/null +++ b/DNN Platform/Library/Data/DataContext.cs @@ -0,0 +1,53 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Configuration; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data.PetaPoco; + +#endregion + +namespace DotNetNuke.Data +{ + public class DataContext + { + #region Public Methods + + public static IDataContext Instance() + { + var defaultConnectionStringName = DataProvider.Instance().Settings["connectionStringName"]; + + return new PetaPocoDataContext(defaultConnectionStringName, DataProvider.Instance().ObjectQualifier); + } + + public static IDataContext Instance(string connectionStringName) + { + return new PetaPocoDataContext(connectionStringName, DataProvider.Instance().ObjectQualifier); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/DataProvider.cs b/DNN Platform/Library/Data/DataProvider.cs new file mode 100644 index 00000000000..50b047db375 Binary files /dev/null and b/DNN Platform/Library/Data/DataProvider.cs differ diff --git a/DNN Platform/Library/Data/DataUtil.cs b/DNN Platform/Library/Data/DataUtil.cs new file mode 100644 index 00000000000..5e2043f536c --- /dev/null +++ b/DNN Platform/Library/Data/DataUtil.cs @@ -0,0 +1,154 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Linq; +using System.Reflection; +using System.Text; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace DotNetNuke.Data +{ + internal static class DataUtil + { + #region Internal Methods + + internal static TAttribute GetAttribute(Type type) + { + TAttribute attribute = default(TAttribute); + + object[] tableNameAttributes = type.GetCustomAttributes(typeof(TAttribute), true); + if (tableNameAttributes.Length > 0) + { + attribute = (TAttribute)tableNameAttributes[0]; + } + + return attribute; + } + + internal static bool GetAutoIncrement(Type type, bool defaultValue) + { + var autoIncrement = defaultValue; + + var primaryKeyAttribute = GetAttribute(type); + if (primaryKeyAttribute != null) + { + autoIncrement = primaryKeyAttribute.AutoIncrement; + } + + return autoIncrement; + } + + internal static string GetColumnName(Type type, string propertyName) + { + return GetColumnName(type.GetProperty(propertyName), propertyName); + } + + internal static string GetColumnName(PropertyInfo propertyInfo, string defaultName) + { + var columnName = defaultName; + + object[] columnNameAttributes = propertyInfo.GetCustomAttributes(typeof(ColumnNameAttribute), true); + if (columnNameAttributes.Length > 0) + { + var columnNameAttribute = (ColumnNameAttribute)columnNameAttributes[0]; + columnName = columnNameAttribute.ColumnName; + } + + return columnName; + } + + internal static bool GetIsCacheable(Type type) + { + return (GetAttribute(type) != null); + } + + internal static string GetPrimaryKeyColumn(Type type, string defaultName) + { + var primaryKeyName = defaultName; + + var primaryKeyAttribute = GetAttribute(type); + if (primaryKeyAttribute != null) + { + primaryKeyName = primaryKeyAttribute.ColumnName; + } + + return primaryKeyName; + } + + internal static string GetPrimaryKeyProperty(Type type, string defaultName) + { + var primaryKeyName = defaultName; + + var primaryKeyAttribute = GetAttribute(type); + if (primaryKeyAttribute != null) + { + primaryKeyName = primaryKeyAttribute.PropertyName; + } + + return primaryKeyName; + } + + internal static string GenerateExecuteStoredProcedureSql(string procedureName, params object[] args) + { + var sb = new StringBuilder(";Exec "); + sb.Append(procedureName); + for (int i = 0; i < args.Count(); i++) + { + sb.Append(String.Format(" @{0}", i)); + if (i < args.Count() - 1) + { + sb.Append(","); + } + } + return sb.ToString(); + } + + internal static string GetTableName(Type type) + { + return GetTableName(type, String.Empty); + } + + internal static string GetTableName(Type type, string defaultName) + { + var tableName = defaultName; + + var tableNameAttribute = GetAttribute(type); + if (tableNameAttribute != null) + { + tableName = tableNameAttribute.TableName; + } + + return tableName; + } + + internal static string ReplaceTokens(string sql) + { + return sql.Replace("{databaseOwner}", DataProvider.Instance().DatabaseOwner) + .Replace("{objectQualifier}", DataProvider.Instance().ObjectQualifier); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/IDataContext.cs b/DNN Platform/Library/Data/IDataContext.cs new file mode 100644 index 00000000000..25855e05c90 --- /dev/null +++ b/DNN Platform/Library/Data/IDataContext.cs @@ -0,0 +1,43 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Data; + +namespace DotNetNuke.Data +{ + public interface IDataContext : IDisposable + { + void BeginTransaction(); + void Commit(); + + void Execute(CommandType type, string sql, params object[] args); + IEnumerable ExecuteQuery(CommandType type, string sql, params object[] args); + T ExecuteScalar(CommandType type, string sql, params object[] args); + T ExecuteSingleOrDefault(CommandType type, string sql, params object[] args); + + IRepository GetRepository() where T : class; + void RollbackTransaction(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/IRepository.cs b/DNN Platform/Library/Data/IRepository.cs new file mode 100644 index 00000000000..3e433c5ec13 --- /dev/null +++ b/DNN Platform/Library/Data/IRepository.cs @@ -0,0 +1,151 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; + +using DotNetNuke.Collections; + +namespace DotNetNuke.Data +{ + public interface IRepository where T : class + { + /// + /// Delete an Item from the repository + /// + /// The item to be deleted + void Delete(T item); + + /// + /// Delete items from the repository based on a sql Condition + /// + /// The sql condition e.g. "WHERE ArticleId = {0}" + /// A collection of arguments to be mapped to the tokens in the sqlCondition + void Delete(string sqlCondition, params object[] args); + + /// + /// Find items from the repository based on a sql condition + /// + /// Find supports both full SQL statements such as "SELECT * FROM table WHERE ..." + /// as well as a SQL condition like "WHERE ..." + /// The sql condition e.g. "WHERE ArticleId = {0}" + /// A collection of arguments to be mapped to the tokens in the sqlCondition + /// A list of items + IEnumerable Find(string sqlCondition, params object[] args); + + /// + /// Find a GetPage of items from the repository based on a sql condition + /// + /// Find supports both full SQL statements such as "SELECT * FROM table WHERE ..." + /// as well as a SQL condition like "WHERE ..." + /// The page Index to fetch + /// The size of the page to fetch + /// The sql condition e.g. "WHERE ArticleId = {0}" + /// A collection of arguments to be mapped to the tokens in the sqlCondition + /// A list of items + IPagedList Find(int pageIndex, int pageSize, string sqlCondition, params object[] args); + + /// + /// Returns all the items in the repository as an enumerable list + /// + /// The list of items + IEnumerable Get(); + + /// + /// Returns an enumerable list of items filtered by scope + /// + /// + /// This overload should be used to get a list of items for a specific module + /// instance or for a specific portal dependening on how the items in the repository + /// are scoped. + /// + /// The type of the scope field + /// The value of the scope to filter by + /// The list of items + IEnumerable Get(TScopeType scopeValue); + + /// + /// Get an individual item based on the items Id field + /// + /// The type of the Id field + /// The value of the Id field + /// An item + T GetById(TProperty id); + + /// + /// Get an individual item based on the items Id field + /// + /// + /// This overload should be used to get an item for a specific module + /// instance or for a specific portal dependening on how the items in the repository + /// are scoped. This will allow the relevant cache to be searched first. + /// + /// The type of the Id field + /// The value of the Id field + /// The type of the scope field + /// The value of the scope to filter by + /// An item + T GetById(TProperty id, TScopeType scopeValue); + + /// + /// Returns a page of items in the repository as a paged list + /// + /// The page Index to fetch + /// The size of the page to fetch + /// The list of items + IPagedList GetPage(int pageIndex, int pageSize); + + /// + /// Returns a page of items in the repository as a paged list filtered by scope + /// + /// + /// This overload should be used to get a list of items for a specific module + /// instance or for a specific portal dependening on how the items in the repository + /// are scoped. + /// + /// The type of the scope field + /// The value of the scope to filter by + /// The page Index to fetch + /// The size of the page to fetch + /// The list of items + IPagedList GetPage(TScopeType scopeValue, int pageIndex, int pageSize); + + /// + /// Inserts an Item into the repository + /// + /// The item to be inserted + void Insert(T item); + + /// + /// Updates an Item in the repository + /// + /// The item to be updated + void Update(T item); + + /// + /// Update items in the repository based on a sql Condition + /// + /// The sql condition e.g. "SET ArticelName = {0} WHERE ArticleId = {0}" + /// A collection of arguments to be mapped to the tokens in the sqlCondition + void Update(string sqlCondition, params object[] args); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/PetaPoco/PetaPocoDataContext.cs b/DNN Platform/Library/Data/PetaPoco/PetaPocoDataContext.cs new file mode 100644 index 00000000000..dd7e49ce373 --- /dev/null +++ b/DNN Platform/Library/Data/PetaPoco/PetaPocoDataContext.cs @@ -0,0 +1,139 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using DotNetNuke.Common; +using PetaPoco; + +namespace DotNetNuke.Data.PetaPoco +{ + public class PetaPocoDataContext : IDataContext + { + #region Private Members + + private readonly Database _database; + private readonly IMapper _mapper; + + #endregion + + #region Constructors + + public PetaPocoDataContext() + : this(ConfigurationManager.ConnectionStrings[0].Name, String.Empty) + { + } + + public PetaPocoDataContext(string connectionStringName) + : this(connectionStringName, String.Empty) + { + } + + public PetaPocoDataContext(string connectionStringName, string tablePrefix) + { + Requires.NotNullOrEmpty("connectionStringName", connectionStringName); + + _database = new Database(connectionStringName); + _mapper = new PetaPocoMapper(tablePrefix); + } + + #endregion + + #region Implementation of IDataContext + + public void BeginTransaction() + { + _database.BeginTransaction(); + } + + public void Commit() + { + _database.CompleteTransaction(); + } + + public void Execute(CommandType type, string sql, params object[] args) + { + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + _database.Execute(DataUtil.ReplaceTokens(sql), args); + } + + public IEnumerable ExecuteQuery(CommandType type, string sql, params object[] args) + { + PetaPocoMapper.SetMapper(_mapper); + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + return _database.Fetch(DataUtil.ReplaceTokens(sql), args); + } + + public T ExecuteScalar(CommandType type, string sql, params object[] args) + { + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + return _database.ExecuteScalar(DataUtil.ReplaceTokens(sql), args); + } + + public T ExecuteSingleOrDefault(CommandType type, string sql, params object[] args) + { + PetaPocoMapper.SetMapper(_mapper); + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + return _database.SingleOrDefault(DataUtil.ReplaceTokens(sql), args); + } + + public IRepository GetRepository() where T : class + { + return new PetaPocoRepository(_database, _mapper); + } + + public void RollbackTransaction() + { + _database.AbortTransaction(); + } + + #endregion + + #region Implementation of IDisposable + + public void Dispose() + { + _database.Dispose(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/PetaPoco/PetaPocoExt.cs b/DNN Platform/Library/Data/PetaPoco/PetaPocoExt.cs new file mode 100644 index 00000000000..98eef2f1349 --- /dev/null +++ b/DNN Platform/Library/Data/PetaPoco/PetaPocoExt.cs @@ -0,0 +1,58 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Data; + +using PetaPoco; + +namespace DotNetNuke.Data.PetaPoco +{ + public static class PetaPocoExt + { + public static IDataReader ExecuteReader(this Database database, string sql, params object[] args) + { + IDataReader reader; + try + { + database.OpenSharedConnection(); + + using (IDbCommand command = database.CreateCommand(database.Connection, sql, args)) + { + reader = command.ExecuteReader(CommandBehavior.CloseConnection); + database.OnExecutedCommand(command); + } + } + catch (Exception exception) + { + if (database.OnException(exception)) + { + throw; + } + reader = null; + } + return reader; + + } + } +} diff --git a/DNN Platform/Library/Data/PetaPoco/PetaPocoHelper.cs b/DNN Platform/Library/Data/PetaPoco/PetaPocoHelper.cs new file mode 100644 index 00000000000..16d7f734ce1 --- /dev/null +++ b/DNN Platform/Library/Data/PetaPoco/PetaPocoHelper.cs @@ -0,0 +1,120 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Data; + +using DotNetNuke.Common.Utilities; + +using PetaPoco; + +namespace DotNetNuke.Data.PetaPoco +{ + public static class PetaPocoHelper + { + #region Public Methods + + public static void ExecuteNonQuery(string connectionString, CommandType type, string sql, params object[] args) + { + ExecuteNonQuery(connectionString, type, Null.NullInteger, sql, args); + } + + public static void ExecuteNonQuery(string connectionString, CommandType type, int timeout, string sql, params object[] args) + { + var database = new Database(connectionString, "System.Data.SqlClient") { EnableAutoSelect = false }; + + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + if (timeout > 0) + { + database.CommandTimeout = timeout; + } + + database.Execute(sql, args); + } + + public static IDataReader ExecuteReader(string connectionString, CommandType type, string sql, params object[] args) + { + return ExecuteReader(connectionString, type, Null.NullInteger, sql, args); + } + + public static IDataReader ExecuteReader(string connectionString, CommandType type, int timeout, string sql, params object[] args) + { + var database = new Database(connectionString, "System.Data.SqlClient") { EnableAutoSelect = false }; + + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + if (timeout > 0) + { + database.CommandTimeout = timeout; + } + return database.ExecuteReader(sql, args); + } + + public static T ExecuteScalar(string connectionString, CommandType type, string sql, params object[] args) + { + return ExecuteScalar(connectionString, type, Null.NullInteger, sql, args); + } + + public static T ExecuteScalar(string connectionString, CommandType type, int timeout, string sql, params object[] args) + { + var database = new Database(connectionString, "System.Data.SqlClient") { EnableAutoSelect = false }; + + if (type == CommandType.StoredProcedure) + { + sql = DataUtil.GenerateExecuteStoredProcedureSql(sql, args); + } + + if (timeout > 0) + { + database.CommandTimeout = timeout; + } + + return database.ExecuteScalar(sql, args); + } + + public static void ExecuteSQL(string connectionString, string sql) + { + ExecuteSQL(connectionString, sql, Null.NullInteger); + } + + public static void ExecuteSQL(string connectionString, string sql, int timeout) + { + var database = new Database(connectionString, "System.Data.SqlClient") { EnableAutoSelect = false }; + + if (timeout > 0) + { + database.CommandTimeout = timeout; + } + + database.Execute(sql); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Data/PetaPoco/PetaPocoMapper.cs b/DNN Platform/Library/Data/PetaPoco/PetaPocoMapper.cs new file mode 100644 index 00000000000..a32cc2ffa1a --- /dev/null +++ b/DNN Platform/Library/Data/PetaPoco/PetaPocoMapper.cs @@ -0,0 +1,118 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Reflection; +using DotNetNuke.ComponentModel.DataAnnotations; +using PetaPoco; + +#endregion + +namespace DotNetNuke.Data.PetaPoco +{ + public class PetaPocoMapper : IMapper + { + private readonly string _tablePrefix; + + public PetaPocoMapper(string tablePrefix) + { + _tablePrefix = tablePrefix; + } + + #region Implementation of IMapper + + public ColumnInfo GetColumnInfo(PropertyInfo pocoProperty) + { + bool includeColumn = true; + + //Check if the class has the ExplictColumnsAttribute + bool declareColumns = pocoProperty.DeclaringType != null + && pocoProperty.DeclaringType.GetCustomAttributes(typeof(DeclareColumnsAttribute), true).Length > 0; + + if (declareColumns) + { + if (pocoProperty.GetCustomAttributes(typeof(IncludeColumnAttribute), true).Length == 0) + { + includeColumn = false; + } + } + else + { + if (pocoProperty.GetCustomAttributes(typeof(IgnoreColumnAttribute), true).Length > 0) + { + includeColumn = false; + } + } + + ColumnInfo ci = null; + if (includeColumn) + { + ci = ColumnInfo.FromProperty(pocoProperty); + ci.ColumnName = DataUtil.GetColumnName(pocoProperty, ci.ColumnName); + + ci.ResultColumn = (pocoProperty.GetCustomAttributes(typeof(ReadOnlyColumnAttribute), true).Length > 0); + } + + return ci; + } + + public TableInfo GetTableInfo(Type pocoType) + { + TableInfo ti = TableInfo.FromPoco(pocoType); + + //Table Name + ti.TableName = DataUtil.GetTableName(pocoType, ti.TableName + "s"); + + ti.TableName = _tablePrefix + ti.TableName; + + //Primary Key + ti.PrimaryKey = DataUtil.GetPrimaryKeyColumn(pocoType, ti.PrimaryKey); + + ti.AutoIncrement = DataUtil.GetAutoIncrement(pocoType, true); + + return ti; + } + + public Func GetFromDbConverter(PropertyInfo pi, Type SourceType) + { + return null; + } + + public Func GetToDbConverter(PropertyInfo SourceProperty) + { + return null; + } + + #endregion + + public static void SetMapper(IMapper mapper) + { + if(Mappers.GetMapper(typeof(T)) is StandardMapper) + { + Mappers.Register(typeof(T), mapper); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/PetaPoco/PetaPocoRepository.cs b/DNN Platform/Library/Data/PetaPoco/PetaPocoRepository.cs new file mode 100644 index 00000000000..126ff9ddd91 --- /dev/null +++ b/DNN Platform/Library/Data/PetaPoco/PetaPocoRepository.cs @@ -0,0 +1,133 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Collections; +using DotNetNuke.Common; + +using PetaPoco; + +#endregion + +namespace DotNetNuke.Data.PetaPoco +{ + public class PetaPocoRepository : RepositoryBase where T : class + { + private readonly Database _database; + private readonly IMapper _mapper; + + #region Constructors + + public PetaPocoRepository(Database database, IMapper mapper) + { + Requires.NotNull("database", database); + + _database = database; + _mapper = mapper; + + PetaPocoMapper.SetMapper(mapper); + } + + #endregion + + #region IRepository Implementation + + public override void Delete(string sqlCondition, params object[] args) + { + _database.Delete(DataUtil.ReplaceTokens(sqlCondition), args); + } + + public override IEnumerable Find(string sqlCondition, params object[] args) + { + return _database.Fetch(DataUtil.ReplaceTokens(sqlCondition), args); + } + + public override IPagedList Find(int pageIndex, int pageSize, string sqlCondition, params object[] args) + { + //Make sure that the sql Condition contains an ORDER BY Clause + if(!sqlCondition.ToUpperInvariant().Contains("ORDER BY")) + { + sqlCondition = String.Format("{0} ORDER BY {1}", sqlCondition, _mapper.GetTableInfo(typeof(T)).PrimaryKey); + } + Page petaPocoPage = _database.Page(pageIndex + 1, pageSize, DataUtil.ReplaceTokens(sqlCondition), args); + + return new PagedList(petaPocoPage.Items, (int)petaPocoPage.TotalItems, pageIndex, pageSize); + } + + public override void Update(string sqlCondition, params object[] args) + { + _database.Update(DataUtil.ReplaceTokens(sqlCondition), args); + } + + #endregion + + protected override void DeleteInternal(T item) + { + _database.Delete(item); + } + + protected override IEnumerable GetInternal() + { + return _database.Fetch(String.Empty); + } + + protected override IPagedList GetPageInternal(int pageIndex, int pageSize) + { + return Find(pageIndex, pageSize, String.Empty); + } + + protected override IEnumerable GetByScopeInternal(object propertyValue) + { + return _database.Fetch(GetScopeSql(), propertyValue); + } + + protected override IPagedList GetPageByScopeInternal(object propertyValue, int pageIndex, int pageSize) + { + return Find(pageIndex, pageSize, GetScopeSql(), propertyValue); + } + + protected override T GetByIdInternal(object id) + { + return _database.SingleOrDefault(id); + } + + protected override void InsertInternal(T item) + { + _database.Insert(item); + } + + protected override void UpdateInternal(T item) + { + _database.Update(item); + } + + private string GetScopeSql() + { + return String.Format("WHERE {0} = @0", DataUtil.GetColumnName(typeof (T), Scope)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Data/RepositoryBase.cs b/DNN Platform/Library/Data/RepositoryBase.cs new file mode 100644 index 00000000000..119d447ca91 --- /dev/null +++ b/DNN Platform/Library/Data/RepositoryBase.cs @@ -0,0 +1,253 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Collections; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel.DataAnnotations; + +namespace DotNetNuke.Data +{ + public abstract class RepositoryBase : IRepository where T : class + { + #region Constructors + + protected RepositoryBase() + { + Initialize(); + } + + #endregion + + #region IRepository Implementation + + public void Delete(T item) + { + DeleteInternal(item); + ClearCache(item); + } + + public abstract void Delete(string sqlCondition, params object[] args); + + public abstract IEnumerable Find(string sqlCondition, params object[] args); + + public abstract IPagedList Find(int pageIndex, int pageSize, string sqlCondition, params object[] args); + + public IEnumerable Get() + { + return IsCacheable && !IsScoped + ? DataCache.GetCachedData>(CacheArgs, c => GetInternal()) + : GetInternal(); + } + + public IEnumerable Get(TScopeType scopeValue) + { + CheckIfScoped(); + + if(IsCacheable) + { + CacheArgs.CacheKey = String.Format(CacheArgs.CacheKey, scopeValue); + } + + return IsCacheable + ? DataCache.GetCachedData>(CacheArgs, c => GetByScopeInternal(scopeValue)) + : GetByScopeInternal(scopeValue); + } + + public T GetById(TProperty id) + { + return IsCacheable && !IsScoped + ? Get().SingleOrDefault(t => CompareTo(GetPrimaryKey(t), id) == 0) + : GetByIdInternal(id); + } + + public T GetById(TProperty id, TScopeType scopeValue) + { + CheckIfScoped(); + + return Get(scopeValue).SingleOrDefault(t => CompareTo(GetPrimaryKey(t), id) == 0); + } + + public IPagedList GetPage(int pageIndex, int pageSize) + { + return IsCacheable && !IsScoped + ? Get().InPagesOf(pageSize).GetPage(pageIndex) + : GetPageInternal(pageIndex, pageSize); + } + + public IPagedList GetPage(TScopeType scopeValue, int pageIndex, int pageSize) + { + CheckIfScoped(); + + return IsCacheable + ? Get(scopeValue).InPagesOf(pageSize).GetPage(pageIndex) + : GetPageByScopeInternal(scopeValue, pageIndex, pageSize); + } + + public void Insert(T item) + { + InsertInternal(item); + ClearCache(item); + } + + public void Update(T item) + { + UpdateInternal(item); + ClearCache(item); + } + + public abstract void Update(string sqlCondition, params object[] args); + + #endregion + + #region Private Methods + + private void CheckIfScoped() + { + if (!IsScoped) + { + throw new NotSupportedException("This method requires the model to be cacheable and have a cache scope defined"); + } + } + + private void ClearCache(T item) + { + if (IsCacheable) + { + DataCache.RemoveCache(IsScoped + ? String.Format(CacheArgs.CacheKey, GetScopeValue(item)) + : CacheArgs.CacheKey); + } + } + + private void Initialize() + { + var type = typeof (T); + Scope = String.Empty; + IsCacheable = false; + IsScoped = false; + CacheArgs = null; + + var scopeAttribute = DataUtil.GetAttribute(type); + if (scopeAttribute != null) + { + Scope = scopeAttribute.Scope; + } + + IsScoped = (!String.IsNullOrEmpty(Scope)); + + var cacheableAttribute = DataUtil.GetAttribute(type); + if (cacheableAttribute != null) + { + IsCacheable = true; + var cacheKey = !String.IsNullOrEmpty(cacheableAttribute.CacheKey) + ? cacheableAttribute.CacheKey + : String.Format("OR_{0}", type.Name); + var cachePriority = cacheableAttribute.CachePriority; + var cacheTimeOut = cacheableAttribute.CacheTimeOut; + + if (IsScoped) + { + cacheKey += "_" + Scope + "_{0}"; + } + + CacheArgs = new CacheItemArgs(cacheKey, cacheTimeOut, cachePriority); + } + } + + #endregion + + #region Protected Properties + + protected CacheItemArgs CacheArgs { get; private set; } + + protected string Scope { get; private set; } + + protected bool IsCacheable { get; private set; } + + protected bool IsScoped { get; private set; } + + #endregion + + protected int CompareTo(TProperty first, TProperty second) + { + Requires.IsTypeOf("first", first); + Requires.IsTypeOf("second", second); + + var firstComparable = first as IComparable; + var secondComparable = second as IComparable; + +// ReSharper disable PossibleNullReferenceException + return firstComparable.CompareTo(secondComparable); +// ReSharper restore PossibleNullReferenceException + } + + protected TProperty GetPropertyValue(T item, string propertyName) + { + var modelType = typeof(T); + var property = modelType.GetProperty(propertyName); + + return (TProperty)property.GetValue(item, null); + } + + protected TProperty GetPrimaryKey(T item) + { + Type modelType = typeof(T); + + //Get the primary key + var primaryKeyName = DataUtil.GetPrimaryKeyProperty(modelType, String.Empty); + + return GetPropertyValue(item, primaryKeyName); + } + + protected TProperty GetScopeValue(T item) + { + return GetPropertyValue(item, Scope); + } + + #region Abstract Methods + + protected abstract void DeleteInternal(T item); + + protected abstract IEnumerable GetInternal(); + + protected abstract IPagedList GetPageInternal(int pageIndex, int pageSize); + + protected abstract IEnumerable GetByScopeInternal(object propertyValue); + + protected abstract IPagedList GetPageByScopeInternal(object propertyValue, int pageIndex, int pageSize); + + protected abstract T GetByIdInternal(object id); + + protected abstract void InsertInternal(T item); + + protected abstract void UpdateInternal(T item); + + #endregion + } + +} diff --git a/DNN Platform/Library/Data/SqlDataProvider.cs b/DNN Platform/Library/Data/SqlDataProvider.cs new file mode 100644 index 00000000000..c551a55a08d --- /dev/null +++ b/DNN Platform/Library/Data/SqlDataProvider.cs @@ -0,0 +1,390 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text.RegularExpressions; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data.PetaPoco; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Log.EventLog; + +using Microsoft.ApplicationBlocks.Data; + +#endregion + +namespace DotNetNuke.Data +{ + public sealed class SqlDataProvider : DataProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SqlDataProvider)); + #region Private Members + + private const string _scriptDelimiterRegex = "(?<=(?:[^\\w]+|^))GO(?=(?: |\\t)*?(?:\\r?\\n|$))"; + + private static readonly Regex ScriptWithRegex = new Regex("WITH\\s*\\([\\s\\S]*?((PAD_INDEX|ALLOW_ROW_LOCKS|ALLOW_PAGE_LOCKS)\\s*=\\s*(ON|OFF))+[\\s\\S]*?\\)", + RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled); + private static readonly Regex ScriptOnPrimaryRegex = new Regex("(TEXTIMAGE_)*ON\\s*\\[\\s*PRIMARY\\s*\\]", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled); + + #endregion + + #region Public Properties + + public override bool IsConnectionValid + { + get + { + return CanConnect(ConnectionString, DatabaseOwner, ObjectQualifier); + } + } + + public override Dictionary Settings + { + get + { + return ComponentFactory.GetComponentSettings() as Dictionary; + } + } + + #endregion + + #region Private Methods + + private static bool CanConnect(string connectionString, string owner, string qualifier) + { + bool connectionValid = true; + + try + { + PetaPocoHelper.ExecuteReader(connectionString, CommandType.StoredProcedure, owner + qualifier + "GetDatabaseVersion"); + } + catch (SqlException ex) + { + if (ex.Errors.Cast().Any(c => !(c.Number == 2812 && c.Class == 16))) + { + connectionValid = false; + } + } + + return connectionValid; + } + + private string ExecuteScriptInternal(string connectionString, string script) + { + string exceptions = ""; + + string[] sqlStatements = SqlDelimiterRegex.Split(script); + foreach (string statement in sqlStatements) + { + var sql = statement.Trim(); + if (!String.IsNullOrEmpty(sql)) + { + + // script dynamic substitution + sql = DataUtil.ReplaceTokens(sql); + + //Clean up some SQL Azure incompatabilities + var query = GetAzureCompactScript(sql); + + if (query != sql) + { + var props = new LogProperties { new LogDetailInfo("SQL Script Modified", query) }; + + var elc = new EventLogController(); + elc.AddLog(props, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.HOST_ALERT.ToString(), + true); + } + + try + { + Logger.Trace("Executing SQL Script " + query); + + //Create a new connection + var connection = new SqlConnection(connectionString); + //Create a new command (with no timeout) + var command = new SqlCommand(query, connection) { CommandTimeout = 0 }; + + connection.Open(); + command.ExecuteNonQuery(); + connection.Close(); + + } + catch (SqlException objException) + { + Logger.Debug(objException); + + exceptions += objException + Environment.NewLine + Environment.NewLine + query + Environment.NewLine + Environment.NewLine; + } + } + } + + return exceptions; + } + + private IDataReader ExecuteSQLInternal(string connectionString, string sql) + { + try + { + sql = DataUtil.ReplaceTokens(sql); + return PetaPocoHelper.ExecuteReader(connectionString, CommandType.Text, sql); + } + catch + { + //error in SQL query + return null; + } + } + + private string GetConnectionStringUserID() + { + string DBUser = "public"; + + //If connection string does not use integrated security, then get user id. + if (ConnectionString.ToUpper().Contains("USER ID") || ConnectionString.ToUpper().Contains("UID") || ConnectionString.ToUpper().Contains("USER")) + { + string[] ConnSettings = ConnectionString.Split(';'); + + foreach (string s in ConnSettings) + { + if (s != string.Empty) + { + string[] ConnSetting = s.Split('='); + if ("USER ID|UID|USER".Contains(ConnSetting[0].Trim().ToUpper())) + { + DBUser = ConnSetting[1].Trim(); + } + } + } + } + return DBUser; + } + + private string GrantStoredProceduresPermission(string Permission, string LoginOrRole) + { + string SQL = string.Empty; + string Exceptions = string.Empty; + + try + { + //grant rights to a login or role for all stored procedures + SQL += "if exists (select * from dbo.sysusers where name='" + LoginOrRole + "')"; + SQL += " begin"; + SQL += " declare @exec nvarchar(2000) "; + SQL += " declare @name varchar(150) "; + SQL += " declare sp_cursor cursor for select o.name as name "; + SQL += " from dbo.sysobjects o "; + SQL += " where ( OBJECTPROPERTY(o.id, N'IsProcedure') = 1 or OBJECTPROPERTY(o.id, N'IsExtendedProc') = 1 or OBJECTPROPERTY(o.id, N'IsReplProc') = 1 ) "; + SQL += " and OBJECTPROPERTY(o.id, N'IsMSShipped') = 0 "; + SQL += " and o.name not like N'#%%' "; + SQL += " and (left(o.name,len('" + ObjectQualifier + "')) = '" + ObjectQualifier + "' or left(o.name,7) = 'aspnet_') "; + SQL += " open sp_cursor "; + SQL += " fetch sp_cursor into @name "; + SQL += " while @@fetch_status >= 0 "; + SQL += " begin"; + SQL += " select @exec = 'grant " + Permission + " on [' + @name + '] to [" + LoginOrRole + "]'"; + SQL += " execute (@exec)"; + SQL += " fetch sp_cursor into @name "; + SQL += " end "; + SQL += " deallocate sp_cursor"; + SQL += " end "; + + SqlHelper.ExecuteNonQuery(UpgradeConnectionString, CommandType.Text, SQL); + } + catch (SqlException objException) + { + Logger.Debug(objException); + + Exceptions += objException + Environment.NewLine + Environment.NewLine + SQL + Environment.NewLine + Environment.NewLine; + } + return Exceptions; + } + + private string GrantUserDefinedFunctionsPermission(string ScalarPermission, string TablePermission, string LoginOrRole) + { + string SQL = string.Empty; + string Exceptions = string.Empty; + try + { + //grant EXECUTE rights to a login or role for all functions + SQL += "if exists (select * from dbo.sysusers where name='" + LoginOrRole + "')"; + SQL += " begin"; + SQL += " declare @exec nvarchar(2000) "; + SQL += " declare @name varchar(150) "; + SQL += " declare @isscalarfunction int "; + SQL += " declare @istablefunction int "; + SQL += " declare sp_cursor cursor for select o.name as name, OBJECTPROPERTY(o.id, N'IsScalarFunction') as IsScalarFunction "; + SQL += " from dbo.sysobjects o "; + SQL += " where ( OBJECTPROPERTY(o.id, N'IsScalarFunction') = 1 OR OBJECTPROPERTY(o.id, N'IsTableFunction') = 1 ) "; + SQL += " and OBJECTPROPERTY(o.id, N'IsMSShipped') = 0 "; + SQL += " and o.name not like N'#%%' "; + SQL += " and (left(o.name,len('" + ObjectQualifier + "')) = '" + ObjectQualifier + "' or left(o.name,7) = 'aspnet_') "; + SQL += " open sp_cursor "; + SQL += " fetch sp_cursor into @name, @isscalarfunction "; + SQL += " while @@fetch_status >= 0 "; + SQL += " begin "; + SQL += " if @IsScalarFunction = 1 "; + SQL += " begin"; + SQL += " select @exec = 'grant " + ScalarPermission + " on [' + @name + '] to [" + LoginOrRole + "]'"; + SQL += " execute (@exec)"; + SQL += " fetch sp_cursor into @name, @isscalarfunction "; + SQL += " end "; + SQL += " else "; + SQL += " begin"; + SQL += " select @exec = 'grant " + TablePermission + " on [' + @name + '] to [" + LoginOrRole + "]'"; + SQL += " execute (@exec)"; + SQL += " fetch sp_cursor into @name, @isscalarfunction "; + SQL += " end "; + SQL += " end "; + SQL += " deallocate sp_cursor"; + SQL += " end "; + + SqlHelper.ExecuteNonQuery(UpgradeConnectionString, CommandType.Text, SQL); + } + catch (SqlException objException) + { + Logger.Debug(objException); + + Exceptions += objException + Environment.NewLine + Environment.NewLine + SQL + Environment.NewLine + Environment.NewLine; + } + return Exceptions; + } + + private string GetAzureCompactScript(string script) + { + if (ScriptWithRegex.IsMatch(script)) + { + script = ScriptWithRegex.Replace(script, string.Empty); + } + + if (ScriptOnPrimaryRegex.IsMatch(script)) + { + script = ScriptOnPrimaryRegex.Replace(script, string.Empty); + } + + return script; + } + + private Regex SqlDelimiterRegex + { + get + { + var objRegex = (Regex)DataCache.GetCache("SQLDelimiterRegex"); + if (objRegex == null) + { + objRegex = new Regex(_scriptDelimiterRegex, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline); + DataCache.SetCache("SQLDelimiterRegex", objRegex); + } + return objRegex; + } + } + + #endregion + + #region Abstract Methods + + public override void ExecuteNonQuery(string procedureName, params object[] commandParameters) + { + PetaPocoHelper.ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, DatabaseOwner + ObjectQualifier + procedureName, commandParameters); + } + + public override IDataReader ExecuteReader(string procedureName, params object[] commandParameters) + { + return PetaPocoHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, DatabaseOwner + ObjectQualifier + procedureName, commandParameters); + } + + public override T ExecuteScalar(string procedureName, params object[] commandParameters) + { + return PetaPocoHelper.ExecuteScalar(ConnectionString, CommandType.StoredProcedure, DatabaseOwner + ObjectQualifier + procedureName, commandParameters); + } + + public override string ExecuteScript(string script) + { + string exceptions = ExecuteScriptInternal(UpgradeConnectionString, script); + + //if the upgrade connection string is specified or or db_owner setting is not set to dbo + if (UpgradeConnectionString != ConnectionString || DatabaseOwner.Trim().ToLower() != "dbo.") + { + try + { + //grant execute rights to the public role or userid for all stored procedures. This is + //necesary because the UpgradeConnectionString will create stored procedures + //which restrict execute permissions for the ConnectionString user account. This is also + //necessary when db_owner is not set to "dbo" + exceptions += GrantStoredProceduresPermission("EXECUTE", GetConnectionStringUserID()); + } + catch (SqlException objException) + { + Logger.Debug(objException); + + exceptions += objException + Environment.NewLine + Environment.NewLine + script + Environment.NewLine + Environment.NewLine; + } + + try + { + //grant execute or select rights to the public role or userid for all user defined functions based + //on what type of function it is (scalar function or table function). This is + //necesary because the UpgradeConnectionString will create user defined functions + //which restrict execute permissions for the ConnectionString user account. This is also + //necessary when db_owner is not set to "dbo" + exceptions += GrantUserDefinedFunctionsPermission("EXECUTE", "SELECT", GetConnectionStringUserID()); + } + catch (SqlException objException) + { + Logger.Debug(objException); + + exceptions += objException + Environment.NewLine + Environment.NewLine + script + Environment.NewLine + Environment.NewLine; + } + } + return exceptions; + } + + public override string ExecuteScript(string connectionString, string script) + { + return ExecuteScriptInternal(connectionString, script); + } + + public override IDataReader ExecuteSQL(string sql) + { + return ExecuteSQLInternal(ConnectionString, sql); + } + + public override IDataReader ExecuteSQLTemp(string connectionString, string sql) + { + return ExecuteSQLInternal(connectionString, sql); + } + + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/DotNetNuke.Library.csproj b/DNN Platform/Library/DotNetNuke.Library.csproj new file mode 100644 index 00000000000..fd5923e1b85 --- /dev/null +++ b/DNN Platform/Library/DotNetNuke.Library.csproj @@ -0,0 +1,1612 @@ + + + + Local + 9.0.30729 + 2.0 + {6B29ADED-7B56-4484-BEA5-C0E09079535B} + Debug + AnyCPU + DotNetNuke + JScript + Grid + IE50 + Library + v4.0 + SAK + SAK + SAK + SAK + DotNetNuke + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + + bin\ + DotNetNuke.xml + true + true + 4 + full + TRACE;DEBUG + AllRules.ruleset + 1591, 3001, 3002, 1574, 1573 + default + + + bin\ + DotNetNuke.xml + true + true + 4 + pdbonly + AllRules.ruleset + 1591, 3001, 3002, 1574, 1573 + true + + + + + + + + + + + AllRules.ruleset + + + AllRules.ruleset + + + + + ..\Components\Log4Net\bin\DotNetNuke.Log4Net.dll + + + ..\Controls\DotNetNuke.WebControls\bin\DotNetNuke.WebControls.dll + False + + + ..\Controls\DotNetNuke.WebUtility\bin\DotNetNuke.WebUtility.dll + False + + + ..\Components\Lucene.Net\bin\Lucene.Net.dll + + + ..\Components\Lucene.Net.Contrib\bin\Lucene.Net.Contrib.FastVectorHighlighter.dll + + + False + ..\Components\DataAccessBlock\bin\Microsoft.ApplicationBlocks.Data.dll + False + + + + + ..\Components\PetaPoco\bin\PetaPoco.dll + False + + + ..\Components\SharpZipLib\bin\SharpZipLib.dll + False + + + + + 3.5 + + + + 3.5 + + + + + + + + + + + 3.5 + + + + False + ..\Components\MVC4\System.Web.WebPages.dll + + + + + ..\Components\Telerik\bin\Telerik.Web.UI.dll + False + + + + + + + + + + + + + + + + + Code + + + + Code + + + + + + + + + + + + + + + + + Code + + + + Code + + + Code + + + + + + + + Code + + + + + + + Code + + + + + + + + + + Code + + + Code + + + Code + + + Code + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + Code + + + Code + + + Code + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + ASPXCodeBehind + + + Code + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + Code + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + + + Code + + + Code + + + Code + + + Code + + + + + + Code + + + Code + + + + Code + + + + + + + + + + + Code + + + + Code + + + + + + + ASPXCodeBehind + + + + + ASPXCodeBehind + + + Code + + + + + + + ASPXCodeBehind + + + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + Code + + + Code + + + Code + + + Code + + + + + Code + + + Code + + + + Code + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + Code + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + Code + + + + + + + + + + + + + Code + + + + + + + + + + + ASPXCodeBehind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + + + ASPXCodeBehind + + + + + + + + ASPXCodeBehind + + + + + + + + + + + + + + + + ASPXCodeBehind + + + + + Code + + + ASPXCodeBehind + + + + ASPXCodeBehind + + + + ASPXCodeBehind + + + + + + + + ASPXCodeBehind + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + Code + + + + Code + + + + ASPXCodeBehind + + + Code + + + ASPXCodeBehind + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + Code + + + + + + + + + Code + + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {ca056730-5759-41f8-a6c1-420f9c0c63e7} + CountryListBox + + + {ddf18e36-41a0-4ca7-a098-78ca6e6f41c1} + DotNetNuke.Instrumentation + + + {537b45eb-2ec3-4849-bc6b-d761f43674a5} + DotNetNuke.Web.Client + + + {86af9531-d270-4c18-a8b9-c67a8782af69} + DotNetNuke.Syndication + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DNN Platform/Library/Entities/BaseEntityInfo.cs b/DNN Platform/Library/Entities/BaseEntityInfo.cs new file mode 100644 index 00000000000..652d9305050 --- /dev/null +++ b/DNN Platform/Library/Entities/BaseEntityInfo.cs @@ -0,0 +1,171 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities + /// Class : BaseEntityInfo + /// ----------------------------------------------------------------------------- + /// + /// BaseEntityInfo provides auditing fields for Core tables. + /// + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public abstract class BaseEntityInfo + { + protected BaseEntityInfo() + { + CreatedByUserID = Null.NullInteger; + LastModifiedByUserID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the CreatedByUserID + /// + /// An Integer + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false), XmlIgnore] + public int CreatedByUserID { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the CreatedOnDate + /// + /// A DateTime + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false), XmlIgnore] + public DateTime CreatedOnDate { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the LastModifiedByUserID + /// + /// An Integer + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false), XmlIgnore] + public int LastModifiedByUserID { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the LastModifiedOnDate + /// + /// A DateTime + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false), XmlIgnore] + public DateTime LastModifiedOnDate { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the UserInfo object associated with this user + /// + /// The PortalID associated with the desired user + /// A UserInfo object + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + public UserInfo CreatedByUser(int portalId) + { + if (CreatedByUserID > Null.NullInteger) + { + UserInfo user = UserController.GetUserById(portalId, CreatedByUserID); + return user; + } + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the UserInfo object associated with this user + /// + /// The PortalID associated with the desired user + /// A UserInfo object + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + public UserInfo LastModifiedByUser(int portalId) + { + if (LastModifiedByUserID > Null.NullInteger) + { + UserInfo user = UserController.GetUserById(portalId, LastModifiedByUserID); + return user; + } + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Fills a BaseEntityInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [jlucarino] 02/20/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected virtual void FillInternal(IDataReader dr) + { + CreatedByUserID = Null.SetNullInteger(dr["CreatedByUserID"]); + CreatedOnDate = Null.SetNullDateTime(dr["CreatedOnDate"]); + LastModifiedByUserID = Null.SetNullInteger(dr["LastModifiedByUserID"]); + LastModifiedOnDate = Null.SetNullDateTime(dr["LastModifiedOnDate"]); + } + + /// + /// method used by cbo to fill readonly properties ignored by HydrateObject reflection + /// + /// the data reader to use + /// + internal void FillBaseProperties(IDataReader dr) + { + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Entities/ConfigurationSetting.cs b/DNN Platform/Library/Entities/ConfigurationSetting.cs new file mode 100644 index 00000000000..4917197f608 --- /dev/null +++ b/DNN Platform/Library/Entities/ConfigurationSetting.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities +{ + public class ConfigurationSetting + { + public bool IsSecure { get; set; } + + public string Key { get; set; } + + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/AttachmentController.cs b/DNN Platform/Library/Entities/Content/AttachmentController.cs new file mode 100644 index 00000000000..c75532d50af --- /dev/null +++ b/DNN Platform/Library/Entities/Content/AttachmentController.cs @@ -0,0 +1,226 @@ +#region Copyright +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.FileSystem; + +namespace DotNetNuke.Entities.Content +{ + /// Implementation of . + public class AttachmentController : IAttachmentController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AttachmentController)); + public AttachmentController() + : this(Util.GetContentController()) + { + } + + public AttachmentController(IContentController contentController) + { + _contentController = contentController; + } + + private readonly IContentController _contentController; + + #region Implementation of IFileController + + private void AddToContent(int contentItemId, Action action) + { + var contentItem = _contentController.GetContentItem(contentItemId); + + action(contentItem); + + _contentController.UpdateContentItem(contentItem); + } + + public void AddFileToContent(int contentItemId, IFileInfo fileInfo) + { + AddFilesToContent(contentItemId, new[] { fileInfo }); + } + + public void AddFilesToContent(int contentItemId, IEnumerable fileInfo) + { + AddToContent(contentItemId, contentItem => contentItem.Files.AddRange(fileInfo)); + } + + public void AddVideoToContent(int contentItemId, IFileInfo fileInfo) + { + AddVideosToContent(contentItemId, new[] { fileInfo }); + } + + public void AddVideosToContent(int contentItemId, IEnumerable fileInfo) + { + AddToContent(contentItemId, contentItem => contentItem.Videos.AddRange(fileInfo)); + } + + public void AddImageToContent(int contentItemId, IFileInfo fileInfo) + { + AddImagesToContent(contentItemId, new[] { fileInfo }); + } + + public void AddImagesToContent(int contentItemId, IEnumerable fileInfo) + { + AddToContent(contentItemId, contentItem => contentItem.Images.AddRange(fileInfo)); + } + + public IList GetVideosByContent(int contentItemId) + { + var files = GetFilesByContent(contentItemId, VideoKey); + + return files.Select(fileId => FileManager.Instance.GetFile(fileId)).ToList(); + } + + public IList GetImagesByContent(int contentItemId) + { + var files = GetFilesByContent(contentItemId, ImageKey); + + return files.Select(fileId => FileManager.Instance.GetFile(fileId)).ToList(); + } + + public IList GetFilesByContent(int contentItemId) + { + var files = GetFilesByContent(contentItemId, FilesKey); + + return files.Select(fileId => FileManager.Instance.GetFile(fileId)).ToList(); + } + + #endregion + + #region Internal utility methods + + private static void SerializeToMetadata(IList files, NameValueCollection nvc, string key) + { + var remove = !files.Any(); + if (remove == false) + { + var serialized = SerializeFileInfo(files); + + if (string.IsNullOrEmpty(serialized)) + { + remove = true; + } + else + { + nvc[key] = serialized; + } + } + + if (remove) + { + nvc.Remove(key); + } + } + + internal static void SerializeAttachmentMetadata(ContentItem contentItem) + { + SerializeToMetadata(contentItem.Files, contentItem.Metadata, FilesKey); + SerializeToMetadata(contentItem.Videos, contentItem.Metadata, VideoKey); + SerializeToMetadata(contentItem.Images, contentItem.Metadata, ImageKey); + } + + private IEnumerable GetFilesByContent(int contentItemId, string type) + { + var contentItem = _contentController.GetContentItem(contentItemId); + if (contentItem == null) + { + throw new ApplicationException(string.Format("Cannot find ContentItem ID {0}", contentItemId)); + } + + var serialized = contentItem.Metadata[type]; + + if (string.IsNullOrEmpty(serialized)) + { + return new int[0]; + } + + try + { + return serialized.FromJson().ToArray(); + } + catch (FormatException ex) + { + throw new ApplicationException( + string.Format("ContentItem metadata has become corrupt (ID {0}): invalid file ID", contentItemId), ex); + } + } + + internal static IEnumerable DeserializeFileInfo(string content) + { + if (string.IsNullOrEmpty(content)) + { + yield break; + } + + foreach (var file in content.FromJson().ToArray()) + { + IFileInfo fileInfo = null; + try + { + fileInfo = FileManager.Instance.GetFile(file); + } + catch + { + // throw new ApplicationException(string.Format("Error loading file properties for FileID '{0}'", file), ex); + + // On second thought, I don't know how much sense it makes to be throwing an exception here. If the file + // has been deleted or is otherwise unavailable, there's really no reason we can't continue on handling the + // ContentItem without its attachment. Better than the yellow screen of death? --cbond + + Logger.WarnFormat("Unable to load file properties for File ID {0}", file); + } + + if (fileInfo != null) + { + yield return fileInfo; + } + } + } + + internal static string SerializeFileInfo(IEnumerable files) + { + var fileList = files.Select(x => x.FileId).ToArray(); + if (fileList.Length == 0) + { + return null; + } + + return fileList.ToJson(); + } + + #endregion + + #region Private + + internal const string FilesKey = "Files"; + internal const string ImageKey = "Images"; + internal const string VideoKey = "Videos"; + internal const string TitleKey = "Title"; + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Common/ContentExtensions.cs b/DNN Platform/Library/Entities/Content/Common/ContentExtensions.cs new file mode 100644 index 00000000000..76f5d0980a5 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Common/ContentExtensions.cs @@ -0,0 +1,223 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + [Obsolete("Moving ContentExtensions to the DotNetNuke.Entities.Content namespace was an error. Please use DotNetNuke.Entities.Content.Common.ContentExtensions")] + public static class ContentExtensions + { + //only forwarding public methods that existed as of 6.1.0 + //calls to internal methods will be fixed in the source + public static string ToDelimittedString(this List terms, string delimiter) + { + return Common.ContentExtensions.ToDelimittedString(terms, delimiter); + } + + public static string ToDelimittedString(this List terms, string format, string delimiter) + { + return Common.ContentExtensions.ToDelimittedString(terms, format, delimiter); + } + } +} + +namespace DotNetNuke.Entities.Content.Common +{ + /// + /// Extension methods for Term, Vocabulary, ContentItem. + /// + /// + public static class ContentExtensions + { + #region "Term Extensions" + + /// + /// Gets the child terms. + /// + /// The term. + /// The term id. + /// The vocabulary id. + /// term collection which's parent is the specific term. + internal static List GetChildTerms(this Term Term, int termId, int vocabularyId) + { + ITermController ctl = Util.GetTermController(); + + IQueryable terms = from term in ctl.GetTermsByVocabulary(vocabularyId) where term.ParentTermId == termId select term; + + return terms.ToList(); + } + + /// + /// Gets the vocabulary. + /// + /// The term. + /// The vocabulary id. + /// Vocabulary + internal static Vocabulary GetVocabulary(this Term term, int vocabularyId) + { + IVocabularyController ctl = Util.GetVocabularyController(); + + return (from v in ctl.GetVocabularies() where v.VocabularyId == vocabularyId select v).SingleOrDefault(); + } + + /// + /// Toes the delimitted string. + /// + /// The terms. + /// The delimitter. + /// terms' name as a string and split with the given delimitter order by name A-Z. + public static string ToDelimittedString(this List terms, string delimitter) + { + var sb = new StringBuilder(); + if (terms != null) + { + foreach (Term _Term in (from term in terms orderby term.Name ascending select term)) + { + if (sb.Length > 0) + { + sb.Append(delimitter); + } + sb.Append(_Term.Name); + } + } + return sb.ToString(); + } + + /// + /// Toes the delimitted string. + /// + /// The terms. + /// The format. + /// The delimitter. + /// formatted terms' name as a string and split with the given delimitter order by name A-Z. + public static string ToDelimittedString(this List terms, string format, string delimitter) + { + var sb = new StringBuilder(); + if (terms != null) + { + foreach (Term _Term in (from term in terms orderby term.Name ascending select term)) + { + if (sb.Length > 0) + { + sb.Append(delimitter); + } + sb.Append(string.Format(format, _Term.Name)); + } + } + return sb.ToString(); + } + + #endregion + + #region "Vocabulary Extensions" + + /// + /// Gets the type of the scope. + /// + /// The voc. + /// The scope type id. + /// scope type. + internal static ScopeType GetScopeType(this Vocabulary voc, int scopeTypeId) + { + IScopeTypeController ctl = Util.GetScopeTypeController(); + + return ctl.GetScopeTypes().Where(s => s.ScopeTypeId == scopeTypeId).SingleOrDefault(); + } + + /// + /// Gets the terms by vocabularyId. + /// + /// The voc. + /// The vocabulary id. + /// term collection. + internal static List GetTerms(this Vocabulary voc, int vocabularyId) + { + ITermController ctl = Util.GetTermController(); + + return ctl.GetTermsByVocabulary(vocabularyId).ToList(); + } + + #endregion + + #region "ContentItem Extensions" + + /// + /// Gets the meta data. + /// + /// The item. + /// The content item id. + /// meta data collection + internal static NameValueCollection GetMetaData(this ContentItem item, int contentItemId) + { + IContentController ctl = Util.GetContentController(); + + NameValueCollection _MetaData; + if (contentItemId == Null.NullInteger) + { + _MetaData = new NameValueCollection(); + } + else + { + _MetaData = ctl.GetMetaData(contentItemId); + } + + return _MetaData; + } + + /// + /// Gets the terms by content item id. + /// + /// The item. + /// The content item id. + /// term collection + internal static List GetTerms(this ContentItem item, int contentItemId) + { + ITermController ctl = Util.GetTermController(); + + List _Terms = null; + if (contentItemId == Null.NullInteger) + { + _Terms = new List(); + } + else + { + _Terms = ctl.GetTermsByContent(contentItemId).ToList(); + } + + return _Terms; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Common/ContentItemEqualityComparer.cs b/DNN Platform/Library/Entities/Content/Common/ContentItemEqualityComparer.cs new file mode 100644 index 00000000000..1a02112cf14 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Common/ContentItemEqualityComparer.cs @@ -0,0 +1,41 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Content.Common +{ + internal class ContentItemEqualityComparer : IEqualityComparer + { + #region Implementation of IEqualityComparer + + public bool Equals(ContentItem x, ContentItem y) + { + return x.ContentItemId == y.ContentItemId; + } + + public int GetHashCode(ContentItem obj) + { + return obj.ContentItemId.GetHashCode(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Common/NameValueEqualityComparer.cs b/DNN Platform/Library/Entities/Content/Common/NameValueEqualityComparer.cs new file mode 100644 index 00000000000..ff83958bf1b --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Common/NameValueEqualityComparer.cs @@ -0,0 +1,41 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Content.Common +{ + internal class NameValueEqualityComparer : IEqualityComparer> + { + #region Implementation of IEqualityComparer> + + public bool Equals(KeyValuePair x, KeyValuePair y) + { + return x.Key == y.Key && x.Value == y.Value; + } + + public int GetHashCode(KeyValuePair obj) + { + return obj.Key.GetHashCode() ^ obj.Value.GetHashCode(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Common/Util.cs b/DNN Platform/Library/Entities/Content/Common/Util.cs new file mode 100644 index 00000000000..2f311cb5816 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Common/Util.cs @@ -0,0 +1,116 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Entities.Content.Taxonomy; + +#endregion + +namespace DotNetNuke.Entities.Content.Common +{ + /// + /// Utility Methods for Content. + /// + public static class Util + { + /// + /// Gets the data service. + /// + /// data service instance from ComponentFactory. + public static IDataService GetDataService() + { + var ds = ComponentFactory.GetComponent(); + + if (ds == null) + { + ds = new DataService(); + ComponentFactory.RegisterComponentInstance(ds); + } + return ds; + } + + /// + /// Gets the content controller. + /// + /// ContentController from ComponentFactory. + public static IContentController GetContentController() + { + var ctl = ComponentFactory.GetComponent(); + + if (ctl == null) + { + ctl = new ContentController(); + ComponentFactory.RegisterComponentInstance(ctl); + } + return ctl; + } + + /// + /// Gets the scope type controller. + /// + /// ScopeTypeController from ComponentFactory. + public static IScopeTypeController GetScopeTypeController() + { + var ctl = ComponentFactory.GetComponent(); + + if (ctl == null) + { + ctl = new ScopeTypeController(); + ComponentFactory.RegisterComponentInstance(ctl); + } + return ctl; + } + + /// + /// Gets the term controller. + /// + /// TermController from ComponentFactory. + public static ITermController GetTermController() + { + var ctl = ComponentFactory.GetComponent(); + + if (ctl == null) + { + ctl = new TermController(); + ComponentFactory.RegisterComponentInstance(ctl); + } + return ctl; + } + + /// + /// Gets the vocabulary controller. + /// + /// VocabularyController from ComponentFactory. + public static IVocabularyController GetVocabularyController() + { + var ctl = ComponentFactory.GetComponent(); + + if (ctl == null) + { + ctl = new VocabularyController(); + ComponentFactory.RegisterComponentInstance(ctl); + } + return ctl; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/ContentController.cs b/DNN Platform/Library/Entities/Content/ContentController.cs new file mode 100644 index 00000000000..f65db895493 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/ContentController.cs @@ -0,0 +1,258 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Data; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + public class ContentController : IContentController + { + private readonly IDataService _dataService; + + #region Constructors + + public ContentController() : this(Util.GetDataService()) + { + } + + public ContentController(IDataService dataService) + { + _dataService = dataService; + } + + #endregion + + #region Public Methods + + public int AddContentItem(ContentItem contentItem) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + + contentItem.ContentItemId = _dataService.AddContentItem(contentItem, UserController.GetCurrentUserInfo().UserID); + + SaveMetadataDelta(contentItem); + + return contentItem.ContentItemId; + } + + public void DeleteContentItem(ContentItem contentItem) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + Requires.PropertyNotNegative("contentItem", "ContentItemId", contentItem.ContentItemId); + + _dataService.DeleteContentItem(contentItem.ContentItemId); + } + + public void DeleteContentItem(int contentItemId) + { + Requires.NotNegative("contentItemId", contentItemId); + + _dataService.DeleteContentItem(contentItemId); + } + + public ContentItem GetContentItem(int contentItemId) + { + //Argument Contract + Requires.NotNegative("contentItemId", contentItemId); + + return CBO.FillObject(_dataService.GetContentItem(contentItemId)); + } + + public IQueryable GetContentItems(int contentTypeId, int tabId, int moduleId) + { + return CBO.FillQueryable(_dataService.GetContentItems(contentTypeId, tabId, moduleId)); + } + + public IQueryable GetContentItemsByTerm(string term) + { + //Argument Contract + Requires.NotNullOrEmpty("term", term); + + return CBO.FillQueryable(_dataService.GetContentItemsByTerm(term)); + } + + public IQueryable GetContentItemsByTerm(Term term) + { + return GetContentItemsByTerm(term.Name); + } + + public IQueryable GetContentItemsByContentType(int contentTypeId) + { + return CBO.FillQueryable(_dataService.GetContentItemsByContentType(contentTypeId)); + } + + /// Get a list of content items by ContentType. + public IQueryable GetContentItemsByContentType(ContentType contentType) + { + return CBO.FillQueryable(_dataService.GetContentItemsByContentType(contentType.ContentTypeId)); + } + + public IQueryable GetContentItemsByTerms(IList terms) + { + return GetContentItemsByTerms(terms.Select(t => t.Name).ToArray()); + } + + public IQueryable GetContentItemsByTerms(string[] terms) + { + var union = new List(); + + union = terms.Aggregate(union, + (current, term) => + !current.Any() + ? GetContentItemsByTerm(term).ToList() + : current.Intersect(GetContentItemsByTerm(term), new ContentItemEqualityComparer()).ToList()); + + return union.AsQueryable(); + } + + public IQueryable GetContentItemsByTabId(int tabId) + { + return CBO.FillQueryable(_dataService.GetContentItemsByTabId(tabId)); + } + + public IQueryable GetContentItemsByVocabularyId(int vocabularyId) + { + return CBO.FillQueryable(_dataService.GetContentItemsByVocabularyId(vocabularyId)); + } + + public IQueryable GetUnIndexedContentItems() + { + return CBO.FillQueryable(_dataService.GetUnIndexedContentItems()); + } + + public IQueryable GetContentItemsByModuleId(int moduleId) + { + return CBO.FillQueryable(_dataService.GetContentItemsByModuleId(moduleId)); + } + + public void UpdateContentItem(ContentItem contentItem) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + Requires.PropertyNotNegative("contentItem", "ContentItemId", contentItem.ContentItemId); + + AttachmentController.SerializeAttachmentMetadata(contentItem); + + SaveMetadataDelta(contentItem); + + _dataService.UpdateContentItem(contentItem, UserController.GetCurrentUserInfo().UserID); + } + + public void AddMetaData(ContentItem contentItem, string name, string value) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + Requires.PropertyNotNegative("contentItem", "ContentItemId", contentItem.ContentItemId); + Requires.NotNullOrEmpty("name", name); + + _dataService.AddMetaData(contentItem, name, value); + } + + public void DeleteMetaData(ContentItem contentItem, string name, string value) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + Requires.PropertyNotNegative("contentItem", "ContentItemId", contentItem.ContentItemId); + Requires.NotNullOrEmpty("name", name); + + _dataService.DeleteMetaData(contentItem, name, value); + } + + public void DeleteMetaData(ContentItem contentItem, string name) + { + if (contentItem.Metadata.AllKeys.Contains(name)) + { + DeleteMetaData(contentItem, name, contentItem.Metadata[name]); + } + } + + public NameValueCollection GetMetaData(int contentItemId) + { + //Argument Contract + Requires.NotNegative("contentItemId", contentItemId); + + var metadata = new NameValueCollection(); + + using (var dr = _dataService.GetMetaData(contentItemId)) + { + if (dr != null) + { + while (dr.Read()) + { + metadata.Add(dr.GetString(0), dr.GetString(1)); + } + } + } + + return metadata; + } + + private void SaveMetadataDelta(ContentItem contentItem) + { + var persisted = GetMetaData(contentItem.ContentItemId); + + var lh = persisted.AllKeys.ToDictionary(x => x, x => persisted[x]); + + var rh = contentItem.Metadata.AllKeys.ToDictionary(x => x, x => contentItem.Metadata[x]); + + if (!MetaDataChanged(lh, rh)) + { + return; + } + + // Items in the database but missing from the parameter (have been deleted). + var deleted = lh.Except(rh).ToArray(); + + // Items included in the object but missing from the database (newly added). + var added = rh.Except(lh).ToArray(); + + _dataService.SynchronizeMetaData(contentItem, added, deleted); + } + + private static bool MetaDataChanged( + IEnumerable> lh, + IEnumerable> rh) + { + return lh.SequenceEqual(rh, new NameValueEqualityComparer()) == false; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/ContentItem.cs b/DNN Platform/Library/Entities/Content/ContentItem.cs new file mode 100644 index 00000000000..ebecdcfbcf2 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/ContentItem.cs @@ -0,0 +1,335 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Data; +using System.Linq; +using System.Web.Script.Serialization; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + /// + /// The ContentItem class which itself inherits from BaseEntityInfo paves the way for easily adding support for taxonomy, + /// tagging and other ContentItem dependant features to your DotNetNuke extensions. + /// + /// + /// + /// Content Items are a collection of individual pieces of content in a DotNetNuke site. Each content item is associated with a single Content Type. + /// + /// + /// Only modules that implement content items (done so by the module developers) can take advantage of some of its benefits, such as Taxonomy. + /// + /// + /// Because ContentItem already implements IHydratable, you will not do so in your custom entity class. Instead, + /// you will need to create overrides of the KeyID property and the Fill method already implemented in the ContentItem class. + /// Don't forget to call ContentItem's FillInternal method in your Fill method override. + /// + /// + /// + /// + /// [Serializable] + /// public class DesktopModuleInfo : ContentItem, IXmlSerializable + /// { + /// #region IHydratable Members + /// + /// public override void Fill(IDataReader dr) + /// { + /// DesktopModuleID = Null.SetNullInteger(dr["DesktopModuleID"]); + /// PackageID = Null.SetNullInteger(dr["PackageID"]); + /// ModuleName = Null.SetNullString(dr["ModuleName"]); + /// FriendlyName = Null.SetNullString(dr["FriendlyName"]); + /// Description = Null.SetNullString(dr["Description"]); + /// FolderName = Null.SetNullString(dr["FolderName"]); + /// Version = Null.SetNullString(dr["Version"]); + /// base.FillInternal(dr); + /// } + /// + /// #endregion + /// } + /// + /// + [Serializable] + public class ContentItem : BaseEntityInfo, IHydratable + { + private NameValueCollection _metadata; + + private List _terms; + + private List _files; + private List _videos; + private List _images; + + public ContentItem() + { + TabID = Null.NullInteger; + ModuleID = Null.NullInteger; + ContentTypeId = Null.NullInteger; + ContentItemId = Null.NullInteger; + StateID = Null.NullInteger; + } + + #region Public Properties + + /// + /// Gets or sets the content item id. + /// + /// + /// The content item id. + /// + [XmlIgnore] + [ScriptIgnore] + public int ContentItemId { get; set; } + + /// + /// Gets or sets the content. + /// + /// + /// The content. + /// + [XmlElement("content")] + public string Content { get; set; } + + /// + /// Gets or sets the content key. + /// + /// + /// The content key. + /// + [XmlElement("contentKey")] + public string ContentKey { get; set; } + + /// + /// Gets or sets the content type id. + /// + /// + /// The content type id. + /// + /// + [XmlIgnore] + [ScriptIgnore] + public int ContentTypeId { get; set; } + + /// + /// Gets or sets a value indicating whether this is indexed. + /// + /// + /// true if indexed; otherwise, false. + /// + [XmlIgnore] + [ScriptIgnore] + public bool Indexed { get; set; } + + /// + /// Gets the metadata. + /// + /// metadata collection + [XmlIgnore] + [ScriptIgnore] + public NameValueCollection Metadata + { + get + { + return _metadata ?? (_metadata = this.GetMetaData(ContentItemId)); + } + } + + /// + /// Gets or sets the module ID. + /// + /// + /// The module ID. + /// + [XmlElement("moduleID")] + public int ModuleID { get; set; } + + /// + /// Gets or sets the tab ID. + /// + /// + /// The tab ID. + /// + [XmlElement("tabid")] + public int TabID { get; set; } + + /// + /// Gets the terms. + /// + /// Terms Collection + [XmlIgnore] + [ScriptIgnore] + public List Terms + { + get + { + return _terms ?? (_terms = this.GetTerms(ContentItemId)); + } + } + + /// The title of the ContentItem. + [XmlElement("contentTitle")] + public string ContentTitle + { + get + { + return Metadata[AttachmentController.TitleKey]; + } + set + { + Metadata[AttachmentController.TitleKey] = value; + } + } + + /// + /// Files that are attached to this ContentItem. + /// + [XmlIgnore] + [ScriptIgnore] + public List Files + { + get { return _files ?? (_files = AttachmentController.DeserializeFileInfo(Metadata[AttachmentController.FilesKey]).ToList()); } + } + + /// + /// Video files attached to this ContentItem. + /// + [XmlIgnore] + [ScriptIgnore] + public List Videos + { + get { return _videos ?? (_videos = AttachmentController.DeserializeFileInfo(Metadata[AttachmentController.VideoKey]).ToList()); } + } + + /// + /// Images associated with this ContentItem. + /// + [XmlIgnore] + [ScriptIgnore] + public List Images + { + get { return _images ?? (_images = AttachmentController.DeserializeFileInfo(Metadata[AttachmentController.ImageKey]).ToList()); } + } + + + /// + /// Gets or sets the Content Workflow State ID. + /// + /// + /// The Content Workflow State ID. + /// + [XmlIgnore] + public int StateID { get; set; } + + #endregion + + #region Protected Methods + + /// + /// Fills the internal. + /// + /// The data reader contains module information. + /// + /// Please remember to call base.FillInternal or base.Fill method in your Fill method. + /// + protected override void FillInternal(IDataReader dr) + { + base.FillInternal(dr); + + ContentItemId = Null.SetNullInteger(dr["ContentItemID"]); + Content = Null.SetNullString(dr["Content"]); + ContentTypeId = Null.SetNullInteger(dr["ContentTypeID"]); + TabID = Null.SetNullInteger(dr["TabID"]); + ModuleID = Null.SetNullInteger(dr["ModuleID"]); + ContentKey = Null.SetNullString(dr["ContentKey"]); + Indexed = Null.SetNullBoolean(dr["Indexed"]); + + var schema = dr.GetSchemaTable(); + if (schema != null) + { + if (schema.Select("ColumnName = 'StateID'").Length > 0) + { + StateID = Null.SetNullInteger(dr["StateID"]); + } + } + } + + protected void Clone(ContentItem cloneItem, ContentItem originalItem) + { + cloneItem.ContentItemId = originalItem.ContentItemId; + cloneItem.Content = originalItem.Content; + cloneItem.ContentTypeId = originalItem.ContentTypeId; + cloneItem.TabID = originalItem.TabID; + cloneItem.ModuleID = originalItem.ModuleID; + cloneItem.ContentKey = originalItem.ContentKey; + cloneItem.Indexed = originalItem.Indexed; + cloneItem.StateID = originalItem.StateID; + } + + #endregion + + #region IHydratable Implementation + + /// + /// Fill this content object will the information from data reader. + /// + /// The data reader. + /// + public virtual void Fill(IDataReader dr) + { + FillInternal(dr); + } + + /// + /// Gets or sets the key ID. + /// + /// + /// The key ID. + /// + /// + /// If you derive class has its own key id, please override this property and set the value to your own key id. + /// + [XmlIgnore] + public virtual int KeyID + { + get + { + return ContentItemId; + } + set + { + ContentItemId = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/ContentType.cs b/DNN Platform/Library/Entities/Content/ContentType.cs new file mode 100644 index 00000000000..492aa7e9b5f --- /dev/null +++ b/DNN Platform/Library/Entities/Content/ContentType.cs @@ -0,0 +1,119 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + /// + /// This class exists solely to maintain compatibility between the original VB version + /// which supported ContentType.ContentType and the c# version which doesn't allow members with + /// the same naem as their parent type + /// + [Serializable] + public abstract class ContentTypeMemberNameFixer + { + public string ContentType { get; set; } + } + + /// + /// Content type of a content item. + /// + /// + /// Content Types, simply put, are a way of telling the framework what module/functionality is associated with a Content Item. + /// Each product (ie. module) that wishes to allow categorization of data (via Taxonomy or Folksonomy) for it's content items + /// will likely need to create its own content type. + /// + [Serializable] + public class ContentType : ContentTypeMemberNameFixer, IHydratable + { + //private string _ContentType; + + public ContentType() : this(Null.NullString) + { + } + + public ContentType(string contentType) + { + ContentTypeId = Null.NullInteger; + ContentType = contentType; + } + + /// + /// Gets or sets the content type id. + /// + /// + /// The content type id. + /// + public int ContentTypeId { get; set; } + + #region "IHydratable Implementation" + + /// + /// Fill this content object will the information from data reader. + /// + /// The data reader. + /// + public void Fill(IDataReader dr) + { + ContentTypeId = Null.SetNullInteger(dr["ContentTypeID"]); + ContentType = Null.SetNullString(dr["ContentType"]); + } + + /// + /// Gets or sets the key ID. + /// + /// + /// ContentTypeID + /// + public int KeyID + { + get + { + return ContentTypeId; + } + set + { + ContentTypeId = value; + } + } + + #endregion + + /// + /// override ToString to return content type + /// + /// + /// property ContentType's value. + /// + public override string ToString() + { + return ContentType; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/ContentTypeController.cs b/DNN Platform/Library/Entities/Content/ContentTypeController.cs new file mode 100644 index 00000000000..63c2f28a7a6 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/ContentTypeController.cs @@ -0,0 +1,162 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + /// + /// ContentTypeController provides the business layer of ContentType. + /// + /// + /// + /// + /// + /// IContentTypeController typeController = new ContentTypeController(); + /// ContentType contentType = (from t in typeController.GetContentTypes() + /// where t.ContentType == "DesktopModule" + /// select t).SingleOrDefault(); + /// if(contentType == null) + /// { + /// contentType = new ContentType {ContentType = "DesktopModule"}; + /// contentType.ContentTypeId = typeController.AddContentType(contentType); + /// } + /// + /// + public class ContentTypeController : IContentTypeController + { + private readonly IDataService _DataService; + private string _CacheKey = "ContentTypes"; + + private int _CacheTimeOut = 20; + + #region "Constructors" + + public ContentTypeController() : this(Util.GetDataService()) + { + } + + public ContentTypeController(IDataService dataService) + { + _DataService = dataService; + } + + #endregion + + #region "Private Methods" + + private object GetContentTypesCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillQueryable(_DataService.GetContentTypes()).ToList(); + } + + #endregion + + #region "Public Methods" + + /// + /// Adds the type of the content. + /// + /// Type of the content. + /// content type id. + /// content type is null. + /// contentType.ContentType is empty. + public int AddContentType(ContentType contentType) + { + //Argument Contract + Requires.NotNull("contentType", contentType); + Requires.PropertyNotNullOrEmpty("contentType", "ContentType", contentType.ContentType); + + contentType.ContentTypeId = _DataService.AddContentType(contentType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + + return contentType.ContentTypeId; + } + + /// + /// Clears the content type cache. + /// + public void ClearContentTypeCache() + { + DataCache.RemoveCache(_CacheKey); + } + + /// + /// Deletes the type of the content. + /// + /// Type of the content. + /// content type is null. + /// content type id is less than 0. + public void DeleteContentType(ContentType contentType) + { + //Argument Contract + Requires.NotNull("contentType", contentType); + Requires.PropertyNotNegative("contentType", "ContentTypeId", contentType.ContentTypeId); + + _DataService.DeleteContentType(contentType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + } + + /// + /// Gets the content types. + /// + /// content type collection. + public IQueryable GetContentTypes() + { + return CBO.GetCachedObject>(new CacheItemArgs(_CacheKey, _CacheTimeOut), GetContentTypesCallBack).AsQueryable(); + } + + /// + /// Updates the type of the content. + /// + /// Type of the content. + /// content type is null. + /// content type id is less than 0. + /// contentType.ContentType is empty. + public void UpdateContentType(ContentType contentType) + { + //Argument Contract + Requires.NotNull("contentType", contentType); + Requires.PropertyNotNegative("contentType", "ContentTypeId", contentType.ContentTypeId); + Requires.PropertyNotNullOrEmpty("contentType", "ContentType", contentType.ContentType); + + _DataService.UpdateContentType(contentType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Data/DataService.cs b/DNN Platform/Library/Entities/Content/Data/DataService.cs new file mode 100644 index 00000000000..7ace0e298be --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Data/DataService.cs @@ -0,0 +1,493 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Entities.Content.Data +{ + /// + /// Persistent data of content with DataProvider instance. + /// + /// + /// It's better to use Util.GetDataService instead of create new instance directly. + /// + /// + /// + /// public ContentController() : this(Util.GetDataService()) + /// { + /// } + /// public ContentController(IDataService dataService) + /// { + /// _dataService = dataService; + /// } + /// + /// + public class DataService : IDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + + #region "ContentItem Methods" + + /// + /// Adds the content item. + /// + /// The content item. + /// The created by user id. + /// content item id. + public int AddContentItem(ContentItem contentItem, int createdByUserId) + { + return _provider.ExecuteScalar("AddContentItem", + contentItem.Content, + contentItem.ContentTypeId, + contentItem.TabID, + contentItem.ModuleID, + contentItem.ContentKey, + contentItem.Indexed, + createdByUserId, + _provider.GetNull(contentItem.StateID)); + } + + /// + /// Deletes the content item. + /// + /// The content item ID. + public void DeleteContentItem(int contentItemId) + { + _provider.ExecuteNonQuery("DeleteContentItem", contentItemId); + } + + /// + /// Gets the content item. + /// + /// The content item id. + /// data reader. + public IDataReader GetContentItem(int contentItemId) + { + return _provider.ExecuteReader("GetContentItem", contentItemId); + } + + /// + /// Gets the content items. + /// + /// The Id of the Content Type. + /// The Id of the Tab. + /// The Id of the Module. + /// data reader. + public IDataReader GetContentItems(int contentTypeId, int tabId, int moduleId) + { + return _provider.ExecuteReader("GetContentItems", _provider.GetNull(contentTypeId), + _provider.GetNull(tabId), + _provider.GetNull(moduleId)); + } + + /// + /// Gets the content items by term. + /// + /// The term. + /// data reader. + public IDataReader GetContentItemsByTerm(string term) + { + return _provider.ExecuteReader("GetContentItemsByTerm", term); + } + + /// + /// Get a list of content items of the specified content type, . + /// + /// The type of content items you are searching for + public IDataReader GetContentItemsByContentType(int contentTypeId) + { + return _provider.ExecuteReader("GetContentItemsByContentType", contentTypeId); + } + + /// + /// Get a list of content items based on TabID (PageID). + /// + /// The TabID (or "Page ID") that the content items are associated with + public IDataReader GetContentItemsByTabId(int tabId) + { + return _provider.ExecuteReader("GetContentItemsByTabId", tabId); + } + + /// + /// Retrieve all content items associated with a articular Module ID, . + /// + public IDataReader GetContentItemsByModuleId(int moduleId) + { + return _provider.ExecuteReader("GetContentItemsByModuleId", moduleId); + } + + /// + /// Retrieve a list of content items containg terms from the specified Vocabulary ID. + /// + public IDataReader GetContentItemsByVocabularyId(int vocabularyId) + { + return _provider.ExecuteReader("GetContentItemsByVocabularyId", vocabularyId); + } + + /// + /// Gets the un indexed content items. + /// + /// data reader. + public IDataReader GetUnIndexedContentItems() + { + return _provider.ExecuteReader("GetUnIndexedContentItems"); + } + + /// + /// Updates the content item. + /// + /// The content item. + /// The created by user id. + public void UpdateContentItem(ContentItem contentItem, int createdByUserId) + { + _provider.ExecuteNonQuery("UpdateContentItem", + contentItem.ContentItemId, + contentItem.Content, + contentItem.ContentTypeId, + contentItem.TabID, + contentItem.ModuleID, + contentItem.ContentKey, + contentItem.Indexed, + createdByUserId, + _provider.GetNull(contentItem.StateID)); + } + + #endregion + + #region "MetaData Methods" + + /// + /// Adds the meta data. + /// + /// The content item. + /// The name. + /// The value. + public void AddMetaData(ContentItem contentItem, string name, string value) + { + _provider.ExecuteNonQuery("AddMetaData", contentItem.ContentItemId, name, value); + } + + public void SynchronizeMetaData(ContentItem contentItem, IEnumerable> added, IEnumerable> deleted) + { + using (var transaction = _provider.GetTransaction()) + { + foreach (var item in deleted) + { + DeleteMetaData(contentItem, item.Key, item.Value); + } + + foreach (var item in added) + { + AddMetaData(contentItem, item.Key, item.Value); + } + + transaction.Commit(); + } + } + + /// + /// Deletes the meta data. + /// + /// The content item. + /// The name. + /// The value. + public void DeleteMetaData(ContentItem contentItem, string name, string value) + { + _provider.ExecuteNonQuery("DeleteMetaData", contentItem.ContentItemId, name, value); + } + + /// + /// Gets the meta data. + /// + /// The content item id. + /// data reader. + public IDataReader GetMetaData(int contentItemId) + { + return _provider.ExecuteReader("GetMetaData", contentItemId); + } + + #endregion + + #region "ContentType Methods" + + /// + /// Adds the type of the content. + /// + /// Type of the content. + /// content type id. + public int AddContentType(ContentType contentType) + { + return _provider.ExecuteScalar("AddContentType", contentType.ContentType); + } + + public void DeleteContentType(ContentType contentType) + { + _provider.ExecuteNonQuery("DeleteContentType", contentType.ContentTypeId); + } + + /// + /// Gets the content types. + /// + /// data reader. + public IDataReader GetContentTypes() + { + return _provider.ExecuteReader("GetContentTypes"); + } + + /// + /// Updates the type of the content. + /// + /// Type of the content. + public void UpdateContentType(ContentType contentType) + { + _provider.ExecuteNonQuery("UpdateContentType", contentType.ContentTypeId, contentType.ContentType); + } + + #endregion + + #region "ScopeType Methods" + + /// + /// Adds the type of the scope. + /// + /// Type of the scope. + /// scope type id. + public int AddScopeType(ScopeType scopeType) + { + return _provider.ExecuteScalar("AddScopeType", scopeType.ScopeType); + } + + /// + /// Deletes the type of the scope. + /// + /// Type of the scope. + public void DeleteScopeType(ScopeType scopeType) + { + _provider.ExecuteNonQuery("DeleteScopeType", scopeType.ScopeTypeId); + } + + /// + /// Gets the scope types. + /// + /// data reader. + public IDataReader GetScopeTypes() + { + return _provider.ExecuteReader("GetScopeTypes"); + } + + /// + /// Updates the type of the scope. + /// + /// Type of the scope. + public void UpdateScopeType(ScopeType scopeType) + { + _provider.ExecuteNonQuery("UpdateScopeType", scopeType.ScopeTypeId, scopeType.ScopeType); + } + + #endregion + + #region "Term Methods" + + /// + /// Adds the heirarchical term. + /// + /// The term. + /// The created by user id. + /// term id. + public int AddHeirarchicalTerm(Term term, int createdByUserId) + { + return _provider.ExecuteScalar("AddHeirarchicalTerm", term.VocabularyId, term.ParentTermId, term.Name, term.Description, term.Weight, createdByUserId); + } + + /// + /// Adds the simple term. + /// + /// The term. + /// The created by user id. + /// term id. + public int AddSimpleTerm(Term term, int createdByUserId) + { + return _provider.ExecuteScalar("AddSimpleTerm", term.VocabularyId, term.Name, term.Description, term.Weight, createdByUserId); + } + + public void AddTermToContent(Term term, ContentItem contentItem) + { + _provider.ExecuteNonQuery("AddTermToContent", term.TermId, contentItem.ContentItemId); + } + + /// + /// Deletes the simple term. + /// + /// The term. + public void DeleteSimpleTerm(Term term) + { + _provider.ExecuteNonQuery("DeleteSimpleTerm", term.TermId); + } + + /// + /// Deletes the heirarchical term. + /// + /// The term. + public void DeleteHeirarchicalTerm(Term term) + { + _provider.ExecuteNonQuery("DeleteHeirarchicalTerm", term.TermId); + } + + /// + /// Gets the term. + /// + /// The term id. + /// data reader. + public IDataReader GetTerm(int termId) + { + return _provider.ExecuteReader("GetTerm", termId); + } + + /// + /// Retrieve term usage data for the specified Term ID, . + /// + public IDataReader GetTermUsage(int termId) + { + return _provider.ExecuteReader("GetTermUsage", termId); + } + + /// + /// Gets the content of the terms by. + /// + /// The content item id. + /// data reader. + public IDataReader GetTermsByContent(int contentItemId) + { + return _provider.ExecuteReader("GetTermsByContent", contentItemId); + } + + /// + /// Gets the terms by vocabulary. + /// + /// The vocabulary id. + /// data reader. + public IDataReader GetTermsByVocabulary(int vocabularyId) + { + return _provider.ExecuteReader("GetTermsByVocabulary", vocabularyId); + } + + /// + /// Removes the content of the terms from. + /// + /// The content item. + public void RemoveTermsFromContent(ContentItem contentItem) + { + _provider.ExecuteNonQuery("RemoveTermsFromContent", contentItem.ContentItemId); + } + + /// + /// Updates the heirarchical term. + /// + /// The term. + /// The last modified by user id. + public void UpdateHeirarchicalTerm(Term term, int lastModifiedByUserId) + { + _provider.ExecuteNonQuery("UpdateHeirarchicalTerm", term.TermId, term.VocabularyId, term.ParentTermId, term.Name, term.Description, term.Weight, lastModifiedByUserId); + } + + /// + /// Updates the simple term. + /// + /// The term. + /// The last modified by user id. + public void UpdateSimpleTerm(Term term, int lastModifiedByUserId) + { + _provider.ExecuteNonQuery("UpdateSimpleTerm", term.TermId, term.VocabularyId, term.Name, term.Description, term.Weight, lastModifiedByUserId); + } + + #endregion + + #region "Vocabulary Methods" + + /// + /// Adds the vocabulary. + /// + /// The vocabulary. + /// The created by user id. + /// Vocabulary id. + public int AddVocabulary(Vocabulary vocabulary, int createdByUserId) + { + return _provider.ExecuteScalar("AddVocabulary", + vocabulary.Type, + vocabulary.Name, + vocabulary.Description, + vocabulary.Weight, + _provider.GetNull(vocabulary.ScopeId), + vocabulary.ScopeTypeId, + createdByUserId); + } + + /// + /// Deletes the vocabulary. + /// + /// The vocabulary. + public void DeleteVocabulary(Vocabulary vocabulary) + { + _provider.ExecuteNonQuery("DeleteVocabulary", vocabulary.VocabularyId); + } + + /// + /// Gets the vocabularies. + /// + /// data reader. + public IDataReader GetVocabularies() + { + return _provider.ExecuteReader("GetVocabularies"); + } + + /// + /// Updates the vocabulary. + /// + /// The vocabulary. + /// The last modified by user id. + public void UpdateVocabulary(Vocabulary vocabulary, int lastModifiedByUserId) + { + _provider.ExecuteNonQuery("UpdateVocabulary", + vocabulary.VocabularyId, + vocabulary.Type, + vocabulary.Name, + vocabulary.Description, + vocabulary.Weight, + vocabulary.ScopeId, + vocabulary.ScopeTypeId, + lastModifiedByUserId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Data/IDataService.cs b/DNN Platform/Library/Entities/Content/Data/IDataService.cs new file mode 100644 index 00000000000..3b11968a46b --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Data/IDataService.cs @@ -0,0 +1,125 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Entities.Content.Data +{ + /// + /// Interface of DataService. + /// + /// + public interface IDataService + { + //Content Item Methods + int AddContentItem(ContentItem contentItem, int createdByUserId); + + void DeleteContentItem(int contentItemId); + + IDataReader GetContentItem(int contentItemId); + + IDataReader GetContentItems(int contentTypeId, int tabId, int moduleId); + + IDataReader GetContentItemsByTerm(string term); + + IDataReader GetContentItemsByContentType(int contentTypeId); + + IDataReader GetContentItemsByModuleId(int moduleId); + + IDataReader GetContentItemsByTabId(int tabId); + + IDataReader GetContentItemsByVocabularyId(int vocabularyId); + + IDataReader GetUnIndexedContentItems(); + + void UpdateContentItem(ContentItem contentItem, int lastModifiedByUserId); + + //Content MetaData Methods + void AddMetaData(ContentItem contentItem, string name, string value); + + void DeleteMetaData(ContentItem contentItem, string name, string value); + + IDataReader GetMetaData(int contentItemId); + + void SynchronizeMetaData(ContentItem contentItem, + IEnumerable> added, + IEnumerable> deleted); + + //ContentType Methods + int AddContentType(ContentType contentType); + + void DeleteContentType(ContentType contentType); + + IDataReader GetContentTypes(); + + void UpdateContentType(ContentType contentType); + + //ScopeType Methods + int AddScopeType(ScopeType scopeType); + + void DeleteScopeType(ScopeType scopeType); + + IDataReader GetScopeTypes(); + + void UpdateScopeType(ScopeType scopeType); + + //Term Methods + int AddHeirarchicalTerm(Term term, int createdByUserId); + + int AddSimpleTerm(Term term, int createdByUserId); + + void AddTermToContent(Term term, ContentItem contentItem); + + void DeleteSimpleTerm(Term term); + + void DeleteHeirarchicalTerm(Term term); + + IDataReader GetTerm(int termId); + + IDataReader GetTermUsage(int termId); + + IDataReader GetTermsByContent(int contentItemId); + + IDataReader GetTermsByVocabulary(int vocabularyId); + + void RemoveTermsFromContent(ContentItem contentItem); + + void UpdateHeirarchicalTerm(Term term, int lastModifiedByUserId); + + void UpdateSimpleTerm(Term term, int lastModifiedByUserId); + + //Vocabulary Methods + int AddVocabulary(Vocabulary vocabulary, int createdByUserId); + + void DeleteVocabulary(Vocabulary vocabulary); + + IDataReader GetVocabularies(); + + void UpdateVocabulary(Vocabulary vocabulary, int lastModifiedByUserId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/IAttachmentController.cs b/DNN Platform/Library/Entities/Content/IAttachmentController.cs new file mode 100644 index 00000000000..dcc43223673 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/IAttachmentController.cs @@ -0,0 +1,63 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; +using DotNetNuke.Services.FileSystem; + +namespace DotNetNuke.Entities.Content +{ + /// Interface of FileController + /// + public interface IAttachmentController + { + /// + /// Add a generic file to a . + /// + /// The content item + /// A file registered in the DotNetNuke + void AddFileToContent(int contentItemId, IFileInfo fileInfo); + + void AddFilesToContent(int contentItemId, IEnumerable fileInfo); + + /// + /// Add a video file to a . + /// + /// The content item + /// A file registered in the DotNetNuke + void AddVideoToContent(int contentItemId, IFileInfo fileInfo); + + void AddVideosToContent(int contentItemId, IEnumerable fileInfo); + + /// + /// Attach an image to a ContentItem. + /// + /// The content item + /// A file registered in the DotNetNuke + void AddImageToContent(int contentItemId, IFileInfo fileInfo); + + void AddImagesToContent(int contentItemId, IEnumerable fileInfo); + + IList GetFilesByContent(int contentItemId); + + IList GetVideosByContent(int contentItemId); + + IList GetImagesByContent(int contentItemId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/IContentController.cs b/DNN Platform/Library/Entities/Content/IContentController.cs new file mode 100644 index 00000000000..22aa2dfa9c6 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/IContentController.cs @@ -0,0 +1,172 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; + +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + /// + /// IContentController provides the business layer of ContentItem. + /// + /// + /// + /// + /// IContentController contentController = Util.GetContentController(); + /// desktopModule.Content = desktopModule.FriendlyName; + /// desktopModule.Indexed = false; + /// desktopModule.ContentTypeId = contentType.ContentTypeId; + /// desktopModule.ContentItemId = contentController.AddContentItem(desktopModule); + /// + /// + public interface IContentController + { + /// + /// Adds the content item. + /// + /// The content item. + /// content item id. + /// content item is null. + int AddContentItem(ContentItem contentItem); + + /// + /// Deletes the content item. + /// + /// The content item. + /// content item is null. + /// content item's id less than 0. + void DeleteContentItem(ContentItem contentItem); + + /// Delete a ContentItem object by ID. + /// The ID of the ContentItem object (ContentItemId) + void DeleteContentItem(int contentItemId); + + /// + /// Gets the content item. + /// + /// The content item id. + /// content item. + /// Content item id is less than 0. + ContentItem GetContentItem(int contentItemId); + + /// Return ContentItems that have the specified term attached. + /// Term name is empty. + IQueryable GetContentItemsByTerm(string term); + + /// Return ContentItems that have the specified term attached. + /// Term name is empty. + IQueryable GetContentItemsByTerm(Term term); + + /// + /// Get a list of content items by ContentType ID. + /// + /// The Content Type ID of the content items we want to query + IQueryable GetContentItemsByContentType(int contentTypeId); + + /// + /// Get a list of content items by ContentType. + /// + /// The Content Type of the content items we want to query + IQueryable GetContentItemsByContentType(ContentType contentType); + + /// + /// Return a list of ContentItems that have all of the specified terms attached. + /// + /// A list of terms that should be attached to the ContentItems returned + IQueryable GetContentItemsByTerms(IList terms); + + /// Return a list of ContentItems that have all of the specified terms attached. + IQueryable GetContentItemsByTerms(string[] terms); + + /// + /// Gets the un indexed content items. + /// + /// content item collection. + IQueryable GetUnIndexedContentItems(); + + /// + /// Retrieve all content items associated with the specified module ID, . + /// + /// The module ID to use in the content item lookup + IQueryable GetContentItemsByModuleId(int moduleId); + + /// + /// Retrieve all content items on the specified page (tab). + /// + /// The page ID to use in the lookup of content items + IQueryable GetContentItemsByTabId(int tabId); + + /// + /// Get a list of content items tagged with terms from the specified Vocabulary ID. + /// + IQueryable GetContentItemsByVocabularyId(int vocabularyId); + + /// + /// Updates the content item. + /// + /// The content item. + /// content item is null. + /// content item's id less than 0. + void UpdateContentItem(ContentItem contentItem); + + /// + /// Adds the meta data. + /// + /// The content item. + /// The name. + /// The value. + /// content item is null. + /// content item's id less than 0. + /// Meta name is empty. + void AddMetaData(ContentItem contentItem, string name, string value); + + /// + /// Deletes the meta data. + /// + /// The content item. + /// The name. + /// The value. + /// content item is null. + /// content item's id less than 0. + /// Meta name is empty. + void DeleteMetaData(ContentItem contentItem, string name, string value); + + /// + /// Similar to DeleteMetaData that requires a value, but this one looks it up for you. + /// + void DeleteMetaData(ContentItem contentItem, string name); + + /// + /// Gets the meta data. + /// + /// The content item id. + /// + /// content item's id less than 0. + NameValueCollection GetMetaData(int contentItemId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/IContentTypeController.cs b/DNN Platform/Library/Entities/Content/IContentTypeController.cs new file mode 100644 index 00000000000..154a7fd406b --- /dev/null +++ b/DNN Platform/Library/Entities/Content/IContentTypeController.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Linq; + +#endregion + +namespace DotNetNuke.Entities.Content +{ + /// + /// Interface of ContentTypeController. + /// + /// + public interface IContentTypeController + { + int AddContentType(ContentType contentType); + + void ClearContentTypeCache(); + + void DeleteContentType(ContentType contentType); + + IQueryable GetContentTypes(); + + void UpdateContentType(ContentType contentType); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/IScopeTypeController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/IScopeTypeController.cs new file mode 100644 index 00000000000..387b16ba183 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/IScopeTypeController.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Linq; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Interface of ScopeTypeController. + /// + /// + public interface IScopeTypeController + { + int AddScopeType(ScopeType scopeType); + + void ClearScopeTypeCache(); + + void DeleteScopeType(ScopeType scopeType); + + IQueryable GetScopeTypes(); + + void UpdateScopeType(ScopeType scopeType); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/ITermController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/ITermController.cs new file mode 100644 index 00000000000..febb5314ad2 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/ITermController.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Linq; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Interface of TermController. + /// + /// + public interface ITermController + { + int AddTerm(Term term); + + void AddTermToContent(Term term, ContentItem contentItem); + + void DeleteTerm(Term term); + + Term GetTerm(int termId); + + TermUsage GetTermUsage(int termId); + + IQueryable GetTermsByContent(int contentItemId); + + IQueryable GetTermsByVocabulary(int vocabularyId); + + IQueryable GetTermsByVocabulary(string vocabularyName); + + void RemoveTermsFromContent(ContentItem contentItem); + + void UpdateTerm(Term term); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/IVocabularyController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/IVocabularyController.cs new file mode 100644 index 00000000000..0844169a60d --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/IVocabularyController.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Linq; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Interface of VocabularyController. + /// + /// + public interface IVocabularyController + { + int AddVocabulary(Vocabulary vocabulary); + + void ClearVocabularyCache(); + + void DeleteVocabulary(Vocabulary vocabulary); + + IQueryable GetVocabularies(); + + void UpdateVocabulary(Vocabulary vocabulary); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/ScopeType.cs b/DNN Platform/Library/Entities/Content/Taxonomy/ScopeType.cs new file mode 100644 index 00000000000..270c0b5382e --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/ScopeType.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// This class exists solely to maintain compatibility between the original VB version + /// which supported ScopeType.ScopeType and the c# version which doesn't allow members with + /// the same naem as their parent type + /// + [Serializable] + public abstract class ScopeTypeMemberNameFixer + { + public string ScopeType { get; set; } + } + + /// + /// Class of ScopeType. + /// + /// + [Serializable] + public class ScopeType : ScopeTypeMemberNameFixer, IHydratable + { + public ScopeType() : this(Null.NullString) + { + } + + public ScopeType(string scopeType) + { + ScopeTypeId = Null.NullInteger; + ScopeType = scopeType; + } + + public int ScopeTypeId { get; set; } + + public void Fill(IDataReader dr) + { + ScopeTypeId = Null.SetNullInteger(dr["ScopeTypeID"]); + ScopeType = Null.SetNullString(dr["ScopeType"]); + } + + public int KeyID + { + get + { + return ScopeTypeId; + } + set + { + ScopeTypeId = value; + } + } + + public override string ToString() + { + return ScopeType; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/ScopeTypeController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/ScopeTypeController.cs new file mode 100644 index 00000000000..b71ea513fa1 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/ScopeTypeController.cs @@ -0,0 +1,121 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// ScopeTypeController provides the business layer of ScopeType. + /// + /// + public class ScopeTypeController : IScopeTypeController + { + private readonly IDataService _DataService; + private string _CacheKey = "ScopeTypes"; + + private int _CacheTimeOut = 20; + + #region "Constructors" + + public ScopeTypeController() : this(Util.GetDataService()) + { + } + + public ScopeTypeController(IDataService dataService) + { + _DataService = dataService; + } + + #endregion + + #region "Private Methods" + + private object GetScopeTypesCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillQueryable(_DataService.GetScopeTypes()).ToList(); + } + + #endregion + + #region "Public Methods" + + public int AddScopeType(ScopeType scopeType) + { + //Argument Contract + Requires.NotNull("scopeType", scopeType); + Requires.PropertyNotNullOrEmpty("scopeType", "ScopeType", scopeType.ScopeType); + + scopeType.ScopeTypeId = _DataService.AddScopeType(scopeType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + + return scopeType.ScopeTypeId; + } + + public void ClearScopeTypeCache() + { + DataCache.RemoveCache(_CacheKey); + } + + public void DeleteScopeType(ScopeType scopeType) + { + //Argument Contract + Requires.NotNull("scopeType", scopeType); + Requires.PropertyNotNegative("scopeType", "ScopeTypeId", scopeType.ScopeTypeId); + + _DataService.DeleteScopeType(scopeType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + } + + public IQueryable GetScopeTypes() + { + return CBO.GetCachedObject>(new CacheItemArgs(_CacheKey, _CacheTimeOut), GetScopeTypesCallBack).AsQueryable(); + } + + public void UpdateScopeType(ScopeType scopeType) + { + //Argument Contract + Requires.NotNull("scopeType", scopeType); + Requires.PropertyNotNegative("scopeType", "ScopeTypeId", scopeType.ScopeTypeId); + Requires.PropertyNotNullOrEmpty("scopeType", "ScopeType", scopeType.ScopeType); + + _DataService.UpdateScopeType(scopeType); + + //Refresh cached collection of types + DataCache.RemoveCache(_CacheKey); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/Term.cs b/DNN Platform/Library/Entities/Content/Taxonomy/Term.cs new file mode 100644 index 00000000000..a1e4da44a73 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/Term.cs @@ -0,0 +1,326 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web.Script.Serialization; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Major class of Taxonomy. + /// + /// + /// + /// Taxonomy is defined as “the practice and science of classification” – Wikipedia, + /// while Folksonomy is defined as “collaborative tagging” – Wikipedia. + /// Usually, taxonomy refers to the practice of using hierarchical categories applied to the content by a “content editor”, + /// while folksonomy refers to the practice of free-form tagging of content by users. + /// In DotNetNuke, while we expose both of these at the presentation layer, in the API and Data Layer they are implemented + /// using a common data structure. + /// + /// + /// There are a number of advantages of using a special System Vocabulary for storing user entered tags. + /// One is that both taxonomy terms and folksonomy tags are treated in the API and Data Layer in the same way. + /// This means that we only have to manage one relationship between content and terms rather than two separate relationships. + /// The second benefit of treating tags in this way is that an admin can “manage” the tags – ie remove any offensive or inappropriate tags, + /// or correct spellings of tags, by using the Taxonomy Manager UI. + /// + /// + /// + /// + /// internal static List<Term> GetTerms(this Vocabulary voc, int vocabularyId) + /// { + /// ITermController ctl = Util.GetTermController(); + /// return ctl.GetTermsByVocabulary(vocabularyId).ToList(); + /// } + /// + /// + [Serializable] + public class Term : BaseEntityInfo, IHydratable + { + private List _childTerms; + private string _description; + private int _left; + private string _name; + private int? _parentTermId; + private int _right; + private readonly List _synonyms = new List(); + private int _termId; + private Vocabulary _vocabulary; + private int _vocabularyId; + private int _weight; + + #region "Constructors" + + public Term() : this(Null.NullString, Null.NullString, Null.NullInteger) + { + } + + public Term(int vocabularyId) : this(Null.NullString, Null.NullString, vocabularyId) + { + } + + public Term(string name) : this(name, Null.NullString, Null.NullInteger) + { + } + + public Term(string name, string description) : this(name, description, Null.NullInteger) + { + } + + public Term(string name, string description, int vocabularyId) + { + _description = description; + _name = name; + _vocabularyId = vocabularyId; + + _parentTermId = null; + _termId = Null.NullInteger; + _left = 0; + _right = 0; + _weight = 0; + } + + #endregion + + #region "Public Properties" + + [XmlIgnore] + [ScriptIgnore] + public List ChildTerms + { + get + { + if (_childTerms == null) + { + _childTerms = this.GetChildTerms(_termId, _vocabularyId); + } + return _childTerms; + } + } + + [XmlIgnore] + [ScriptIgnore] + public string Description + { + get + { + return _description; + } + set + { + _description = value; + } + } + + [XmlIgnore] + [ScriptIgnore] + public bool IsHeirarchical + { + get + { + return (Vocabulary.Type == VocabularyType.Hierarchy); + } + } + + [XmlIgnore] + [ScriptIgnore] + public int Left + { + get + { + return _left; + } + } + + [XmlIgnore] + [ScriptIgnore] + public string Name + { + get + { + return _name; + } + set + { + _name = value; + } + } + + [XmlIgnore] + [ScriptIgnore] + public int? ParentTermId + { + get + { + return _parentTermId; + } + set + { + _parentTermId = value; + } + } + + [XmlIgnore] + [ScriptIgnore] + public int Right + { + get + { + return _right; + } + } + + [XmlIgnore] + [ScriptIgnore] + public List Synonyms + { + get + { + return _synonyms; + } + } + + [XmlIgnore] + [ScriptIgnore] + public int TermId + { + get + { + return _termId; + } + set + { + _termId = value; + } + } + + [XmlIgnore] + [ScriptIgnore] + public Vocabulary Vocabulary + { + get + { + if (_vocabulary == null && _vocabularyId > Null.NullInteger) + { + _vocabulary = this.GetVocabulary(_vocabularyId); + } + return _vocabulary; + } + } + + [XmlIgnore] + [ScriptIgnore] + public int VocabularyId + { + get + { + return _vocabularyId; + } + } + + [XmlIgnore] + [ScriptIgnore] + public int Weight + { + get + { + return _weight; + } + set + { + _weight = value; + } + } + + #endregion + + #region "IHydratable Implementation" + + public virtual void Fill(IDataReader dr) + { + TermId = Null.SetNullInteger(dr["TermID"]); + Name = Null.SetNullString(dr["Name"]); + Description = Null.SetNullString(dr["Description"]); + Weight = Null.SetNullInteger(dr["Weight"]); + _vocabularyId = Null.SetNullInteger(dr["VocabularyID"]); + + if (dr["TermLeft"] != DBNull.Value) + { + _left = Convert.ToInt32(dr["TermLeft"]); + } + if (dr["TermRight"] != DBNull.Value) + { + _right = Convert.ToInt32(dr["TermRight"]); + } + if (dr["ParentTermID"] != DBNull.Value) + { + ParentTermId = Convert.ToInt32(dr["ParentTermID"]); + } + + //Fill base class properties + FillInternal(dr); + } + + public int KeyID + { + get + { + return TermId; + } + set + { + TermId = value; + } + } + + #endregion + + public string GetTermPath() + { + string path = "\\\\" + Name; + + if (ParentTermId.HasValue) + { + ITermController ctl = Util.GetTermController(); + + Term parentTerm = (from t in ctl.GetTermsByVocabulary(VocabularyId) where t.TermId == ParentTermId select t).SingleOrDefault(); + + if (parentTerm != null) + { + path = parentTerm.GetTermPath() + path; + } + } + return path; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/TermController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/TermController.cs new file mode 100644 index 00000000000..8e7de4f1bc0 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/TermController.cs @@ -0,0 +1,276 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// The Main Business layer of Taxonomy. + /// + /// + /// + /// internal static List<Term> GetTerms(this Vocabulary voc, int vocabularyId) + /// { + /// ITermController ctl = Util.GetTermController(); + /// return ctl.GetTermsByVocabulary(vocabularyId).ToList(); + /// } + /// + /// + public class TermController : ITermController + { + private readonly IDataService _DataService; + private const string _CacheKey = "Terms_{0}"; + private const CacheItemPriority _CachePriority = CacheItemPriority.Normal; + + private const int _CacheTimeOut = 20; + + #region Constructors + + public TermController() : this(Util.GetDataService()) + { + } + + public TermController(IDataService dataService) + { + _DataService = dataService; + } + + #endregion + + #region Private Methods + + private object GetTermsCallBack(CacheItemArgs cacheItemArgs) + { + var vocabularyId = (int) cacheItemArgs.ParamList[0]; + return CBO.FillQueryable(_DataService.GetTermsByVocabulary(vocabularyId)).ToList(); + } + + #endregion + + #region Public Methods + + /// + /// Adds the term. + /// + /// The term. + /// term id. + /// term is null. + /// term.VocabularyId is less than 0. + /// term.Name is empty. + public int AddTerm(Term term) + { + //Argument Contract + Requires.NotNull("term", term); + Requires.PropertyNotNegative("term", "VocabularyId", term.VocabularyId); + Requires.PropertyNotNullOrEmpty("term", "Name", term.Name); + + if ((term.IsHeirarchical)) + { + term.TermId = _DataService.AddHeirarchicalTerm(term, UserController.GetCurrentUserInfo().UserID); + } + else + { + term.TermId = _DataService.AddSimpleTerm(term, UserController.GetCurrentUserInfo().UserID); + } + + //Clear Cache + DataCache.RemoveCache(string.Format(_CacheKey, term.VocabularyId)); + + return term.TermId; + } + + /// + /// Adds the content of the term to. + /// + /// The term. + /// The content item. + /// term is null. + /// content item is null. + public void AddTermToContent(Term term, ContentItem contentItem) + { + //Argument Contract + Requires.NotNull("term", term); + Requires.NotNull("contentItem", contentItem); + + _DataService.AddTermToContent(term, contentItem); + } + + /// + /// Deletes the term. + /// + /// The term. + /// term is null. + /// term.TermId is less than 0. + public void DeleteTerm(Term term) + { + //Argument Contract + Requires.NotNull("term", term); + Requires.PropertyNotNegative("term", "TermId", term.TermId); + + if ((term.IsHeirarchical)) + { + _DataService.DeleteHeirarchicalTerm(term); + } + else + { + _DataService.DeleteSimpleTerm(term); + } + + //Clear Cache + DataCache.RemoveCache(string.Format(_CacheKey, term.VocabularyId)); + } + + /// + /// Gets the term. + /// + /// The term id. + /// specific term. + /// termId is less than 0. + public Term GetTerm(int termId) + { + //Argument Contract + Requires.NotNegative("termId", termId); + + return CBO.FillObject(_DataService.GetTerm(termId)); + } + + + /// + /// Retrieve usage data for the specified term ID. + /// + /// Term ID in question + public TermUsage GetTermUsage(int termId) + { + Requires.NotNegative("termId", termId); + + return CBO.FillObject(_DataService.GetTermUsage(termId)); + } + + /// + /// Gets the content of the terms by content item id. + /// + /// The content item id. + /// term collection + /// ContentItemId is less than 0. + public IQueryable GetTermsByContent(int contentItemId) + { + //Argument Contract + Requires.NotNegative("contentItemId", contentItemId); + + return CBO.FillQueryable(_DataService.GetTermsByContent(contentItemId)); + } + + /// + /// Gets the terms by vocabulary id. + /// + /// The vocabulary id. + /// term collection + /// vocabularyId is less than 0. + public IQueryable GetTermsByVocabulary(int vocabularyId) + { + //Argument Contract + Requires.NotNegative("vocabularyId", vocabularyId); + + return CBO.GetCachedObject>(new CacheItemArgs(string.Format(_CacheKey, vocabularyId), _CacheTimeOut, _CachePriority, vocabularyId), GetTermsCallBack).AsQueryable(); + } + + /// + /// Gets the terms by vocabulary name. + /// + /// Name of the vocabulary. + /// term collection + /// vocabularyName is empty. + public IQueryable GetTermsByVocabulary(string vocabularyName) + { + //Argument Contract + Requires.NotNullOrEmpty("vocabularyName", vocabularyName); + + IVocabularyController vocabularyController = Util.GetVocabularyController(); + Vocabulary vocabulary = (vocabularyController.GetVocabularies() + .Cast().Where(v => v.Name == vocabularyName)) + .SingleOrDefault(); + + if (vocabulary == null) + { + throw new ArgumentException("Vocabulary does not exist.", "vocabularyName"); + } + + return GetTermsByVocabulary(vocabulary.VocabularyId); + } + + /// + /// Removes all terms from content item. + /// + /// The content item. + /// content item is null. + public void RemoveTermsFromContent(ContentItem contentItem) + { + //Argument Contract + Requires.NotNull("contentItem", contentItem); + + _DataService.RemoveTermsFromContent(contentItem); + } + + /// + /// Updates the term. + /// + /// The term. + /// term is null. + /// term.TermId is less than 0. + /// term.VocabularyId is less than 0. + /// term.Name is empty. + public void UpdateTerm(Term term) + { + //Argument Contract + Requires.NotNull("term", term); + Requires.PropertyNotNegative("term", "TermId", term.TermId); + Requires.PropertyNotNegative("term", "Vocabulary.VocabularyId", term.VocabularyId); + Requires.PropertyNotNullOrEmpty("term", "Name", term.Name); + + if ((term.IsHeirarchical)) + { + _DataService.UpdateHeirarchicalTerm(term, UserController.GetCurrentUserInfo().UserID); + } + else + { + _DataService.UpdateSimpleTerm(term, UserController.GetCurrentUserInfo().UserID); + } + + //Clear Cache + DataCache.RemoveCache(string.Format(_CacheKey, term.VocabularyId)); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/TermUsage.cs b/DNN Platform/Library/Entities/Content/Taxonomy/TermUsage.cs new file mode 100644 index 00000000000..092e5e05075 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/TermUsage.cs @@ -0,0 +1,52 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + public class TermUsage + { + public int TotalTermUsage { get; set; } + + public int MonthTermUsage { get; set; } + + public int WeekTermUsage { get; set; } + + public int DayTermUsage { get; set; } + + /// + /// parameterless constructor, so that it can be used in CBO. + /// + public TermUsage() + { + + } + + internal TermUsage(int total, int month, int week, int day) + { + TotalTermUsage = total; + + MonthTermUsage = month; + + WeekTermUsage = week; + + DayTermUsage = day; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/Vocabulary.cs b/DNN Platform/Library/Entities/Content/Taxonomy/Vocabulary.cs new file mode 100644 index 00000000000..cd644665954 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/Vocabulary.cs @@ -0,0 +1,258 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Class of Vocabulary. + /// + /// + [Serializable] + public class Vocabulary : BaseEntityInfo, IHydratable + { + private string _Description; + private bool _IsSystem; + private string _Name; + private int _ScopeId; + private ScopeType _ScopeType; + private int _ScopeTypeId; + private List _Terms; + private VocabularyType _Type; + private int _VocabularyId; + + private int _Weight; + + #region "Constructors" + + public Vocabulary() : this(Null.NullString, Null.NullString, VocabularyType.Simple) + { + } + + public Vocabulary(string name) : this(name, Null.NullString, VocabularyType.Simple) + { + } + + public Vocabulary(string name, string description) : this(name, description, VocabularyType.Simple) + { + } + + public Vocabulary(VocabularyType type) : this(Null.NullString, Null.NullString, type) + { + } + + public Vocabulary(string name, string description, VocabularyType type) + { + _Description = description; + _Name = name; + _Type = type; + + _ScopeId = Null.NullInteger; + _ScopeTypeId = Null.NullInteger; + _VocabularyId = Null.NullInteger; + _Weight = 0; + } + + #endregion + + #region "Public Properties" + + public string Description + { + get + { + return _Description; + } + set + { + _Description = value; + } + } + + public bool IsHeirarchical + { + get + { + return (Type == VocabularyType.Hierarchy); + } + } + + public bool IsSystem + { + get + { + return _IsSystem; + } + set + { + _IsSystem = value; + } + } + + public string Name + { + get + { + return _Name; + } + set + { + _Name = value; + } + } + + public int ScopeId + { + get + { + return _ScopeId; + } + set + { + _ScopeId = value; + } + } + + public ScopeType ScopeType + { + get + { + if (_ScopeType == null) + { + _ScopeType = this.GetScopeType(_ScopeTypeId); + } + + return _ScopeType; + } + } + + public int ScopeTypeId + { + get + { + return _ScopeTypeId; + } + set + { + _ScopeTypeId = value; + } + } + + public List Terms + { + get + { + if (_Terms == null) + { + _Terms = this.GetTerms(_VocabularyId); + } + return _Terms; + } + } + + public VocabularyType Type + { + get + { + return _Type; + } + set + { + _Type = value; + } + } + + public int VocabularyId + { + get + { + return _VocabularyId; + } + set + { + _VocabularyId = value; + } + } + + public int Weight + { + get + { + return _Weight; + } + set + { + _Weight = value; + } + } + + #endregion + + #region "IHydratable Implementation" + + public virtual void Fill(IDataReader dr) + { + VocabularyId = Null.SetNullInteger(dr["VocabularyID"]); + switch (Convert.ToInt16(dr["VocabularyTypeID"])) + { + case 1: + Type = VocabularyType.Simple; + break; + case 2: + Type = VocabularyType.Hierarchy; + break; + } + IsSystem = Null.SetNullBoolean(dr["IsSystem"]); + Name = Null.SetNullString(dr["Name"]); + Description = Null.SetNullString(dr["Description"]); + ScopeId = Null.SetNullInteger(dr["ScopeID"]); + ScopeTypeId = Null.SetNullInteger(dr["ScopeTypeID"]); + Weight = Null.SetNullInteger(dr["Weight"]); + + //Fill base class properties + FillInternal(dr); + } + + public virtual int KeyID + { + get + { + return VocabularyId; + } + set + { + VocabularyId = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyController.cs b/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyController.cs new file mode 100644 index 00000000000..230ffb36012 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyController.cs @@ -0,0 +1,122 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Data; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// VocabularyController provides the business layer of Vocabulary and VocabularyType. + /// + /// + public class VocabularyController : IVocabularyController + { + private readonly IDataService _DataService; + private string _CacheKey = "Vocabularies"; + private int _CacheTimeOut = 20; + + #region Constructors + + public VocabularyController() : this(Util.GetDataService()) + { + } + + public VocabularyController(IDataService dataService) + { + _DataService = dataService; + } + + #endregion + + #region Private Methods + + private object GetVocabulariesCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillQueryable(_DataService.GetVocabularies()).ToList(); + } + + #endregion + + #region Public Methods + + public int AddVocabulary(Vocabulary vocabulary) + { + //Argument Contract + Requires.NotNull("vocabulary", vocabulary); + Requires.PropertyNotNullOrEmpty("vocabulary", "Name", vocabulary.Name); + Requires.PropertyNotNegative("vocabulary", "ScopeTypeId", vocabulary.ScopeTypeId); + + vocabulary.VocabularyId = _DataService.AddVocabulary(vocabulary, UserController.GetCurrentUserInfo().UserID); + + //Refresh Cache + DataCache.RemoveCache(_CacheKey); + + return vocabulary.VocabularyId; + } + + public void ClearVocabularyCache() + { + DataCache.RemoveCache(_CacheKey); + } + + public void DeleteVocabulary(Vocabulary vocabulary) + { + //Argument Contract + Requires.NotNull("vocabulary", vocabulary); + Requires.PropertyNotNegative("vocabulary", "VocabularyId", vocabulary.VocabularyId); + + _DataService.DeleteVocabulary(vocabulary); + + //Refresh Cache + DataCache.RemoveCache(_CacheKey); + } + + public IQueryable GetVocabularies() + { + return CBO.GetCachedObject>(new CacheItemArgs(_CacheKey, _CacheTimeOut), GetVocabulariesCallBack).AsQueryable(); + } + + public void UpdateVocabulary(Vocabulary vocabulary) + { + //Argument Contract + Requires.NotNull("vocabulary", vocabulary); + Requires.PropertyNotNegative("vocabulary", "VocabularyId", vocabulary.VocabularyId); + Requires.PropertyNotNullOrEmpty("vocabulary", "Name", vocabulary.Name); + + //Refresh Cache + DataCache.RemoveCache(_CacheKey); + + _DataService.UpdateVocabulary(vocabulary, UserController.GetCurrentUserInfo().UserID); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyType.cs b/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyType.cs new file mode 100644 index 00000000000..a1c1f24c504 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Taxonomy/VocabularyType.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Content.Taxonomy +{ + /// + /// Enumeration of VocabularyType. + /// + public enum VocabularyType + { + /// + /// Simple Vocabulary + /// + Simple = 1, + /// + /// The Vocabulary can have parent or child nodes. + /// + Hierarchy = 2 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflow.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflow.cs new file mode 100644 index 00000000000..8e989ade9f5 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflow.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public class ContentWorkflow + { + public int WorkflowID { get; set; } + + public int PortalID { get; set; } + + public string WorkflowName { get; set; } + + public string Description { get; set; } + + public bool IsDeleted { get; set; } + + public bool StartAfterCreating { get; set; } + + public bool StartAfterEditing { get; set; } + + public bool DispositionEnabled { get; set; } + + public IEnumerable States { get; set; } + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowController.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowController.cs new file mode 100644 index 00000000000..aa1434455c6 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowController.cs @@ -0,0 +1,686 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Social.Notifications; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public class ContentWorkflowController : ComponentBase, IContentWorkflowController + { + private ContentController contentController; + private const string ContentWorkflowNotificationType = "ContentWorkflowNotification"; + + private ContentWorkflowController() + { + contentController = new ContentController(); + } + + #region Public Methods + public IEnumerable GetWorkflows(int portalID) + { + return CBO.FillCollection(DataProvider.Instance().GetContentWorkflows(portalID)); + } + + public void StartWorkflow(int workflowID, int itemID, int userID) + { + var item = contentController.GetContentItem(itemID); + var workflow = GetWorkflow(item); + + //If already exists a started workflow + if (workflow != null && !IsWorkflowCompleted(workflow, item)) + { + //TODO; Study if is need to throw an exception + return; + } + if(workflow == null) + workflow = GetWorkflowByID(workflowID); + + //Delete previous logs + DataProvider.Instance().DeleteContentWorkflowLogs(itemID, workflowID); + var newStateID = GetFirstWorkflowStateID(workflow); + SetWorkflowState(newStateID, item); + AddWorkflowLog(item, ContentWorkflowLogType.WorkflowStarted, userID); + AddWorkflowLog(item, ContentWorkflowLogType.StateInitiated, userID); + } + + public void CompleteState(int itemID, string subject, string body, string comment, int portalID, int userID) + { + var item = contentController.GetContentItem(itemID); + var workflow = GetWorkflow(item); + if (workflow == null) + return; + + if (!IsWorkflowCompleted(workflow, item)) + { + var currentState = GetWorkflowStateByID(item.StateID); + if (!String.IsNullOrEmpty(comment)) + { + AddWorkflowCommentLog(item, comment, userID); + } + AddWorkflowLog(item, currentState.StateID == GetFirstWorkflowStateID(workflow) ? ContentWorkflowLogType.DraftCompleted : ContentWorkflowLogType.StateCompleted, userID); + + var endStateID = GetNextWorkflowStateID(workflow, item.StateID); + SetWorkflowState(endStateID, item); + if (endStateID == GetLastWorkflowStateID(workflow)) + { + AddWorkflowLog(item, ContentWorkflowLogType.WorkflowApproved, userID); + } + else + { + AddWorkflowLog(item, ContentWorkflowLogType.StateInitiated, userID); + } + + SendNotification(new PortalSettings(portalID), workflow, item, currentState, subject, body, comment, endStateID, userID); + } + } + + public void DiscardState(int itemID, string subject, string body, string comment, int portalID, int userID) + { + var item = contentController.GetContentItem(itemID); + var workflow = GetWorkflow(item); + if (workflow == null) + return; + + + var currentState = GetWorkflowStateByID(item.StateID); + if ((GetFirstWorkflowStateID(workflow) != currentState.StateID) && (GetLastWorkflowStateID(workflow) != currentState.StateID)) + { + if (!String.IsNullOrEmpty(comment)) + { + AddWorkflowCommentLog(item, comment, userID); + } + AddWorkflowLog(item, ContentWorkflowLogType.StateDiscarded, userID); + int previousStateID = GetPreviousWorkflowStateID(workflow, item.StateID); + SetWorkflowState(previousStateID, item); + AddWorkflowLog(item, ContentWorkflowLogType.StateInitiated, userID); + SendNotification(new PortalSettings(portalID), workflow, item, currentState, subject, body, comment, previousStateID, userID); + } + } + + public bool IsWorkflowCompleted(int itemID) + { + var item = contentController.GetContentItem(itemID); //Ensure DB values + var workflow = GetWorkflow(item); + if (workflow == null) return true; // If item has not workflow, then it is considered as completed + return IsWorkflowCompleted(workflow, item); + } + + public ContentWorkflow GetDefaultWorkflow(int portalID) + { + var wf = GetWorkflows(portalID).First(); // We assume there is only 1 Workflow. This needs to be changed for other scenarios + wf.States = GetWorkflowStates(wf.WorkflowID); + return wf; + } + + public bool IsWorkflowOnDraft(int itemID) + { + var item = contentController.GetContentItem(itemID); //Ensure DB values + var workflow = GetWorkflow(item); + if (workflow == null) return false; // If item has not workflow, then it is not on Draft + return item.StateID == GetFirstWorkflowStateID(workflow); + } + + public ContentWorkflow GetWorkflowByID(int workflowID) + { + var workflow = CBO.FillObject(DataProvider.Instance().GetContentWorkflow(workflowID)); + if (workflow != null) + { + workflow.States = GetWorkflowStates(workflowID); + return workflow; + } + return null; + } + + public ContentWorkflow GetWorkflow(ContentItem item) + { + var state = GetWorkflowStateByID(item.StateID); + if (state == null) return null; + return GetWorkflowByID(state.WorkflowID); + } + + public void AddWorkflow(ContentWorkflow workflow) + { + var id = DataProvider.Instance().AddContentWorkflow(workflow.PortalID, workflow.WorkflowName, workflow.Description, workflow.IsDeleted, workflow.StartAfterCreating, workflow.StartAfterEditing, workflow.DispositionEnabled); + workflow.WorkflowID = id; + } + + public void UpdateWorkflow(ContentWorkflow workflow) + { + DataProvider.Instance().UpdateContentWorkflow(workflow.WorkflowID, workflow.WorkflowName, workflow.Description, workflow.IsDeleted, workflow.StartAfterCreating, workflow.StartAfterEditing, workflow.DispositionEnabled); + } + + public IEnumerable GetWorkflowLogs(int contentItemId, int workflowId) + { + return CBO.FillCollection(DataProvider.Instance().GetContentWorkflowLogs(contentItemId, workflowId)); + } + + public void DeleteWorkflowLogs(int contentItemID, int workflowID) + { + DataProvider.Instance().DeleteContentWorkflowLogs(contentItemID, workflowID); + } + + public IEnumerable GetWorkflowStates(int workflowID) + { + return CBO.FillCollection(DataProvider.Instance().GetContentWorkflowStates(workflowID)); + } + + public void AddWorkflowState(ContentWorkflowState state) + { + var id = DataProvider.Instance().AddContentWorkflowState(state.WorkflowID, + state.StateName, + state.Order, + state.IsActive, + state.SendEmail, + state.SendMessage, + state.IsDisposalState, + state.OnCompleteMessageSubject, + state.OnCompleteMessageBody, + state.OnDiscardMessageSubject, + state.OnDiscardMessageBody); + state.StateID = id; + } + + public void UpdateWorkflowState(ContentWorkflowState state) + { + DataProvider.Instance().UpdateContentWorkflowState(state.StateID, + state.StateName, + state.Order, + state.IsActive, + state.SendEmail, + state.SendMessage, + state.IsDisposalState, + state.OnCompleteMessageSubject, + state.OnCompleteMessageBody, + state.OnDiscardMessageSubject, + state.OnDiscardMessageBody); + } + + public IEnumerable GetWorkflowStatePermissionByState(int stateID) + { + return CBO.FillCollection(DataProvider.Instance().GetContentWorkflowStatePermissionsByStateID(stateID)); + } + + public void AddWorkflowStatePermission(ContentWorkflowStatePermission permission, int lastModifiedByUserID) + { + DataProvider.Instance().AddContentWorkflowStatePermission(permission.StateID, + permission.PermissionID, + permission.RoleID, + permission.AllowAccess, + permission.UserID, + lastModifiedByUserID); + } + + public void UpdateWorkflowStatePermission(ContentWorkflowStatePermission permission, int lastModifiedByUserID) + { + DataProvider.Instance().UpdateContentWorkflowStatePermission(permission.WorkflowStatePermissionID, + permission.StateID, + permission.PermissionID, + permission.RoleID, + permission.AllowAccess, + permission.UserID, + lastModifiedByUserID); + } + + public void DeleteWorkflowStatePermission(int workflowStatePermissionID) + { + DataProvider.Instance().DeleteContentWorkflowStatePermission(workflowStatePermissionID); + } + + public bool IsAnyReviewer(int workflowID) + { + var workflow = GetWorkflowByID(workflowID); + return workflow.States.Any(contentWorkflowState => IsReviewer(contentWorkflowState.StateID) ); + } + + public bool IsAnyReviewer(int portalID, int userID, int workflowID) + { + var workflow = GetWorkflowByID(workflowID); + return workflow.States.Any(contentWorkflowState => IsReviewer(portalID, userID, contentWorkflowState.StateID) ); + } + + public bool IsReviewer(int stateID) + { + var permissions = GetWorkflowStatePermissionByState(stateID); + var user = UserController.GetCurrentUserInfo(); + return IsReviewer(user, PortalSettings.Current, permissions); + } + + public bool IsReviewer(int portalID, int userID, int stateID) + { + var permissions = GetWorkflowStatePermissionByState(stateID); + var user = UserController.GetUserById(portalID, userID); + var portalSettings = new PortalSettings(portalID); + + return IsReviewer(user, portalSettings, permissions); + } + + public bool IsCurrentReviewer(int portalID, int userID, int itemID) + { + var item = contentController.GetContentItem(itemID); + return IsReviewer(portalID, userID, item.StateID); + } + + public bool IsCurrentReviewer(int itemID) + { + var item = contentController.GetContentItem(itemID); + return IsReviewer(item.StateID); + } + + public ContentWorkflowState GetWorkflowStateByID(int stateID) + { + return CBO.FillObject(DataProvider.Instance().GetContentWorkflowState(stateID)); + } + + public void AddWorkflowLog(ContentItem item, string action, string comment, int userID) + { + var workflow = GetWorkflow(item); + + AddWorkflowLog(workflow != null ? workflow.WorkflowID: Null.NullInteger, item, action, comment, userID); + } + + public void CreateDefaultWorkflows(int portalId) + { + var wf = new ContentWorkflow + { + PortalID = portalId, + WorkflowName = Localization.GetString("DefaultWorkflowName"), + Description = Localization.GetString("DefaultWorkflowDescription"), + IsDeleted = false, + StartAfterCreating = false, + StartAfterEditing = true, + DispositionEnabled = false, + States = new List + { + new ContentWorkflowState + { + StateName = Localization.GetString("DefaultWorkflowState1.StateName"), + Order = 1, + IsActive = true, + SendEmail = false, + SendMessage = true, + IsDisposalState = false, + OnCompleteMessageSubject = Localization.GetString("DefaultWorkflowState1.OnCompleteMessageSubject"), + OnCompleteMessageBody = Localization.GetString("DefaultWorkflowState1.OnCompleteMessageBody"), + OnDiscardMessageSubject = Localization.GetString("DefaultWorkflowState1.OnDiscardMessageSubject"), + OnDiscardMessageBody = Localization.GetString("DefaultWorkflowState1.OnDiscardMessageBody") + }, + new ContentWorkflowState + { + StateName = Localization.GetString("DefaultWorkflowState2.StateName"), + Order = 2, + IsActive = true, + SendEmail = false, + SendMessage = true, + IsDisposalState = false, + OnCompleteMessageSubject = Localization.GetString("DefaultWorkflowState2.OnCompleteMessageSubject"), + OnCompleteMessageBody = Localization.GetString("DefaultWorkflowState2.OnCompleteMessageBody"), + OnDiscardMessageSubject = Localization.GetString("DefaultWorkflowState2.OnDiscardMessageSubject"), + OnDiscardMessageBody = Localization.GetString("DefaultWorkflowState2.OnDiscardMessageBody") + }, + new ContentWorkflowState + { + StateName = Localization.GetString("DefaultWorkflowState3.StateName"), + Order = 3, + IsActive = true, + SendEmail = false, + SendMessage = true, + IsDisposalState = false, + OnCompleteMessageSubject = Localization.GetString("DefaultWorkflowState3.OnCompleteMessageSubject"), + OnCompleteMessageBody = Localization.GetString("DefaultWorkflowState3.OnCompleteMessageBody"), + OnDiscardMessageSubject = Localization.GetString("DefaultWorkflowState3.OnDiscardMessageSubject"), + OnDiscardMessageBody = Localization.GetString("DefaultWorkflowState3.OnDiscardMessageBody") + } + } + }; + + AddWorkflow(wf); + foreach (var wfs in wf.States) + { + wfs.WorkflowID = wf.WorkflowID; + AddWorkflowState(wfs); + } + } + + public void SendWorkflowNotification(bool sendEmail, bool sendMessage, PortalSettings settings, IEnumerable roles, IEnumerable users, string subject, string body, + string comment, int userID) + { + var replacedSubject = ReplaceNotificationTokens(subject, null, null, null, settings.PortalId, userID); + var replacedBody = ReplaceNotificationTokens(body, null, null, null, settings.PortalId, userID); + SendNotification(sendEmail, sendMessage, settings, roles, users, replacedSubject, replacedBody, comment, userID); + } + + public void DiscardWorkflow(int contentItemId, string comment, int portalId, int userId) + { + var item = contentController.GetContentItem(contentItemId); + var workflow = GetWorkflow(item); + var stateId = GetLastWorkflowStateID(workflow); + AddWorkflowCommentLog(item, comment, userId); + AddWorkflowLog(item, ContentWorkflowLogType.WorkflowDiscarded, userId); + SetWorkflowState(stateId, item); + } + + public void CompleteWorkflow(int contentItemId, string comment, int portalId, int userId) + { + var item = contentController.GetContentItem(contentItemId); + var workflow = GetWorkflow(item); + var lastStateId = GetLastWorkflowStateID(workflow); + AddWorkflowCommentLog(item, comment, userId); + AddWorkflowLog(item, ContentWorkflowLogType.WorkflowApproved, userId); + SetWorkflowState(lastStateId, item); + } + + public string ReplaceNotificationTokens(string text, ContentWorkflow workflow, ContentItem item, ContentWorkflowState state, int portalID, int userID, string comment = "") + { + var user = UserController.GetUserById(portalID, userID); + var datetime = DateTime.Now; + var result = text.Replace("[USER]", user != null ? user.DisplayName : ""); + result = result.Replace("[DATE]", datetime.ToString("d-MMM-yyyy hh:mm") + datetime.ToString("tt").ToLower()); + result = result.Replace("[STATE]", state != null ? state.StateName : ""); + result = result.Replace("[WORKFLOW]", workflow != null ? workflow.WorkflowName : ""); + result = result.Replace("[CONTENT]", item != null ? item.ContentTitle : ""); + result = result.Replace("[COMMENT]", !String.IsNullOrEmpty(comment) ? comment : ""); + + return result; + } + + #endregion + + #region Private Methods + private void AddWorkflowCommentLog(ContentItem item, string userComment, int userID) + { + var workflow = GetWorkflow(item); + + var logComment = ReplaceNotificationTokens(GetWorkflowActionComment(ContentWorkflowLogType.CommentProvided), workflow, item, workflow.States.FirstOrDefault(s => s.StateID == item.StateID), workflow.PortalID, userID, userComment); + AddWorkflowLog(workflow.WorkflowID, item, GetWorkflowActionText(ContentWorkflowLogType.CommentProvided), logComment, userID); + } + + private void SendNotification(bool sendEmail, bool sendMessage, PortalSettings settings, IEnumerable roles, IEnumerable users, string subject, string body, string comment, int userID) + { + if (sendEmail) + { + SendEmailNotifications(settings, roles, users, subject, body, comment); + } + if (sendMessage) + { + SendMessageNotifications(settings, roles, users, subject, body, comment, userID); + } + } + + private void SendNotification(PortalSettings settings, ContentWorkflow workflow, ContentItem item, ContentWorkflowState state, string subject, string body, string comment, int destinationStateID, int actionUserID) + { + var permissions = GetWorkflowStatePermissionByState(destinationStateID); + var users = GetUsersFromPermissions(settings, permissions); + var roles = GetRolesFromPermissions(settings, permissions); + var replacedSubject = ReplaceNotificationTokens(subject, workflow, item, GetWorkflowStateByID(destinationStateID), settings.PortalId, actionUserID); + var replacedBody = ReplaceNotificationTokens(body, workflow, item, GetWorkflowStateByID(destinationStateID), settings.PortalId, actionUserID); + + SendNotification(state.SendEmail, state.SendMessage, settings, roles, users, replacedSubject, replacedBody, comment, actionUserID); + } + + private void SendMessageNotifications(PortalSettings settings, IEnumerable roles, IEnumerable users, string subject, string body, string comment, int actionUserID) + { + //TODO: Confirm the final body and comment format + var fullbody = GetFullBody(body, comment); + + if (!roles.Any() && !users.Any()) + { + return; // If there are no receivers, the notification is avoided + } + + var notification = new Notification + { + NotificationTypeID = NotificationsController.Instance.GetNotificationType(ContentWorkflowNotificationType).NotificationTypeId, + Subject = subject, + Body = fullbody, + IncludeDismissAction = true, + SenderUserID = actionUserID + }; + + NotificationsController.Instance.SendNotification(notification, settings.PortalId, roles.ToList(), users.ToList()); + } + + private string GetFullBody(string body, string comment) + { + return body + "

" + comment; + } + + private void SendEmailNotifications(PortalSettings settings, IEnumerable roles, IEnumerable users, string subject, string body, string comment) + { + //TODO: Confirm the final body and comment format + var fullbody = GetFullBody(body, comment); + var roleController = new RoleController(); + var emailUsers = users.ToList(); + foreach (var role in roles) + { + var roleUsers = roleController.GetUsersByRoleName(settings.PortalId, role.RoleName); + emailUsers.AddRange(from UserInfo user in roleUsers select user); + } + + foreach (var userMail in emailUsers.Select(u => u.Email).Distinct()) + { + Mail.SendEmail(settings.Email, userMail, subject, fullbody); + } + } + + private IEnumerable GetRolesFromPermissions(PortalSettings settings, IEnumerable permissions) + { + var roles = new List(); + var roleController = new RoleController(); + foreach (var permission in permissions) + { + if (permission.AllowAccess) + { + if (permission.RoleID > Null.NullInteger) + { + roles.Add(roleController.GetRole(permission.RoleID, settings.PortalId)); + } + } + } + return roles; + } + + private IEnumerable GetUsersFromPermissions(PortalSettings settings, IEnumerable permissions) + { + var users = new List(); + foreach (var permission in permissions) + { + if (permission.AllowAccess) + { + if (permission.UserID > Null.NullInteger) + { + users.Add(UserController.GetUserById(settings.PortalId, permission.UserID)); + } + } + } + return users; + } + + private bool IsReviewer(UserInfo user, PortalSettings settings, IEnumerable permissions) + { + var administratorRoleName = settings.AdministratorRoleName; + return user.IsSuperUser || PortalSecurity.IsInRoles(user, settings, administratorRoleName) || PortalSecurity.IsInRoles(user, settings, PermissionController.BuildPermissions(permissions.ToList(), "REVIEW")); + } + + private void AddWorkflowLog(ContentItem item, ContentWorkflowLogType logType, int userID) + { + var workflow = GetWorkflow(item); + + var comment = ReplaceNotificationTokens(GetWorkflowActionComment(logType), workflow, item, workflow.States.FirstOrDefault(s => s.StateID == item.StateID), workflow.PortalID, userID); + + AddWorkflowLog(workflow.WorkflowID, item, GetWorkflowActionText(logType), comment, userID); + } + + private void AddWorkflowLog(int workflowID, ContentItem item, string action, string comment, int userID) + { + DataProvider.Instance().AddContentWorkflowLog(action, comment, userID, workflowID, item.ContentItemId); + } + + private string GetWorkflowActionText(ContentWorkflowLogType logType) + { + var logName = Enum.GetName(typeof(ContentWorkflowLogType), logType); + return Localization.GetString(logName + ".Action"); + } + + private string GetWorkflowActionComment(ContentWorkflowLogType logType) + { + var logName = Enum.GetName(typeof(ContentWorkflowLogType), logType); + return Localization.GetString(logName + ".Comment"); + } + + private int GetFirstWorkflowStateID(ContentWorkflow workflow) + { + int intStateID = -1; + var states = workflow.States; + if (states.Any()) + { + intStateID = states.OrderBy(s => s.Order).FirstOrDefault().StateID; + } + return intStateID; + } + + private int GetLastWorkflowStateID(ContentWorkflow workflow) + { + int intStateID = -1; + var states = workflow.States; + if (states.Any()) + { + intStateID = states.OrderBy(s => s.Order).LastOrDefault().StateID; + } + return intStateID; + } + + private int GetPreviousWorkflowStateID(ContentWorkflow workflow, int stateID) + { + int intPreviousStateID = -1; + + var states = workflow.States.OrderBy(s => s.Order); + int intItem = 0; + + // locate the current state + var initState = states.SingleOrDefault(s => s.StateID == stateID); + if (initState != null) + { + intPreviousStateID = initState.StateID; + } + for (int i = 0; i < states.Count(); i++) + { + if (states.ElementAt(i).StateID == stateID) + { + intPreviousStateID = stateID; + intItem = i; + } + } + // get previous active state + if (intPreviousStateID == stateID) + { + intItem = intItem - 1; + while (intItem >= 0) + { + if (states.ElementAt(intItem).IsActive) + { + intPreviousStateID = states.ElementAt(intItem).StateID; + break; + } + intItem = intItem - 1; + } + } + + // if none found then reset to first state + if (intPreviousStateID == -1) + { + intPreviousStateID = GetFirstWorkflowStateID(workflow); + } + + return intPreviousStateID; + } + + private int GetNextWorkflowStateID(ContentWorkflow workflow, int stateID) + { + int intNextStateID = -1; + var states = workflow.States.OrderBy(s => s.Order); + int intItem = 0; + + // locate the current state + for (intItem = 0; intItem < states.Count(); intItem++) + { + if (states.ElementAt(intItem).StateID == stateID) + { + intNextStateID = stateID; + break; + } + } + + // get next active state + if (intNextStateID == stateID) + { + intItem = intItem + 1; + while (intItem < states.Count()) + { + if (states.ElementAt(intItem).IsActive) + { + intNextStateID = states.ElementAt(intItem).StateID; + break; + } + intItem = intItem + 1; + } + } + + // if none found then reset to first state + if (intNextStateID == -1) + { + intNextStateID = GetFirstWorkflowStateID(workflow); + } + + return intNextStateID; + } + + private void SetWorkflowState(int stateID, ContentItem item) + { + item.StateID = stateID; + contentController.UpdateContentItem(item); + } + + private bool IsWorkflowCompleted(ContentWorkflow workflow, ContentItem item) + { + var endStateID = GetLastWorkflowStateID(workflow); + + return item.StateID == Null.NullInteger || endStateID == item.StateID; + } + + #endregion + + + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLog.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLog.cs new file mode 100644 index 00000000000..eddb7f6005e --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLog.cs @@ -0,0 +1,36 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public class ContentWorkflowLog + { + public int WorkflowLogID { get; set; } + public int WorkflowID { get; set; } + public int ContentItemID { get; set; } + public string Action { get; set; } + public string Comment { get; set; } + public DateTime Date { get; set; } + public int User { get; set; } + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLogType.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLogType.cs new file mode 100644 index 00000000000..cb8ab42b36f --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowLogType.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public enum ContentWorkflowLogType + { + WorkflowStarted, + StateCompleted, + DraftCompleted, + StateDiscarded, + StateInitiated, + WorkflowApproved, + WorkflowDiscarded, + CommentProvided, + WorkflowError + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowState.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowState.cs new file mode 100644 index 00000000000..7646928c4d3 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowState.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Xml.Serialization; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public class ContentWorkflowState + { + public int StateID { get; set; } + + public int WorkflowID { get; set; } + + public string StateName { get; set; } + + public int Order { get; set; } + + public bool IsActive { get; set; } + + public bool SendEmail { get; set; } + + public bool SendMessage { get; set; } + + public bool IsDisposalState { get; set; } + + public string OnCompleteMessageSubject { get; set; } + + public string OnCompleteMessageBody { get; set; } + + public string OnDiscardMessageSubject { get; set; } + + public string OnDiscardMessageBody { get; set; } + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowStatePermission.cs b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowStatePermission.cs new file mode 100644 index 00000000000..456304ac35c --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/ContentWorkflowStatePermission.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +using DotNetNuke.Security.Permissions; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public class ContentWorkflowStatePermission : PermissionInfoBase + { + public int WorkflowStatePermissionID { get; set; } + + public int StateID { get; set; } + } +} diff --git a/DNN Platform/Library/Entities/Content/Workflow/IContentWorkflowController.cs b/DNN Platform/Library/Entities/Content/Workflow/IContentWorkflowController.cs new file mode 100644 index 00000000000..3a56a1dc722 --- /dev/null +++ b/DNN Platform/Library/Entities/Content/Workflow/IContentWorkflowController.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +namespace DotNetNuke.Entities.Content.Workflow +{ + public interface IContentWorkflowController + { + IEnumerable GetWorkflows(int portalID); + + void StartWorkflow(int workflowID, int itemID, int userID); + + void CompleteState(int itemID, string subject, string body, string comment, int portalID, int userID); + + void DiscardState(int itemID, string subject, string body, string comment, int portalID, int userID); + + bool IsWorkflowCompleted(int itemID); + + ContentWorkflow GetDefaultWorkflow(int portalID); + + bool IsWorkflowOnDraft(int itemID); + + ContentWorkflow GetWorkflowByID(int workflowID); + + ContentWorkflow GetWorkflow(ContentItem item); + + void AddWorkflow(ContentWorkflow workflow); + + void UpdateWorkflow(ContentWorkflow workflow); + + IEnumerable GetWorkflowLogs(int workflowId, int contentItemId); + + void DeleteWorkflowLogs(int workflowID, int contentItemID); + + IEnumerable GetWorkflowStates(int workflowID); + + ContentWorkflowState GetWorkflowStateByID(int stateID); + + void AddWorkflowState(ContentWorkflowState state); + + void UpdateWorkflowState(ContentWorkflowState state); + + IEnumerable GetWorkflowStatePermissionByState(int stateID); + + void AddWorkflowStatePermission(ContentWorkflowStatePermission permission, int lastModifiedByUserID); + + void UpdateWorkflowStatePermission(ContentWorkflowStatePermission permission, int lasModifiedByUserId); + + void DeleteWorkflowStatePermission(int workflowStatePermissionID); + + bool IsAnyReviewer(int portalID, int userID, int workflowID); + + bool IsAnyReviewer(int workflowID); + + bool IsCurrentReviewer(int portalId, int userID, int itemID); + + bool IsCurrentReviewer(int itemID); + + bool IsReviewer(int portalId, int userID, int stateID); + + bool IsReviewer(int stateID); + + void AddWorkflowLog(ContentItem item, string action, string comment, int userID); + + void CreateDefaultWorkflows(int portalId); + + void SendWorkflowNotification(bool sendEmail, bool sendMessage, PortalSettings settings, IEnumerable roles, IEnumerable users, string subject, string body, string comment, + int userID); + + void DiscardWorkflow(int contentItemId, string comment, int portalId, int userId); + + void CompleteWorkflow(int contentItemId, string comment, int portalId, int userId); + + string ReplaceNotificationTokens(string text, ContentWorkflow workflow, ContentItem item, ContentWorkflowState state, int portalID, int userID, string comment = ""); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Controllers/HostController.cs b/DNN Platform/Library/Entities/Controllers/HostController.cs new file mode 100644 index 00000000000..6ce0e839db0 --- /dev/null +++ b/DNN Platform/Library/Entities/Controllers/HostController.cs @@ -0,0 +1,373 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +using System.Globalization; +using DotNetNuke.Web.Client; +#endregion + +namespace DotNetNuke.Entities.Controllers +{ + /// + /// HostController provides business layer of host settings. + /// + /// + /// + /// public static bool CheckUpgrade + /// { + /// get + /// { + /// return HostController.Instance.GetBoolean("CheckUpgrade", true); + /// } + /// } + /// + /// + public class HostController : ComponentBase, IHostController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (HostController)); + internal HostController() + { + } + + #region IHostController Members + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// host setting's value. + /// key is empty. + public bool GetBoolean(string key) + { + return GetBoolean(key, Null.NullBoolean); + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// this value will be return if setting's value is empty. + /// host setting's value. + /// key is empty. + public bool GetBoolean(string key, bool defaultValue) + { + Requires.NotNullOrEmpty("key", key); + + bool retValue = false; + try + { + string setting = string.Empty; + if ((GetSettings().ContainsKey(key))) + { + setting = GetSettings()[key].Value; + } + + if (string.IsNullOrEmpty(setting)) + { + retValue = defaultValue; + } + else + { + retValue = (setting.ToUpperInvariant().StartsWith("Y") || setting.ToUpperInvariant() == "TRUE"); + } + } + catch (Exception exc) + { + Logger.Error(exc); + //we just want to trap the error as we may not be installed so there will be no Settings + } + return retValue; + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// host setting's value. + /// key is empty. + public double GetDouble(string key) + { + return GetDouble(key, Null.NullDouble); + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// this value will be return if setting's value is empty. + /// host setting's value. + /// key is empty. + public double GetDouble(string key, double defaultValue) + { + Requires.NotNullOrEmpty("key", key); + + double retValue; + + if ((!GetSettings().ContainsKey(key) || !double.TryParse(GetSettings()[key].Value, out retValue))) + { + retValue = defaultValue; + } + + return retValue; + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// host setting's value. + /// key is empty. + public int GetInteger(string key) + { + return GetInteger(key, Null.NullInteger); + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// this value will be return if setting's value is empty. + /// host setting's value. + /// key is empty. + public int GetInteger(string key, int defaultValue) + { + Requires.NotNullOrEmpty("key", key); + + int retValue; + + if ((!GetSettings().ContainsKey(key) || !int.TryParse(GetSettings()[key].Value, out retValue))) + { + retValue = defaultValue; + } + + return retValue; + } + + /// + /// Gets all host settings. + /// + /// host setting. + public Dictionary GetSettings() + { + return CBO.GetCachedObject>( + new CacheItemArgs(DataCache.HostSettingsCacheKey, + DataCache.HostSettingsCacheTimeOut, + DataCache.HostSettingsCachePriority), + GetSettingsDictionaryCallBack, + true); + } + + /// + /// Gets all host settings as dictionary. + /// + /// host setting's value. + public Dictionary GetSettingsDictionary() + { + return GetSettings().ToDictionary(c => c.Key, c => c.Value.Value); + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// host setting's value. + /// key is empty. + public string GetString(string key) + { + return GetString(key, string.Empty); + } + + /// + /// Gets the setting value by the specific key. + /// + /// The key. + /// this value will be return if setting's value is empty. + /// host setting's value. + /// key is empty. + public string GetString(string key, string defaultValue) + { + Requires.NotNullOrEmpty("key", key); + + if (!GetSettings().ContainsKey(key) || GetSettings()[key].Value == null) + { + return defaultValue; + } + + return GetSettings()[key].Value; + } + + /// + /// Updates the specified settings. + /// + /// The settings. + public void Update(Dictionary settings) + { + foreach (KeyValuePair settingKvp in settings) + { + Update(settingKvp.Key, settingKvp.Value, false); + } + + DataCache.ClearHostCache(false); + } + + /// + /// Updates the specified config. + /// + /// The config. + public void Update(ConfigurationSetting config) + { + Update(config, true); + } + + /// + /// Updates the specified config. + /// + /// The config. + /// if set to true will clear cache after update the setting. + public void Update(ConfigurationSetting config, bool clearCache) + { + var objEventLog = new EventLogController(); + try + { + var settings = GetSettingsFromDatabase(); + if (settings.ContainsKey(config.Key)) + { + ConfigurationSetting currentconfig; + settings.TryGetValue(config.Key, out currentconfig); + if (currentconfig != null && currentconfig.Value != config.Value) + { + DataProvider.Instance().UpdateHostSetting(config.Key, config.Value, config.IsSecure, UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(config.Key, + config.Value, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.HOST_SETTING_UPDATED); + } + } + else + { + DataProvider.Instance().AddHostSetting(config.Key, config.Value, config.IsSecure, UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(config.Key, + config.Value, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.HOST_SETTING_CREATED); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + + if ((clearCache)) + { + DataCache.ClearHostCache(false); + } + } + + /// + /// Updates the specified key. + /// + /// The key. + /// The value. + /// if set to true will clear cache after update settings. + public void Update(string key, string value, bool clearCache) + { + Update(new ConfigurationSetting { Key = key, Value = value }, clearCache); + } + + /// + /// Updates the specified key. + /// + /// The key. + /// The value. + public void Update(string key, string value) + { + Update(key, value, true); + } + + public void IncrementCrmVersion(bool includeOverridingPortals) + { + var currentVersion = Host.Host.CrmVersion; + var newVersion = currentVersion + 1; + Update(ClientResourceSettings.VersionKey, newVersion.ToString(CultureInfo.InvariantCulture), true); + + if (includeOverridingPortals) + { + PortalController.IncrementOverridingPortalsCrmVersion(); + } + } + + #endregion + + private static Dictionary GetSettingsFromDatabase() + { + var dicSettings = new Dictionary(); + IDataReader dr = null; + try + { + dr = DataProvider.Instance().GetHostSettings(); + while (dr.Read()) + { + string key = dr.GetString(0); + var config = new ConfigurationSetting + { + Key = key, + IsSecure = Convert.ToBoolean(dr[2]), + Value = dr.IsDBNull(1) ? string.Empty : dr.GetString(1) + }; + + dicSettings.Add(key, config); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return dicSettings; + } + + private static object GetSettingsDictionaryCallBack(CacheItemArgs cacheItemArgs) + { + return GetSettingsFromDatabase(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Controllers/IHostController.cs b/DNN Platform/Library/Entities/Controllers/IHostController.cs new file mode 100644 index 00000000000..d1c68df26f5 --- /dev/null +++ b/DNN Platform/Library/Entities/Controllers/IHostController.cs @@ -0,0 +1,67 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Entities.Controllers +{ + /// + /// Interface of HostController. + /// + /// + public interface IHostController + { + bool GetBoolean(string key); + + bool GetBoolean(string key, bool defaultValue); + + double GetDouble(string key, double defaultValue); + + double GetDouble(string key); + + int GetInteger(string key); + + int GetInteger(string key, int defaultValue); + + Dictionary GetSettings(); + + Dictionary GetSettingsDictionary(); + + string GetString(string key); + + string GetString(string key, string defaultValue); + + void Update(Dictionary settings); + + void Update(ConfigurationSetting config); + + void Update(ConfigurationSetting config, bool clearCache); + + void Update(string key, string value, bool clearCache); + + void Update(string key, string value); + + void IncrementCrmVersion(bool includeOverridingPortals); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/DataStructures/NTree.cs b/DNN Platform/Library/Entities/DataStructures/NTree.cs new file mode 100644 index 00000000000..b2d76584a13 --- /dev/null +++ b/DNN Platform/Library/Entities/DataStructures/NTree.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace DotNetNuke.Entities.DataStructures +{ + [Serializable] + [DataContract] + public class NTree + { + public NTree() + { + Children = new List>(); + } + + [DataMember(Name = "data")] + public T Data; + + [DataMember(Name = "children")] + public List> Children; + + public bool HasChildren() + { + return Children != null && Children.Count > 0; + } + + } + +} diff --git a/DNN Platform/Library/Entities/Host/Host.cs b/DNN Platform/Library/Entities/Host/Host.cs new file mode 100644 index 00000000000..76246a123d2 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/Host.cs @@ -0,0 +1,1801 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Framework; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Scheduling; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + using Web.Client; + + /// + /// Contains most of the host settings. + /// + public class Host : BaseEntityInfo + { + #region Public Shared Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the AutoAccountUnlockDuration + /// + /// + /// Defaults to 10 + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int AutoAccountUnlockDuration + { + get + { + return HostController.Instance.GetInteger("AutoAccountUnlockDuration", 10); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the AuthenticatedCacheability + /// + /// + /// Defaults to HttpCacheability.ServerAndNoCache + /// + /// + /// [cnurse] 03/05/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string AuthenticatedCacheability + { + get + { + return HostController.Instance.GetString("AuthenticatedCacheability", "4"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Upgrade Indicator is enabled + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CheckUpgrade + { + get + { + return HostController.Instance.GetBoolean("CheckUpgrade", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Control Panel + /// + /// + /// Defaults to glbDefaultControlPanel constant + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string ControlPanel + { + get + { + string setting = HostController.Instance.GetString("ControlPanel"); + if (string.IsNullOrEmpty(setting)) + { + setting = Globals.glbDefaultControlPanel; + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Indicates whether Composite Files are enabled at the host level. + /// + /// + /// [irobinson] 02/25/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CrmEnableCompositeFiles + { + get + { + return HostController.Instance.GetBoolean(ClientResourceSettings.EnableCompositeFilesKey, false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Indicates whether CSS Minification is enabled at the host level. + /// + /// + /// [irobinson] 02/25/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CrmMinifyCss + { + get + { + return HostController.Instance.GetBoolean(ClientResourceSettings.MinifyCssKey); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Indicates whether JS Minification is enabled at the host level. + /// + /// + /// [irobinson] 02/25/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CrmMinifyJs + { + get + { + return HostController.Instance.GetBoolean(ClientResourceSettings.MinifyJsKey); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns the Client Resource Management version number. + /// + /// + /// Defaults to 1 + /// + /// + /// [irobinson] 02/25/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static int CrmVersion + { + get + { + return HostController.Instance.GetInteger(ClientResourceSettings.VersionKey, 1); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Admin Container + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string DefaultAdminContainer + { + get + { + string setting = HostController.Instance.GetString("DefaultAdminContainer"); + if (string.IsNullOrEmpty(setting)) + { + setting = SkinController.GetDefaultAdminContainer(); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Admin Skin + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string DefaultAdminSkin + { + get + { + string setting = HostController.Instance.GetString("DefaultAdminSkin"); + if (string.IsNullOrEmpty(setting)) + { + setting = SkinController.GetDefaultAdminSkin(); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Doc Type + /// + /// + /// [cnurse] 07/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string DefaultDocType + { + get + { + string doctype = ""; + string setting = HostController.Instance.GetString("DefaultDocType"); + if (!string.IsNullOrEmpty(setting)) + { + switch (setting) + { + case "0": + doctype = ""; + break; + case "1": + doctype = ""; + break; + case "2": + doctype = ""; + break; + case "3": + doctype = ""; + break; + } + } + return doctype; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Portal Container + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string DefaultPortalContainer + { + get + { + string setting = HostController.Instance.GetString("DefaultPortalContainer"); + if (string.IsNullOrEmpty(setting)) + { + setting = SkinController.GetDefaultPortalContainer(); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Portal Skin + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string DefaultPortalSkin + { + get + { + string setting = HostController.Instance.GetString("DefaultPortalSkin"); + if (string.IsNullOrEmpty(setting)) + { + setting = SkinController.GetDefaultPortalSkin(); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Demo Period for new portals + /// + /// + /// Defaults to -1 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int DemoPeriod + { + get + { + return HostController.Instance.GetInteger("DemoPeriod"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether demo signups are enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 04/14/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static bool DemoSignup + { + get + { + return HostController.Instance.GetBoolean("DemoSignup", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to dislpay the beta notice + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 05/19/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static bool DisplayBetaNotice + { + get + { + return HostController.Instance.GetBoolean("DisplayBetaNotice", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to dislpay the copyright + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 03/05/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool DisplayCopyright + { + get + { + return HostController.Instance.GetBoolean("Copyright", true); + } + } + + /// + /// Enable checking for banned words when setting password during registration + /// + public static bool EnableBannedList + { + get + { + return HostController.Instance.GetBoolean("EnableBannedList", true); + } + } + + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Browser Language Detection is Enabled + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 02/19/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableBrowserLanguage + { + get + { + return HostController.Instance.GetBoolean("EnableBrowserLanguage", true); + } + } + + public static bool EnableContentLocalization + { + get + { + return HostController.Instance.GetBoolean("EnableContentLocalization", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether a css class based on the Module Name is automatically rendered + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 06/30/2010 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableCustomModuleCssClass + { + get + { + return HostController.Instance.GetBoolean("EnableCustomModuleCssClass", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether File AutoSync is Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableFileAutoSync + { + get + { + return HostController.Instance.GetBoolean("EnableFileAutoSync", false); + } + } + + /// + /// enable whether the IP address of the user is checked against a list during login + /// + public static bool EnableIPChecking + { + get + { + return HostController.Instance.GetBoolean("EnableIPChecking", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Module Online Help is Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableModuleOnLineHelp + { + get + { + return HostController.Instance.GetBoolean("EnableModuleOnLineHelp", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Request Filters are Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableRequestFilters + { + get + { + return HostController.Instance.GetBoolean("EnableRequestFilters", false); + } + } + + /// + /// enable whether a client-side password strength meter is shown on registration screen + /// + public static bool EnableStrengthMeter + { + get + { + return HostController.Instance.GetBoolean("EnableStrengthMeter", false); + } + } + + /// + /// enable whether a previous passwords are stored to check if user is reusing them + /// + public static bool EnablePasswordHistory + { + get + { + return HostController.Instance.GetBoolean("EnablePasswordHistory", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to use the Language in the Url + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 02/19/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableUrlLanguage + { + get + { + return HostController.Instance.GetBoolean("EnableUrlLanguage", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Users Online are Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableUsersOnline + { + get + { + return !HostController.Instance.GetBoolean("DisableUsersOnline", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether SSL is Enabled for SMTP + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EnableSMTPSSL + { + get + { + return HostController.Instance.GetBoolean("SMTPEnableSSL", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Event Log Buffer is Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool EventLogBuffer + { + get + { + return HostController.Instance.GetBoolean("EventLogBuffer", false); + } + } + + /// + /// Gets the allowed file extensions. + /// + public static FileExtensionWhitelist AllowedExtensionWhitelist + { + get + { + return new FileExtensionWhitelist(HostController.Instance.GetString("FileExtensions")); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the GUID + /// + /// + /// [cnurse] 12/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string GUID + { + get + { + return HostController.Instance.GetString("GUID"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Help URL + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string HelpURL + { + get + { + return HostController.Instance.GetString("HelpURL"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Currency + /// + /// + /// Defaults to USD + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string HostCurrency + { + get + { + string setting = HostController.Instance.GetString("HostCurrency"); + if (string.IsNullOrEmpty(setting)) + { + setting = "USD"; + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Email + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string HostEmail + { + get + { + return HostController.Instance.GetString("HostEmail"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Fee + /// + /// + /// Defaults to 0 + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static double HostFee + { + get + { + return HostController.Instance.GetDouble("HostFee", 0); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Portal's PortalId + /// + /// + /// Defaults to Null.NullInteger + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int HostPortalID + { + get + { + return HostController.Instance.GetInteger("HostPortalId"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Space + /// + /// + /// Defaults to 0 + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static double HostSpace + { + get + { + return HostController.Instance.GetDouble("HostSpace", 0); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host Title + /// + /// + /// [cnurse] 12/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string HostTitle + { + get + { + return HostController.Instance.GetString("HostTitle"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Host URL + /// + /// + /// [cnurse] 04/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string HostURL + { + get + { + return HostController.Instance.GetString("HostURL"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the HttpCompression Algorithm + /// + /// + /// Defaults to Null.NullInteger(None) + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int HttpCompressionAlgorithm + { + get + { + return HostController.Instance.GetInteger("HttpCompression"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns size of the batch used to determine how many emails are sent per CoreMessaging Scheduler run + /// + /// + /// Defaults to 50 + /// + /// ----------------------------------------------------------------------------- + public static int MessageSchedulerBatchSize + { + get + { + return HostController.Instance.GetInteger("MessageSchedulerBatchSize",50); + } + } + + /// + /// set length of time (in minutes) that reset links are valid for - default is 60 + /// + public static int MembershipResetLinkValidity + { + get + { + return HostController.Instance.GetInteger("MembershipResetLinkValidity", 60); + } + } + + /// + /// set number of passwords stored for password change comparison operations - default is 5 + /// + public static int MembershipNumberPasswords + { + get + { + return HostController.Instance.GetInteger("MembershipNumberPasswords", 5); + } + } + + /// + /// sets the HTTP Status code returned if IP address filtering is enabled on login + /// and the users IP does not meet criteria -default is 403 + /// + public static string MembershipFailedIPException + { + get + { + return HostController.Instance.GetString("MembershipFailedIPException", "403"); + } + } + + + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Caching method + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string ModuleCachingMethod + { + get + { + return HostController.Instance.GetString("ModuleCaching"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Page Caching method + /// + /// + /// [jbrinkman] 11/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static string PageCachingMethod + { + get + { + return HostController.Instance.GetString("PageCaching"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Page Quota + /// + /// + /// Defaults to 0 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int PageQuota + { + get + { + return HostController.Instance.GetInteger("PageQuota", 0); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PageState Persister + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string PageStatePersister + { + get + { + string setting = HostController.Instance.GetString("PageStatePersister"); + if (string.IsNullOrEmpty(setting)) + { + setting = "P"; + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Password Expiry + /// + /// + /// Defaults to 0 + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int PasswordExpiry + { + get + { + return HostController.Instance.GetInteger("PasswordExpiry", 0); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Password Expiry Reminder window + /// + /// + /// Defaults to 7 (1 week) + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int PasswordExpiryReminder + { + get + { + return HostController.Instance.GetInteger("PasswordExpiryReminder", 7); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Payment Processor + /// + /// + /// [cnurse] 04/14/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static string PaymentProcessor + { + get + { + return HostController.Instance.GetString("PaymentProcessor"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PerformanceSettings + /// + /// + /// Defaults to PerformanceSettings.ModerateCaching + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Globals.PerformanceSettings PerformanceSetting + { + get + { + Globals.PerformanceSettings setting = Globals.PerformanceSettings.ModerateCaching; + string s = HostController.Instance.GetString("PerformanceSetting"); + if (!string.IsNullOrEmpty(s)) + { + setting = (Globals.PerformanceSettings) Enum.Parse(typeof (Globals.PerformanceSettings), s); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Payment Processor Password + /// + /// + /// [cnurse] 04/14/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static string ProcessorPassword + { + get + { + return HostController.Instance.GetString("ProcessorPassword"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Payment Processor User Id + /// + /// + /// [cnurse] 04/14/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static string ProcessorUserId + { + get + { + return HostController.Instance.GetString("ProcessorUserId"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Proxy Server Password + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string ProxyPassword + { + get + { + return HostController.Instance.GetString("ProxyPassword"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Proxy Server Port + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int ProxyPort + { + get + { + return HostController.Instance.GetInteger("ProxyPort"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Proxy Server + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string ProxyServer + { + get + { + return HostController.Instance.GetString("ProxyServer"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Proxy Server UserName + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string ProxyUsername + { + get + { + return HostController.Instance.GetString("ProxyUsername"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to use the remember me checkbox + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 04/14/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static bool RememberCheckbox + { + get + { + return HostController.Instance.GetBoolean("RememberCheckbox", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Scheduler Mode + /// + /// + /// Defaults to SchedulerMode.TIMER_METHOD + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static SchedulerMode SchedulerMode + { + get + { + SchedulerMode setting = SchedulerMode.TIMER_METHOD; + string s = HostController.Instance.GetString("SchedulerMode"); + if (!string.IsNullOrEmpty(s)) + { + setting = (SchedulerMode) Enum.Parse(typeof (SchedulerMode), s); + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Common Words in the Search Index + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool SearchIncludeCommon + { + get + { + return HostController.Instance.GetBoolean("SearchIncludeCommon", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Numbers in the Search Index + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool SearchIncludeNumeric + { + get + { + return HostController.Instance.GetBoolean("SearchIncludeNumeric", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the maximum Search Word length to index + /// + /// + /// Defaults to 25 + /// + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SearchMaxWordlLength + { + get + { + return HostController.Instance.GetInteger("MaxSearchWordLength", 50); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the maximum Search Word length to index + /// + /// + /// Defaults to 3 + /// + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SearchMinWordlLength + { + get + { + return HostController.Instance.GetInteger("MinSearchWordLength", 4); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the filter used for inclusion of tag info + /// + /// + /// Defaults to "" + /// + /// + /// [vnguyen] 09/03/2010 Created + /// + /// ----------------------------------------------------------------------------- + public static string SearchIncludedTagInfoFilter + { + get + { + return HostController.Instance.GetString("SearchIncludedTagInfoFilter", ""); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Site Log Buffer size + /// + /// + /// Defaults to 1 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SiteLogBuffer + { + get + { + return HostController.Instance.GetInteger("SiteLogBuffer", 1); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Site Log History + /// + /// + /// Defaults to -1 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SiteLogHistory + { + get + { + return HostController.Instance.GetInteger("SiteLogHistory"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Site Log Storage location + /// + /// + /// Defaults to "D" + /// + /// + /// [cnurse] 03/05/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string SiteLogStorage + { + get + { + string setting = HostController.Instance.GetString("SiteLogStorage"); + if (string.IsNullOrEmpty(setting)) + { + setting = "D"; + } + return setting; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the SMTP Authentication + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string SMTPAuthentication + { + get + { + return HostController.Instance.GetString("SMTPAuthentication"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the SMTP Password + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string SMTPPassword + { + get + { + return HostController.Instance.GetString("SMTPPassword"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the SMTP Server + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string SMTPServer + { + get + { + return HostController.Instance.GetString("SMTPServer"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the SMTP Username + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static string SMTPUsername + { + get + { + return HostController.Instance.GetString("SMTPUsername"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Exceptions are rethrown + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 07/24/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool ThrowCBOExceptions + { + get + { + return HostController.Instance.GetBoolean("ThrowCBOExceptions", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Friendly Urls is Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool UseFriendlyUrls + { + get + { + return HostController.Instance.GetBoolean("UseFriendlyUrls", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Custom Error Messages is Enabled + /// + /// + /// Defaults to False + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool UseCustomErrorMessages + { + get + { + return HostController.Instance.GetBoolean("UseCustomErrorMessages", false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the User Quota + /// + /// + /// Defaults to 0 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int UserQuota + { + get + { + return HostController.Instance.GetInteger("UserQuota", 0); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the window to use in minutes when determining if the user is online + /// + /// + /// Defaults to 15 + /// + /// + /// [cnurse] 01/29/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int UsersOnlineTimeWindow + { + get + { + return HostController.Instance.GetInteger("UsersOnlineTime", 15); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the WebRequest Timeout value + /// + /// + /// Defaults to 10000 + /// + /// + /// [cnurse] 01/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int WebRequestTimeout + { + get + { + return HostController.Instance.GetInteger("WebRequestTimeout", 10000); + } + } + + /// + /// Gets whether to use the minified or debug version of the jQuery scripts + /// + /// + /// Defaults to False + /// + /// + /// [jbrinkman] 09/30/2008 Created + /// + public static bool jQueryDebug + { + get + { + return HostController.Instance.GetBoolean("jQueryDebug", false); + } + } + + /// + /// Gets whether to use a hosted version of the jQuery script file + /// + /// + /// Defaults to False + /// + /// + /// [jbrinkman] 09/30/2008 Created + /// + public static bool jQueryHosted + { + get + { + return HostController.Instance.GetBoolean("jQueryHosted", false); + } + } + + /// + /// Gets the Url for a hosted version of jQuery + /// + /// + /// Defaults to the DefaultHostedUrl constant in the jQuery class. + /// The framework will default to the latest released 1.x version hosted on Google. + /// + public static string jQueryUrl + { + get + { + if (HttpContext.Current.Request.IsSecureConnection) + { + return HostController.Instance.GetString("jQueryUrl", jQuery.DefaultHostedUrl).Replace("http://", "https://"); + } + else + { + return HostController.Instance.GetString("jQueryUrl", jQuery.DefaultHostedUrl); + } + } + } + + /// + /// Gets the Url for a hosted version of jQuery Migrate plugin. + /// + /// + /// Defaults to the DefaultHostedUrl constant in the jQuery class. + /// The framework will default to the latest released 1.x version hosted on Google. + /// + public static string jQueryMigrateUrl + { + get + { + if (HttpContext.Current.Request.IsSecureConnection) + { + return HostController.Instance.GetString("jQueryMigrateUrl", string.Empty).Replace("http://", "https://"); + } + else + { + return HostController.Instance.GetString("jQueryMigrateUrl", string.Empty); + } + } + } + + /// + /// Gets the Url for a hosted version of jQuery UI + /// + /// + /// Defaults to the DefaultUIHostedUrl constant in the jQuery class. + /// The framework will default to the latest released 1.x version hosted on Google. + /// + public static string jQueryUIUrl + { + get + { + if (HttpContext.Current.Request.IsSecureConnection) + { + return HostController.Instance.GetString("jQueryUIUrl", jQuery.DefaultUIHostedUrl).Replace("http://", "https://"); + } + else + { + return HostController.Instance.GetString("jQueryUIUrl", jQuery.DefaultUIHostedUrl); + } + } + } + + /// + /// Gets whether to use a hosted version of the MS Ajax Library + /// + /// + /// Defaults to False + /// + public static bool EnableMsAjaxCdn + { + get + { + return HostController.Instance.GetBoolean("EnableMsAjaxCDN", false); + } + } + + /// + /// Gets whether to use a hosted version of the Telerik Library + /// + /// + /// Defaults to False + /// + public static bool EnableTelerikCdn + { + get + { + return HostController.Instance.GetBoolean("EnableTelerikCDN", false); + } + } + + /// + /// Get Telerik CDN Basic Path. + /// + public static string TelerikCdnBasicUrl + { + get + { + return HostController.Instance.GetString("TelerikCDNBasicUrl"); + } + } + + /// + /// Get Telerik CDN Secure Path. + /// + public static string TelerikCdnSecureUrl + { + get + { + return HostController.Instance.GetString("TelerikCDNSecureUrl"); + } + } + + /// + /// Get the time, in seconds, before asynchronous postbacks time out if no response is received. + /// + public static int AsyncTimeout + { + get + { + var timeout = HostController.Instance.GetInteger("AsyncTimeout", 90); + if (timeout < 90) + { + timeout = 90; + } + + return timeout; + } + } + + #endregion + + #region Obsolete Members + + [Obsolete("Replaced in DotNetNuke 6.0 by AllowedExtensionWhitelist")] + public static string FileExtensions + { + get + { + return HostController.Instance.GetString("FileExtensions"); + } + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.GetSettingsDictionary()")] + public static Dictionary GetHostSettingsDictionary() + { + var dicSettings = DataCache.GetCache>(DataCache.UnSecureHostSettingsCacheKey); + + if (dicSettings == null) + { + dicSettings = new Dictionary(); + IDataReader dr = DataProvider.Instance().GetHostSettings(); + try + { + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + dicSettings.Add(dr.GetString(0), dr.GetString(1)); + } + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + //Save settings to cache + DNNCacheDependency objDependency = null; + DataCache.SetCache(DataCache.UnSecureHostSettingsCacheKey, + dicSettings, + objDependency, + Cache.NoAbsoluteExpiration, + TimeSpan.FromMinutes(DataCache.HostSettingsCacheTimeOut), + DataCache.HostSettingsCachePriority, + null); + } + + return dicSettings; + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.GetSecureHostSetting()")] + public static string GetSecureHostSetting(string key) + { + return HostController.Instance.GetString(key); + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.GetSecureHostSettingsDictionary()")] + public static Dictionary GetSecureHostSettingsDictionary() + { + var dicSettings = DataCache.GetCache>(DataCache.SecureHostSettingsCacheKey); + + if (dicSettings == null) + { + dicSettings = new Dictionary(); + IDataReader dr = DataProvider.Instance().GetHostSettings(); + try + { + while (dr.Read()) + { + if (!Convert.ToBoolean(dr[2])) + { + string settingName = dr.GetString(0); + if (settingName.ToLower().IndexOf("password") == -1) + { + if (!dr.IsDBNull(1)) + { + dicSettings.Add(settingName, dr.GetString(1)); + } + else + { + dicSettings.Add(settingName, ""); + } + } + } + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + //Save settings to cache + DNNCacheDependency objDependency = null; + DataCache.SetCache(DataCache.SecureHostSettingsCacheKey, + dicSettings, + objDependency, + Cache.NoAbsoluteExpiration, + TimeSpan.FromMinutes(DataCache.HostSettingsCacheTimeOut), + DataCache.HostSettingsCachePriority, + null); + } + + return dicSettings; + } + + [Obsolete("Deprecated in 5.5. This setting was never used and has been replaced in 5.5 by a Portal Setting as Content Localization is Portal based.")] + public static bool ContentLocalization + { + get + { + return HostController.Instance.GetBoolean("ContentLocalization", false); + } + } + + [Obsolete("property obsoleted in 5.4.0 - code updated to use portalcontroller method")] + public static string ContentLocale + { + get + { + return "en-us"; + } + } + + [Obsolete("MS AJax is now required for DotNetNuke 5.0 and above")] + public static bool EnableAJAX + { + get + { + return HostController.Instance.GetBoolean("EnableAJAX", true); + } + } + + [Obsolete("Deprecated in DotNetNuke 6.1")] + public static bool WhitespaceFilter + { + get + { + return false; + } + } + + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Host/HostPropertyAccess.cs b/DNN Platform/Library/Entities/Host/HostPropertyAccess.cs new file mode 100644 index 00000000000..07898929f26 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/HostPropertyAccess.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Globalization; + +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + public class HostPropertyAccess : DictionaryPropertyAccess + { + public HostPropertyAccess() : base(HostController.Instance.GetSettingsDictionary()) + { + } + + public override string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope CurrentScope, ref bool PropertyNotFound) + { + if (propertyName.ToLower() == "hosttitle" || CurrentScope == Scope.Debug) + { + return base.GetProperty(propertyName, format, formatProvider, AccessingUser, CurrentScope, ref PropertyNotFound); + } + else + { + PropertyNotFound = true; + return PropertyAccess.ContentLocked; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Host/HostSettings.cs b/DNN Platform/Library/Entities/Host/HostSettings.cs new file mode 100644 index 00000000000..9a0e78ff050 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/HostSettings.cs @@ -0,0 +1,67 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + [Obsolete("Replaced in DotNetNuke 5.0 by Host class because of Namespace clashes with Obsolete Globals.HostSetting Property")] + public class HostSettings : BaseEntityInfo + { + public static string GetHostSetting(string key) + { + string setting = Null.NullString; + HostController.Instance.GetSettingsDictionary().TryGetValue(key, out setting); + return setting; + } + + [Obsolete("Replaced in DNN 5.0 by Host.GetHostSettingsDictionary")] + public static Hashtable GetHostSettings() + { + var h = new Hashtable(); + foreach (var kvp in Host.GetHostSettingsDictionary()) + { + h.Add(kvp.Key, kvp.Value); + } + + return h; + } + + [Obsolete("Replaced in DNN 5.0 by Host.GetSecureHostSettingsDictionary")] + public static Hashtable GetSecureHostSettings() + { + var h = new Hashtable(); + foreach (var kvp in Host.GetSecureHostSettingsDictionary()) + { + h.Add(kvp.Key, kvp.Value); + } + + return h; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Host/HostSettingsController.cs b/DNN Platform/Library/Entities/Host/HostSettingsController.cs new file mode 100644 index 00000000000..4761abfb4b5 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/HostSettingsController.cs @@ -0,0 +1,66 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + [Obsolete("Replaced in DotNetNuke 5.5 by HostController")] + public class HostSettingsController + { + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.GetHostSetting()")] + public IDataReader GetHostSetting(string SettingName) + { + return DataProvider.Instance().GetHostSetting(SettingName); + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.GetHostSetting()")] + public IDataReader GetHostSettings() + { + return DataProvider.Instance().GetHostSettings(); + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.UpdateHostSetting()")] + public void UpdateHostSetting(string SettingName, string SettingValue) + { + UpdateHostSetting(SettingName, SettingValue, false, true); + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.UpdateHostSetting()")] + public void UpdateHostSetting(string SettingName, string SettingValue, bool SettingIsSecure) + { + UpdateHostSetting(SettingName, SettingValue, SettingIsSecure, true); + } + + [Obsolete("Replaced in DotNetNuke 5.5 by HostController.UpdateHostSetting()")] + public void UpdateHostSetting(string SettingName, string SettingValue, bool SettingIsSecure, bool clearCache) + { + HostController.Instance.Update(new ConfigurationSetting {Key = SettingName, Value = SettingValue, IsSecure = SettingIsSecure}); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Host/ServerController.cs b/DNN Platform/Library/Entities/Host/ServerController.cs new file mode 100644 index 00000000000..ca877eb7363 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/ServerController.cs @@ -0,0 +1,125 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + public class ServerController + { + private const string cacheKey = "WebServers"; + private const int cacheTimeout = 20; + private const CacheItemPriority cachePriority = CacheItemPriority.High; + private static readonly DataProvider dataProvider = DataProvider.Instance(); + + public static bool UseAppName + { + get + { + var uniqueServers = new Dictionary(); + foreach (ServerInfo server in GetEnabledServers()) + { + uniqueServers[server.ServerName] = server.IISAppName; + } + return uniqueServers.Count < GetEnabledServers().Count; + } + } + + private static object GetServersCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillCollection(dataProvider.GetServers()); + } + + public static void ClearCachedServers() + { + DataCache.RemoveCache(cacheKey); + } + + public static void DeleteServer(int serverID) + { + DataProvider.Instance().DeleteServer(serverID); + ClearCachedServers(); + } + + public static List GetEnabledServers() + { + var servers = new List(); + var storedServers = GetServers(); + if (storedServers != null) + { + foreach (ServerInfo server in storedServers) + { + if (server.Enabled) + { + servers.Add(server); + } + } + } + return servers; + } + + public static string GetExecutingServerName() + { + string executingServerName = Globals.ServerName; + if (UseAppName) + { + executingServerName += "-" + Globals.IISAppName; + } + return executingServerName; + } + + public static string GetServerName(ServerInfo webServer) + { + string serverName = webServer.ServerName; + if (UseAppName) + { + serverName += "-" + webServer.IISAppName; + } + return serverName; + } + + public static List GetServers() + { + var servers = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, cacheTimeout, cachePriority), GetServersCallBack); + return servers; + } + + public static void UpdateServer(ServerInfo server) + { + DataProvider.Instance().UpdateServer(server.ServerID, server.Url, server.Enabled); + ClearCachedServers(); + } + + public static void UpdateServerActivity(ServerInfo server) + { + DataProvider.Instance().UpdateServerActivity(server.ServerName, server.IISAppName, server.CreatedDate, server.LastActivityDate); + ClearCachedServers(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Host/ServerInfo.cs b/DNN Platform/Library/Entities/Host/ServerInfo.cs new file mode 100644 index 00000000000..d71ded7d044 --- /dev/null +++ b/DNN Platform/Library/Entities/Host/ServerInfo.cs @@ -0,0 +1,108 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + [Serializable] + public class ServerInfo : IHydratable + { + public ServerInfo() : this(DateTime.Now, DateTime.Now) + { + } + + public ServerInfo(DateTime created, DateTime lastactivity) + { + IISAppName = Globals.IISAppName; + ServerName = Globals.ServerName; + CreatedDate = created; + LastActivityDate = lastactivity; + } + + public int ServerID { get; set; } + + public string IISAppName { get; set; } + + public string ServerName { get; set; } + + public string Url { get; set; } + + public bool Enabled { get; set; } + + public DateTime CreatedDate { get; set; } + + public DateTime LastActivityDate { get; set; } + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ServerInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 03/25/2009 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + ServerID = Null.SetNullInteger(dr["ServerID"]); + IISAppName = Null.SetNullString(dr["IISAppName"]); + ServerName = Null.SetNullString(dr["ServerName"]); + Url = Null.SetNullString(dr["URL"]); + Enabled = Null.SetNullBoolean(dr["Enabled"]); + CreatedDate = Null.SetNullDateTime(dr["CreatedDate"]); + LastActivityDate = Null.SetNullDateTime(dr["LastActivityDate"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 03/25/2009 Created + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return ServerID; + } + set + { + ServerID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/IPFilter/IIPFilterController.cs b/DNN Platform/Library/Entities/IPFilter/IIPFilterController.cs new file mode 100644 index 00000000000..8889deea82f --- /dev/null +++ b/DNN Platform/Library/Entities/IPFilter/IIPFilterController.cs @@ -0,0 +1,54 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Host +{ + /// + /// Do not implement. This interface is meant for reference and unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IIPFilterController + { + int AddIPFilter(IPFilterInfo ipFilter); + + void UpdateIPFilter(IPFilterInfo ipFilter); + + void DeleteIPFilter(IPFilterInfo ipFilter); + + IPFilterInfo GetIPFilter(int ipFilter); + + IList GetIPFilters(); + + [Obsolete("deprecated with 7.1.0 - please use IsIPBanned instead")] + void IsIPAddressBanned(string ipAddress); + + bool IsIPBanned(string ipAddress); + + bool IsAllowableDeny(string ipAddress, IPFilterInfo ipFilter); + + bool CanIPStillAccess(string myip, IList filterList); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/IPFilter/IPFilterController.cs b/DNN Platform/Library/Entities/IPFilter/IPFilterController.cs new file mode 100644 index 00000000000..e193c39df92 --- /dev/null +++ b/DNN Platform/Library/Entities/IPFilter/IPFilterController.cs @@ -0,0 +1,216 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Common.Utils; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + public class IPFilterController : ComponentBase, IIPFilterController + { + #region Private + + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (IPFilterController)); + + private enum FilterType + { + Allow=1, + Deny=2 + } + #endregion + + #region Constructor + + internal IPFilterController() + { + } + + #endregion + + #region IIPFilterController Members + + public int AddIPFilter(IPFilterInfo ipFilter) + { + Requires.NotNull("ipFilter", ipFilter); + int id = DataProvider.Instance().AddIPFilter(ipFilter.IPAddress, ipFilter.SubnetMask, ipFilter.RuleType, UserController.GetCurrentUserInfo().UserID); + return id; + } + + public void UpdateIPFilter(IPFilterInfo ipFilter) + { + Requires.NotNull("ipFilter", ipFilter); + DataProvider.Instance().UpdateIPFilter(ipFilter.IPFilterID, ipFilter.IPAddress, ipFilter.SubnetMask, ipFilter.RuleType, UserController.GetCurrentUserInfo().UserID); + } + + public void DeleteIPFilter(IPFilterInfo ipFilter) + { + Requires.PropertyNotNegative("ipFilter", "ipFilter.IPFilterID", ipFilter.IPFilterID); + DataProvider.Instance().DeleteIPFilter(ipFilter.IPFilterID); + } + + public IPFilterInfo GetIPFilter(int ipFilter) + { + return CBO.FillObject(DataProvider.Instance().GetIPFilter(ipFilter)); + } + + IList IIPFilterController.GetIPFilters() + { + return CBO.FillCollection(DataProvider.Instance().GetIPFilters()); + } + + [Obsolete("deprecated with 7.1.0 - please use IsIPBanned instead to return the value and apply your own logic")] + public void IsIPAddressBanned(string ipAddress) + { + if (CheckIfBannedIPAddress(ipAddress)) + {//should throw 403.6 + throw new HttpException(403, ""); + } + } + + public bool IsIPBanned(string ipAddress) + { + + return CheckIfBannedIPAddress(ipAddress); + } + + private bool CheckIfBannedIPAddress(string ipAddress) + { + IList filterList = IPFilterController.Instance.GetIPFilters(); + + foreach (var ipFilterInfo in filterList) + { + if (ipFilterInfo.RuleType == 2) + { + if (NetworkUtils.IsIPInRange(ipAddress, ipFilterInfo.IPAddress, ipFilterInfo.SubnetMask)) + { + //log + LogBannedIPAttempt(ipAddress); + return true; + + } + } + } + return false; + } + + + + private void LogBannedIPAttempt(string ipAddress) + { + var controller = new LogController(); + var log = new LogInfo + { + LogTypeKey = EventLogController.EventLogType.IP_LOGIN_BANNED.ToString() + }; + log.LogProperties.Add(new LogDetailInfo("HostAddress", ipAddress)); + controller.AddLog(log); + } + + public bool CanIPStillAccess(string myip,IList filterList) + { + var allowAllIPs = false; + var globalAllow = (from p in filterList + where p.IPAddress == "*" + select p).ToList(); + + if (globalAllow.Count > 0) + { + allowAllIPs = true; + } + + var allowRules = (from p in filterList + where p.RuleType == (int)FilterType.Allow + select p).ToList(); + + var denyRules = (from p in filterList + where p.RuleType == (int)FilterType.Deny + select p).ToList(); + //if global allow and no deny + if (allowAllIPs & denyRules.Count==0) + { + return true; + } + + //if global allow, check if a deny rule would override + if (allowAllIPs & denyRules.Count>0) + { + if (denyRules.Any(ipf => NetworkUtils.IsIPInRange(myip, ipf.IPAddress, ipf.SubnetMask))) + { + return false; + } + } + + //if no global allow, check if a deny rule would apply + if (allowAllIPs==false & denyRules.Count > 0) + { + if (denyRules.Any(ipf => NetworkUtils.IsIPInRange(myip, ipf.IPAddress, ipf.SubnetMask))) + { + return false; + } + } + + //if no global allow, and no deny rules check if an allow rule would apply + if (allowAllIPs == false & denyRules.Count == 0) + { + if (allowRules.Any(ipf => NetworkUtils.IsIPInRange(myip, ipf.IPAddress, ipf.SubnetMask))) + { + return true; + } + } + + return false; + } + + + public bool IsAllowableDeny(string currentIP, IPFilterInfo ipFilter) + { + if (ipFilter.RuleType==(int)FilterType.Allow) + { + return true; + } + + if (NetworkUtils.IsIPInRange(currentIP, ipFilter.IPAddress, ipFilter.SubnetMask)) + { + return false; + } + return true; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/IPFilter/IPFilterInfo.cs b/DNN Platform/Library/Entities/IPFilter/IPFilterInfo.cs new file mode 100644 index 00000000000..13df4bf5674 --- /dev/null +++ b/DNN Platform/Library/Entities/IPFilter/IPFilterInfo.cs @@ -0,0 +1,128 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Entities.Host +{ + + public class IPFilterInfo : BaseEntityInfo, IHydratable + { + + #region Constructors + + /// + /// Create new IPFilterInfo instance + /// + /// + /// + public IPFilterInfo(string ipAddress, string subnetMask, int ruleType) + { + IPAddress = ipAddress; + SubnetMask = subnetMask; + RuleType = ruleType; + } + + public IPFilterInfo() + { + IPAddress = String.Empty; + SubnetMask = String.Empty; + RuleType = -1; + } + + #endregion + + #region Auto_Properties + + public int IPFilterID { get; set; } + + public string IPAddress { get; set; } + + public string SubnetMask { get; set; } + + public int RuleType { get; set; } + + #endregion + + + #region IHydratable Members + + /// + /// Fills an IPFilterInfo from a Data Reader + /// + /// The Data Reader to use + /// Standard IHydratable.Fill implementation + /// + public void Fill(IDataReader dr) + { + IPFilterID = Null.SetNullInteger(dr["IPFilterID"]); + + try + { + IPFilterID = Null.SetNullInteger(dr["IPFilterID"]); + } + catch (IndexOutOfRangeException) + { + + //else swallow the error + } + + IPAddress = Null.SetNullString(dr["IPAddress"]); + SubnetMask = Null.SetNullString(dr["SubnetMask"]); + RuleType = Null.SetNullInteger(dr["RuleType"]); + + FillInternal(dr); + } + + /// + /// Gets and sets the Key ID + /// + /// KeyId of the IHydratable.Key + /// + public int KeyID + { + get + { + return IPFilterID; + } + set + { + IPFilterID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Icons/IconController.cs b/DNN Platform/Library/Entities/Icons/IconController.cs new file mode 100644 index 00000000000..9b82a7633b8 --- /dev/null +++ b/DNN Platform/Library/Entities/Icons/IconController.cs @@ -0,0 +1,147 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web; +using System.Xml; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Icons +{ + /// + /// IconController provides all operation to icons. + /// + /// + /// Tab is equal to page in DotNetNuke. + /// Tabs will be a sitemap for a poatal, and every request at first need to check whether there is valid tab information + /// include in the url, if not it will use default tab to display information. + /// + public class IconController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (IconController)); + #region Constants + + public const string DefaultIconSize = "16X16"; + public const string DefaultLargeIconSize = "32X32"; + public const string DefaultIconStyle = "Standard"; + public const string DefaultIconLocation = "icons/sigma"; + public const string IconKeyName = "IconKey"; + public const string IconSizeName = "IconSize"; + public const string IconStyleName = "IconStyle"; + + #endregion + + + /// + /// Gets the Icon URL. + /// + /// Key to icon, e.g. edit + /// Link to the image, e.g. /Icons/Sigma/edit_16x16_standard.png + public static string IconURL(string key) + { + return IconURL(key, DefaultIconSize, DefaultIconStyle); + } + + /// + /// Gets the Icon URL. + /// + /// Key to icon, e.g. edit + /// Size of icon, e.g.16x16 (default) or 32x32 + /// Link to the image, e.g. /Icons/Sigma/edit_16x16_standard.png + public static string IconURL(string key, string size) + { + return IconURL(key, size, DefaultIconStyle); + } + + /// + /// Gets the Icon URL. + /// + /// Key to icon, e.g. edit + /// Size of icon, e.g.16x16 (default) or 32x32 + /// Style of icon, e.g. Standard (default) + /// Link to the image, e.g. /Icons/Sigma/edit_16x16_standard.png + public static string IconURL(string key, string size, string style) + { + if (string.IsNullOrEmpty(key)) + return string.Empty; + + if (string.IsNullOrEmpty(size)) + size = DefaultIconSize; + + if (string.IsNullOrEmpty(style)) + style = DefaultIconStyle; + + string fileName = string.Format("{0}/{1}_{2}_{3}.png", DefaultIconLocation, key, size, style); + + //In debug mode, we want to warn (onluy once) if icon is not present on disk +#if DEBUG + CheckIconOnDisk(fileName); +#endif + return Globals.ApplicationPath + "/" + fileName; + } + + private static readonly SharedDictionary _iconsStatusOnDisk = new SharedDictionary(); + private static void CheckIconOnDisk(string path) + { + using (_iconsStatusOnDisk.GetReadLock()) + { + if (_iconsStatusOnDisk.ContainsKey(path)) + return; + } + + using (_iconsStatusOnDisk.GetWriteLock()) + { + if (!_iconsStatusOnDisk.ContainsKey(path)) + { + _iconsStatusOnDisk.Add(path, true); + string iconPhysicalPath = Path.Combine(Globals.ApplicationMapPath, path.Replace('/', '\\')); + if (!File.Exists(iconPhysicalPath)) + Logger.WarnFormat(string.Format("Icon Not Present on Disk {0}", iconPhysicalPath)); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Actions/ActionEventArgs.cs b/DNN Platform/Library/Entities/Modules/Actions/ActionEventArgs.cs new file mode 100644 index 00000000000..8a67966aa6a --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ActionEventArgs.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Modules.Actions +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace : DotNetNuke.Entities.Modules.Actions + /// Class : ActionEventArgs + ///----------------------------------------------------------------------------- + /// + /// ActionEventArgs provides a custom EventARgs class for Action Events + /// + /// + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public class ActionEventArgs : EventArgs + { + private readonly ModuleAction _action; + private readonly ModuleInfo _moduleConfiguration; + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public ActionEventArgs(ModuleAction Action, ModuleInfo ModuleConfiguration) + { + _action = Action; + _moduleConfiguration = ModuleConfiguration; + } + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleAction Action + { + get + { + return _action; + } + } + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleInfo ModuleConfiguration + { + get + { + return _moduleConfiguration; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/Actions/ActionEventHandler.cs b/DNN Platform/Library/Entities/Modules/Actions/ActionEventHandler.cs new file mode 100644 index 00000000000..974557ff862 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ActionEventHandler.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Actions +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules.Actions + /// Class: ActionEventHandler + /// ----------------------------------------------------------------------------- + /// + /// The ActionEventHandler delegate defines a custom event handler for an Action + /// Event. + /// + /// + /// [cnurse] 01/12/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public delegate void ActionEventHandler(object sender, ActionEventArgs e); +} diff --git a/DNN Platform/Library/Entities/Modules/Actions/ModuleAction.cs b/DNN Platform/Library/Entities/Modules/Actions/ModuleAction.cs new file mode 100644 index 00000000000..11a4a5022c2 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ModuleAction.cs @@ -0,0 +1,371 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Entities.Modules.Actions +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : ModuleAction + ///----------------------------------------------------------------------------- + /// + /// Each Module Action represents a separate functional action as defined by the + /// associated module. + /// + /// A module action is used to define a specific function for a given module. + /// Each module can define one or more actions which the portal will present to the + /// user. These actions may be presented as a menu, a dropdown list or even a group + /// of linkbuttons. + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public class ModuleAction + { + public ModuleAction(int id) : this(id, "", "", "", "", "", "", false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName) : this(id, title, cmdName, "", "", "", "", false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg) : this(id, title, cmdName, cmdArg, "", "", "", false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon) : this(id, title, cmdName, cmdArg, icon, "", "", false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url) + : this(id, title, cmdName, cmdArg, icon, url, "", false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url, string clientScript) + : this(id, title, cmdName, cmdArg, icon, url, clientScript, false, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url, string clientScript, bool useActionEvent) + : this(id, title, cmdName, cmdArg, icon, url, clientScript, useActionEvent, SecurityAccessLevel.Anonymous, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url, string clientScript, bool useActionEvent, SecurityAccessLevel secure) + : this(id, title, cmdName, cmdArg, icon, url, clientScript, useActionEvent, secure, true, false) + { + } + + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url, string clientScript, bool useActionEvent, SecurityAccessLevel secure, bool visible) + : this(id, title, cmdName, cmdArg, icon, url, clientScript, useActionEvent, secure, visible, false) + { + } + + ///----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the class + /// using the specified parameters + /// + /// This is the identifier to use for this action. + /// This is the title that will be displayed for this action + /// The command name passed to the client when this action is + /// clicked. + /// The command argument passed to the client when this action is + /// clicked. + /// The URL of the Icon to place next to this action + /// The destination URL to redirect the client browser when this action is clicked. + /// + /// Determines whether client will receive an event notification + /// The security access level required for access to this action + /// Whether this action will be displayed + /// + /// The moduleaction constructor is used to set the various properties of + /// the class at the time the instance is created. + /// + /// + /// [Joe] 10/26/2003 Created + /// [Nik Kalyani] 10/15/2004 Created multiple signatures to eliminate Optional parameters + /// + ///----------------------------------------------------------------------------- + public ModuleAction(int id, string title, string cmdName, string cmdArg, string icon, string url, string clientScript, bool useActionEvent, SecurityAccessLevel secure, bool visible, + bool newWindow) + { + ID = id; + Title = title; + CommandName = cmdName; + CommandArgument = cmdArg; + Icon = icon; + Url = url; + ClientScript = clientScript; + UseActionEvent = useActionEvent; + Secure = secure; + Visible = visible; + NewWindow = newWindow; + Actions = new ModuleActionCollection(); + } + + ///----------------------------------------------------------------------------- + /// + /// The Actions property allows the user to create a hierarchy of actions, with + /// each action having sub-actions. + /// + /// Returns a collection of ModuleActions. + /// Each action may contain one or more child actions. When displayed via + /// the control, these subactions are + /// shown as sub-menus. If other Action controls are implemented, then + /// sub-actions may or may not be supported for that control type. + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleActionCollection Actions { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// A Module Action ID is a identifier that can be used in a Module Action Collection + /// to find a specific Action. + /// + /// The integer ID of the current . + /// When building a hierarchy of ModuleActions, + /// the ID is used to link the child and parent actions. + /// + /// [Joe] 10/18/2003 Created + /// + ///----------------------------------------------------------------------------- + public int ID { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets whether the current action should be displayed. + /// + /// A boolean value that determines if the current action should be displayed + /// If Visible is false, then the action is always hidden. If Visible + /// is true then the action may be visible depending on the security access rights + /// specified by the property. By + /// utilizing a custom method in your module, you can encapsulate specific business + /// rules to determine if the Action should be visible. + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public bool Visible { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets the value indicating the that is required + /// to access this . + /// + /// The value indicating the that is required + /// to access this + /// The security access level determines the roles required by the current user in + /// order to access this module action. + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public SecurityAccessLevel Secure { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// A Module Action CommandName represents a string used by the ModuleTitle to notify + /// the parent module that a given Module Action was selected in the Module Menu. + /// + /// The name of the command to perform. + /// + /// Use the CommandName property to determine the command to perform. The CommandName + /// property can contain any string set by the programmer. The programmer can then + /// identify the command name in code and perform the appropriate tasks. + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public string CommandName { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// A Module Action CommandArgument provides additional information and + /// complements the CommandName. + /// + /// A string that contains the argument for the command. + /// + /// The CommandArgument can contain any string set by the programmer. The + /// CommandArgument property complements the + /// property by allowing you to provide any additional information for the command. + /// For example, you can set the CommandName property to "Sort" and set the + /// CommandArgument property to "Ascending" to specify a command to sort in ascending + /// order. + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public string CommandArgument { get; set; } + + internal string ControlKey + { + get + { + string controlKey = String.Empty; + if (!String.IsNullOrEmpty(Url)) + { + int startIndex = Url.IndexOf("/ctl/"); + int endIndex = -1; + if (startIndex > -1) + { + startIndex += 4; + endIndex = Url.IndexOf("/", startIndex + 1); + } + else + { + startIndex = Url.IndexOf("ctl="); + if (startIndex > -1) + { + startIndex += 4; + endIndex = Url.IndexOf("&", startIndex + 1); + } + } + if (startIndex > -1) + { + controlKey = endIndex > -1 ? Url.Substring(startIndex + 1, endIndex - startIndex - 1) : Url.Substring(startIndex + 1); + } + } + return controlKey; + } + } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets the string that is displayed in the Module Menu + /// that represents a given menu action. + /// + /// The string value that is displayed to represent the module action. + /// The title property is displayed by the Actions control for each module + /// action. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public string Title { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets the URL for the icon file that is displayed for the given + /// . + /// + /// The URL for the icon that is displayed with the module action. + /// The URL for the icon is a simple string and is not checked for formatting. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public string Icon { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets the URL to which the user is redirected when the + /// associated Module Menu Action is selected. + /// + /// The URL to which the user is redirected when the + /// associated Module Menu Action is selected. + /// If the URL is present then the Module Action Event is not fired. + /// If the URL is empty then the Action Event is fired and is passed the value + /// of the associated Command property. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public string Url { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets javascript which will be run in the clients browser + /// when the associated Module menu Action is selected. prior to a postback. + /// + /// The Javascript which will be run during the menuClick event + /// If the ClientScript property is present then it is called prior + /// to the postback occuring. If the ClientScript returns false then the postback + /// is canceled. If the ClientScript is empty then the Action Event is fired and + /// is passed the value of the associated Command property. + /// + /// [jbrinkman] 5/21/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string ClientScript { get; set; } + + /// + /// Gets or sets a value that determines if a local ActionEvent is fired when the + /// contains a URL. + /// + /// A boolean indicating whether to fire the ActionEvent. + /// When a MenuAction is clicked, an event is fired within the Actions + /// control. If the UseActionEvent is true then the Actions control will forward + /// the event to the parent skin which will then attempt to raise the event to + /// the appropriate module. If the UseActionEvent is false, and the URL property + /// is set, then the Actions control will redirect the response to the URL. In + /// all cases, an ActionEvent is raised if the URL is not set. + /// + /// [jbrinkman] 12/22/2003 Created + /// + ///----------------------------------------------------------------------------- + public bool UseActionEvent { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets a value that determines if a new window is opened when the + /// DoAction() method is called. + /// + /// A boolean indicating whether to open a new window. + /// + /// + /// [jbrinkman] 12/22/2003 Created + /// + ///----------------------------------------------------------------------------- + public bool NewWindow { get; set; } + + ///----------------------------------------------------------------------------- + /// + /// Determines whether the action node contains any child actions. + /// + /// True if child actions exist, false if child actions do not exist. + /// Each action may contain one or more child actions in the + /// property. When displayed via + /// the control, these subactions are + /// shown as sub-menus. + /// + /// [Joe] 10/26/2003 Created + /// + ///----------------------------------------------------------------------------- + public bool HasChildren() + { + return (Actions.Count > 0); + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/Actions/ModuleActionCollection.cs b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionCollection.cs new file mode 100644 index 00000000000..09a811b5fae --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionCollection.cs @@ -0,0 +1,427 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Entities.Modules.Actions +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : ModuleActionCollection + ///----------------------------------------------------------------------------- + /// + /// Represents a collection of objects. + /// + /// The ModuleActionCollection is a custom collection of ModuleActions. + /// Each ModuleAction in the collection has it's own + /// collection which provides the ability to create a hierarchy of ModuleActions. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public class ModuleActionCollection : CollectionBase + { + ///----------------------------------------------------------------------------- + /// + /// Initializes a new, empty instance of the class. + /// + /// The default constructor creates an empty collection of + /// objects. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleActionCollection() + { + } + + ///----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the + /// class containing the elements of the specified source collection. + /// + /// A with which to initialize the collection. + /// This overloaded constructor copies the s + /// from the indicated collection. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleActionCollection(ModuleActionCollection value) + { + AddRange(value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the + /// class containing the specified array of objects. + /// + /// An array of objects + /// with which to initialize the collection. + /// This overloaded constructor copies the s + /// from the indicated array. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleActionCollection(ModuleAction[] value) + { + AddRange(value); + } + + ///----------------------------------------------------------------------------- + /// + /// Gets or sets the at the + /// specified index in the collection. + /// + /// In VB.Net, this property is the indexer for the class. + /// + /// + /// The index of the collection to access. + /// A at each valid index. + /// This method is an indexer that can be used to access the collection. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleAction this[int index] + { + get + { + return (ModuleAction) List[index]; + } + set + { + List[index] = value; + } + } + + ///----------------------------------------------------------------------------- + /// + /// Add an element of the specified to the end of the collection. + /// + /// An object of type to add to the collection. + /// The index of the newly added + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public int Add(ModuleAction value) + { + return List.Add(value); + } + + ///----------------------------------------------------------------------------- + /// + /// Add an element of the specified to the end of the collection. + /// + /// This is the identifier to use for this action. + /// This is the title that will be displayed for this action + /// The command name passed to the client when this action is + /// clicked. + /// The index of the newly added + /// This method creates a new with the specified + /// values, adds it to the collection and returns the index of the newly created ModuleAction. + ///----------------------------------------------------------------------------- + public ModuleAction Add(int ID, string Title, string CmdName) + { + return Add(ID, Title, CmdName, string.Empty, string.Empty, string.Empty, false, SecurityAccessLevel.Anonymous, true, false); + } + + ///----------------------------------------------------------------------------- + /// + /// Add an element of the specified to the end of the collection. + /// + /// This is the identifier to use for this action. + /// This is the title that will be displayed for this action + /// The command name passed to the client when this action is + /// clicked. + /// The command argument passed to the client when this action is + /// clicked. + /// The URL of the Icon to place next to this action + /// The destination URL to redirect the client browser when this + /// action is clicked. + /// Determines whether client will receive an event + /// notification + /// The security access level required for access to this action + /// Whether this action will be displayed + /// Whether open in new window. + /// The index of the newly added + /// This method creates a new with the specified + /// values, adds it to the collection and returns the index of the newly created ModuleAction. + /// + /// [Joe] 10/18/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleAction Add(int ID, string Title, string CmdName, string CmdArg, string Icon, string Url, bool UseActionEvent, SecurityAccessLevel Secure, bool Visible, bool NewWindow) + { + return Add(ID, Title, CmdName, CmdArg, Icon, Url, "", UseActionEvent, Secure, Visible, NewWindow); + } + + /// ----------------------------------------------------------------------------- + /// + /// Add an element of the specified to the end of the collection. + /// + /// This is the identifier to use for this action. + /// This is the title that will be displayed for this action + /// The command name passed to the client when this action is + /// clicked. + /// The command argument passed to the client when this action is + /// clicked. + /// The URL of the Icon to place next to this action + /// The destination URL to redirect the client browser when this + /// action is clicked. + /// Client side script to be run when the this action is + /// clicked. + /// Determines whether client will receive an event + /// notification + /// The security access level required for access to this action + /// Whether this action will be displayed + /// Whether open in new window. + /// The index of the newly added + /// This method creates a new with the specified + /// values, adds it to the collection and returns the index of the newly created ModuleAction. + /// /// + /// [jbrinkman] 5/22/2004 Created + /// + /// ----------------------------------------------------------------------------- + public ModuleAction Add(int ID, string Title, string CmdName, string CmdArg, string Icon, string Url, string ClientScript, bool UseActionEvent, SecurityAccessLevel Secure, bool Visible, + bool NewWindow) + { + var ModAction = new ModuleAction(ID, Title, CmdName, CmdArg, Icon, Url, ClientScript, UseActionEvent, Secure, Visible, NewWindow); + Add(ModAction); + return ModAction; + } + + ///----------------------------------------------------------------------------- + /// + /// Copies the elements of the specified + /// array to the end of the collection. + /// + /// An array of type + /// containing the objects to add to the collection. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public void AddRange(ModuleAction[] value) + { + int i; + for (i = 0; i <= value.Length - 1; i++) + { + Add(value[i]); + } + } + + ///----------------------------------------------------------------------------- + /// + /// Adds the contents of another + /// to the end of the collection. + /// + /// A containing + /// the objects to add to the collection. + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public void AddRange(ModuleActionCollection value) + { + foreach (ModuleAction mA in value) + { + Add(mA); + } + } + + ///----------------------------------------------------------------------------- + /// + /// Gets a value indicating whether the collection contains the specified . + /// + /// The to search for in the collection. + /// true if the collection contains the specified object; otherwise, false. + /// + /// + /// ' Tests for the presence of a ModuleAction in the + /// ' collection, and retrieves its index if it is found. + /// Dim testModuleAction = New ModuleAction(5, "Edit Action", "Edit") + /// Dim itemIndex As Integer = -1 + /// If collection.Contains(testModuleAction) Then + /// itemIndex = collection.IndexOf(testModuleAction) + /// End If + /// + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public bool Contains(ModuleAction value) + { + //If value is not of type ModuleAction, this will return false. + return List.Contains(value); + } + + public ModuleAction GetActionByCommandName(string name) + { + ModuleAction retAction = null; + + //Check each action in the List + foreach (ModuleAction modAction in List) + { + if (modAction.CommandName == name) + { + retAction = modAction; + break; + } + //If action has children check them + if (modAction.HasChildren()) + { + ModuleAction childAction = modAction.Actions.GetActionByCommandName(name); + if (childAction != null) + { + retAction = childAction; + break; + } + } + } + return retAction; + } + + public ModuleActionCollection GetActionsByCommandName(string name) + { + var retActions = new ModuleActionCollection(); + + //Check each action in the List + foreach (ModuleAction modAction in List) + { + if (modAction.CommandName == name) + { + retActions.Add(modAction); + } + //If action has children check them + if (modAction.HasChildren()) + { + retActions.AddRange(modAction.Actions.GetActionsByCommandName(name)); + } + } + return retActions; + } + + public ModuleAction GetActionByID(int id) + { + ModuleAction retAction = null; + + //Check each action in the List + foreach (ModuleAction modAction in List) + { + if (modAction.ID == id) + { + retAction = modAction; + break; + } + //If action has children check them + if (modAction.HasChildren()) + { + ModuleAction childAction = modAction.Actions.GetActionByID(id); + if (childAction != null) + { + retAction = childAction; + break; + } + } + } + return retAction; + } + + ///----------------------------------------------------------------------------- + /// + /// Gets the index in the collection of the specified , + /// if it exists in the collection. + /// + /// The to locate in the collection. + /// The index in the collection of the specified object, if found; otherwise, -1. + /// This example tests for the presense of a ModuleAction in the + /// collection, and retrieves its index if it is found. + /// + /// Dim testModuleAction = New ModuleAction(5, "Edit Action", "Edit") + /// Dim itemIndex As Integer = -1 + /// If collection.Contains(testModuleAction) Then + /// itemIndex = collection.IndexOf(testModuleAction) + /// End If + /// + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public int IndexOf(ModuleAction value) + { + return List.IndexOf(value); + } + + ///----------------------------------------------------------------------------- + /// + /// Add an element of the specified to the + /// collection at the designated index. + /// + /// An Integer to indicate the location to add the object to the collection. + /// An object of type to add to the collection. + /// + /// + /// ' Inserts a ModuleAction at index 0 of the collection. + /// collection.Insert(0, New ModuleAction(5, "Edit Action", "Edit")) + /// + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public void Insert(int index, ModuleAction value) + { + List.Insert(index, value); + } + + ///----------------------------------------------------------------------------- + /// + /// Remove the specified object of type from the collection. + /// + /// An object of type to remove from the collection. + /// + /// + /// ' Removes the specified ModuleAction from the collection. + /// Dim testModuleAction = New ModuleAction(5, "Edit Action", "Edit") + /// collection.Remove(testModuleAction) + /// + /// + /// + /// [Joe] 10/9/2003 Created + /// + ///----------------------------------------------------------------------------- + public void Remove(ModuleAction value) + { + List.Remove(value); + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/Actions/ModuleActionEventListener.cs b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionEventListener.cs new file mode 100644 index 00000000000..94fe6a01a14 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionEventListener.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Actions +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : ModuleActionEventListener + /// + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public class ModuleActionEventListener + { + private readonly ActionEventHandler _actionEvent; + private readonly int _moduleID; + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public ModuleActionEventListener(int ModID, ActionEventHandler e) + { + _moduleID = ModID; + _actionEvent = e; + } + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public int ModuleID + { + get + { + return _moduleID; + } + } + + ///----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [jbrinkman] 12/27/2003 Created + /// + ///----------------------------------------------------------------------------- + public ActionEventHandler ActionEvent + { + get + { + return _actionEvent; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/Actions/ModuleActionType.cs b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionType.cs new file mode 100644 index 00000000000..e33ed2d8030 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Actions/ModuleActionType.cs @@ -0,0 +1,62 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Actions +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : ModuleActionType + ///----------------------------------------------------------------------------- + /// + /// Identifies common module action types + /// + /// + /// Common action types can be specified in the CommandName attribute of the + /// ModuleAction class + /// + ///----------------------------------------------------------------------------- + public class ModuleActionType + { + public const string AddContent = "AddContent.Action"; + public const string EditContent = "EditContent.Action"; + public const string ContentOptions = "ContentOptions.Action"; + public const string SyndicateModule = "SyndicateModule.Action"; + public const string ImportModule = "ImportModule.Action"; + public const string ExportModule = "ExportModule.Action"; + public const string OnlineHelp = "OnlineHelp.Action"; + public const string ModuleHelp = "ModuleHelp.Action"; + public const string HelpText = "ModuleHelp.Text"; + public const string PrintModule = "PrintModule.Action"; + public const string ModuleSettings = "ModuleSettings.Action"; + public const string DeleteModule = "DeleteModule.Action"; + public const string ClearCache = "ClearCache.Action"; + public const string MoveTop = "MoveTop.Action"; + public const string MoveUp = "MoveUp.Action"; + public const string MoveDown = "MoveDown.Action"; + public const string MoveBottom = "MoveBottom.Action"; + public const string MovePane = "MovePane.Action"; + public const string MoveRoot = "MoveRoot.Action"; + public const string ViewSource = "ViewSource.Action"; + public const string LocalizeModule = "Localize.Action"; + public const string DeLocalizeModule = "DeLocalize.Action"; + public const string TranslateModule = "Translate.Action"; + public const string UnTranslateModule = "UnTranslate.Action"; + } +} diff --git a/DNN Platform/Library/Entities/Modules/Communications/IModuleCommunicator.cs b/DNN Platform/Library/Entities/Modules/Communications/IModuleCommunicator.cs new file mode 100644 index 00000000000..35c6cc898ee --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/IModuleCommunicator.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Communications +{ + public interface IModuleCommunicator + { + event ModuleCommunicationEventHandler ModuleCommunication; + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/IModuleListener.cs b/DNN Platform/Library/Entities/Modules/Communications/IModuleListener.cs new file mode 100644 index 00000000000..de469b45818 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/IModuleListener.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Communications +{ + public interface IModuleListener + { + void OnModuleCommunication(object s, ModuleCommunicationEventArgs e); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicate.cs b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicate.cs new file mode 100644 index 00000000000..723d1c24faf --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicate.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; + +#endregion + +namespace DotNetNuke.Entities.Modules.Communications +{ + public class ModuleCommunicate + { + private readonly ModuleCommunicators _ModuleCommunicators = new ModuleCommunicators(); + + private readonly ModuleListeners _ModuleListeners = new ModuleListeners(); + + public ModuleCommunicators ModuleCommunicators + { + get + { + return _ModuleCommunicators; + } + } + + public ModuleListeners ModuleListeners + { + get + { + return _ModuleListeners; + } + } + + + public void LoadCommunicator(Control ctrl) + { + // Check and see if the module implements IModuleCommunicator + if (ctrl is IModuleCommunicator) + { + Add((IModuleCommunicator) ctrl); + } + + // Check and see if the module implements IModuleListener + if (ctrl is IModuleListener) + { + Add((IModuleListener) ctrl); + } + } + + private int Add(IModuleCommunicator item) + { + int returnData = _ModuleCommunicators.Add(item); + + int i = 0; + for (i = 0; i <= _ModuleListeners.Count - 1; i++) + { + item.ModuleCommunication += _ModuleListeners[i].OnModuleCommunication; + } + + + return returnData; + } + + private int Add(IModuleListener item) + { + int returnData = _ModuleListeners.Add(item); + + int i = 0; + for (i = 0; i <= _ModuleCommunicators.Count - 1; i++) + { + _ModuleCommunicators[i].ModuleCommunication += item.OnModuleCommunication; + } + + return returnData; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventArgs.cs b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventArgs.cs new file mode 100644 index 00000000000..30fd9c54b68 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventArgs.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Modules.Communications +{ + public class ModuleCommunicationEventArgs : EventArgs + { + public ModuleCommunicationEventArgs() + { + } + + public ModuleCommunicationEventArgs(string text) + { + Text = text; + } + + public ModuleCommunicationEventArgs(string type, object value, string sender, string target) + { + Type = type; + Value = value; + Sender = sender; + Target = target; + } + + public string Sender { get; set; } + + public string Target { get; set; } + + public string Text { get; set; } + + public string Type { get; set; } + + public object Value { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventHandler.cs b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventHandler.cs new file mode 100644 index 00000000000..bb342c8573a --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicationEventHandler.cs @@ -0,0 +1,24 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Communications +{ + public delegate void ModuleCommunicationEventHandler(object sender, ModuleCommunicationEventArgs e); +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicators.cs b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicators.cs new file mode 100644 index 00000000000..fec370fc3cc --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/ModuleCommunicators.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Modules.Communications +{ + public class ModuleCommunicators : CollectionBase + { + public IModuleCommunicator this[int index] + { + get + { + return (IModuleCommunicator) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(IModuleCommunicator item) + { + return List.Add(item); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/ModuleListeners.cs b/DNN Platform/Library/Entities/Modules/Communications/ModuleListeners.cs new file mode 100644 index 00000000000..51f8b7ec526 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/ModuleListeners.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Modules.Communications +{ + public class ModuleListeners : CollectionBase + { + public IModuleListener this[int index] + { + get + { + return (IModuleListener) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(IModuleListener item) + { + return List.Add(item); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Communications/RoleChangeEventArgs.cs b/DNN Platform/Library/Entities/Modules/Communications/RoleChangeEventArgs.cs new file mode 100644 index 00000000000..2e727e82fca --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Communications/RoleChangeEventArgs.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules.Communications +{ + public class RoleChangeEventArgs : ModuleCommunicationEventArgs + { + public string PortalId { get; set; } + + public string RoleId { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ControlInfo.cs b/DNN Platform/Library/Entities/Modules/ControlInfo.cs new file mode 100644 index 00000000000..6870aedc058 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ControlInfo.cs @@ -0,0 +1,133 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ControlInfo + /// ----------------------------------------------------------------------------- + /// + /// ControlInfo provides a base class for Module Controls and SkinControls + /// + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public abstract class ControlInfo : BaseEntityInfo + { + protected ControlInfo() + { + SupportsPartialRendering = Null.NullBoolean; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Control Key + /// + /// A String + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public string ControlKey { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Control Source + /// + /// A String + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public string ControlSrc { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a flag that determines whether the control support the AJAX + /// Update Panel + /// + /// A Boolean + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool SupportsPartialRendering { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ControlInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + protected override void FillInternal(IDataReader dr) + { + //Call EntityBaseInfo's implementation + base.FillInternal(dr); + ControlKey = Null.SetNullString(dr["ControlKey"]); + ControlSrc = Null.SetNullString(dr["ControlSrc"]); + SupportsPartialRendering = Null.SetNullBoolean(dr["SupportsPartialRendering"]); + } + + protected void ReadXmlInternal(XmlReader reader) + { + switch (reader.Name) + { + case "controlKey": + ControlKey = reader.ReadElementContentAsString(); + break; + case "controlSrc": + ControlSrc = reader.ReadElementContentAsString(); + break; + case "supportsPartialRendering": + string elementvalue = reader.ReadElementContentAsString(); + if (!string.IsNullOrEmpty(elementvalue)) + { + SupportsPartialRendering = bool.Parse(elementvalue); + } + break; + } + } + + protected void WriteXmlInternal(XmlWriter writer) + { + //write out properties + writer.WriteElementString("controlKey", ControlKey); + writer.WriteElementString("controlSrc", ControlSrc); + writer.WriteElementString("supportsPartialRendering", SupportsPartialRendering.ToString()); + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionController.cs b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionController.cs new file mode 100644 index 00000000000..54a7c301968 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionController.cs @@ -0,0 +1,322 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Entities.Modules.Definitions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules.Definitions + /// Class : ModuleDefinitionController + /// ----------------------------------------------------------------------------- + /// + /// ModuleDefinitionController provides the Business Layer for Module Definitions + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class ModuleDefinitionController + { + private const string key = "ModuleDefID"; + private static readonly DataProvider dataProvider = DataProvider.Instance(); + + #region Private Members + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionsCallBack gets a Dictionary of Module Definitions from + /// the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static object GetModuleDefinitionsCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillDictionary(key, dataProvider.GetModuleDefinitions(), new Dictionary()); + } + + #endregion + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionByID gets a Module Definition by its ID + /// + /// The object of the Module Definition + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void DeleteModuleDefinition(ModuleDefinitionInfo objModuleDefinition) + { + DeleteModuleDefinition(objModuleDefinition.ModuleDefID); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteModuleDefinition deletes a Module Definition By ID + /// + /// The ID of the Module Definition to delete + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public void DeleteModuleDefinition(int moduleDefinitionId) + { + //Delete associated permissions + var permissionController = new PermissionController(); + foreach (PermissionInfo permission in permissionController.GetPermissionsByModuleDefID(moduleDefinitionId)) + { + permissionController.DeletePermission(permission.PermissionID); + } + dataProvider.DeleteModuleDefinition(moduleDefinitionId); + DataCache.ClearHostCache(true); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionByID gets a Module Definition by its ID + /// + /// The ID of the Module Definition + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static ModuleDefinitionInfo GetModuleDefinitionByID(int moduleDefID) + { + return (from kvp in GetModuleDefinitions() + where kvp.Value.ModuleDefID == moduleDefID + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionByFriendlyName gets a Module Definition by its Friendly + /// Name (and DesktopModuleID) + /// + /// The friendly name + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static ModuleDefinitionInfo GetModuleDefinitionByFriendlyName(string friendlyName) + { + Requires.NotNullOrEmpty("friendlyName", friendlyName); + + return (from kvp in GetModuleDefinitions() + where kvp.Value.FriendlyName == friendlyName + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionByFriendlyName gets a Module Definition by its Friendly + /// Name (and DesktopModuleID) + /// + /// The friendly name + /// The ID of the Dekstop Module + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static ModuleDefinitionInfo GetModuleDefinitionByFriendlyName(string friendlyName, int desktopModuleID) + { + Requires.NotNullOrEmpty("friendlyName", friendlyName); + Requires.NotNegative("desktopModuleID", desktopModuleID); + + return (from kvp in GetModuleDefinitions() + where kvp.Value.FriendlyName == friendlyName && kvp.Value.DesktopModuleID == desktopModuleID + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitions gets a Dictionary of Module Definitions. + /// + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetModuleDefinitions() + { + return CBO.GetCachedObject>(new CacheItemArgs(DataCache.ModuleDefinitionCacheKey, + DataCache.ModuleDefinitionCachePriority), + GetModuleDefinitionsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinitionsByDesktopModuleID gets a Dictionary of Module Definitions + /// with a particular DesktopModuleID, keyed by the FriendlyName. + /// + /// The ID of the Desktop Module + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetModuleDefinitionsByDesktopModuleID(int desktopModuleID) + { + //Iterate through cached Dictionary to get all Module Definitions with the correct DesktopModuleID + return GetModuleDefinitions().Where(kvp => kvp.Value.DesktopModuleID == desktopModuleID) + .ToDictionary(kvp => kvp.Value.FriendlyName, kvp => kvp.Value); + } + + /// + /// Get ModuleDefinition by DefinitionName + /// + /// The defintion name + /// The ID of the Dekstop Module + /// A ModuleDefinition or null if not found + public static ModuleDefinitionInfo GetModuleDefinitionByDefinitionName(string definitionName, int desktopModuleID) + { + Requires.NotNullOrEmpty("definitionName", definitionName); + Requires.NotNegative("desktopModuleID", desktopModuleID); + + return (from kvp in GetModuleDefinitions() + where kvp.Value.DefinitionName == definitionName && kvp.Value.DesktopModuleID == desktopModuleID + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveModuleDefinition saves the Module Definition to the database + /// + /// The Module Definition to save + /// A flag that determines whether the child objects are also saved + /// A flag that determines whether to clear the host cache + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SaveModuleDefinition(ModuleDefinitionInfo moduleDefinition, bool saveChildren, bool clearCache) + { + int moduleDefinitionID = moduleDefinition.ModuleDefID; + if (moduleDefinitionID == Null.NullInteger) + { + //Add new Module Definition + moduleDefinitionID = dataProvider.AddModuleDefinition(moduleDefinition.DesktopModuleID, + moduleDefinition.FriendlyName, + moduleDefinition.DefinitionName, + moduleDefinition.DefaultCacheTime, + UserController.GetCurrentUserInfo().UserID); + } + else + { + //Upgrade Module Definition + dataProvider.UpdateModuleDefinition(moduleDefinition.ModuleDefID, moduleDefinition.FriendlyName, moduleDefinition.DefinitionName, moduleDefinition.DefaultCacheTime, UserController.GetCurrentUserInfo().UserID); + } + if (saveChildren) + { + foreach (KeyValuePair kvp in moduleDefinition.Permissions) + { + kvp.Value.ModuleDefID = moduleDefinitionID; + + //check if permission exists + var permissionController = new PermissionController(); + ArrayList permissions = permissionController.GetPermissionByCodeAndKey(kvp.Value.PermissionCode, kvp.Value.PermissionKey); + if (permissions != null && permissions.Count == 1) + { + var permission = (PermissionInfo) permissions[0]; + kvp.Value.PermissionID = permission.PermissionID; + permissionController.UpdatePermission(kvp.Value); + } + else + { + permissionController.AddPermission(kvp.Value); + } + } + foreach (KeyValuePair kvp in moduleDefinition.ModuleControls) + { + kvp.Value.ModuleDefID = moduleDefinitionID; + + //check if definition exists + ModuleControlInfo moduleControl = ModuleControlController.GetModuleControlByControlKey(kvp.Value.ControlKey, kvp.Value.ModuleDefID); + if (moduleControl != null) + { + kvp.Value.ModuleControlID = moduleControl.ModuleControlID; + } + ModuleControlController.SaveModuleControl(kvp.Value, clearCache); + } + } + if (clearCache) + { + DataCache.ClearHostCache(true); + } + return moduleDefinitionID; + } + + #region Obsolete Members + + [Obsolete("Deprecated in DotNetNuke 6.0. Replaced by SaveModuleDefinition")] + public void UpdateModuleDefinition(ModuleDefinitionInfo objModuleDefinition) + { + SaveModuleDefinition(objModuleDefinition, false, true); + } + + [Obsolete("Deprecated in DotNetNuke 6.0. Replaced by SaveModuleDefinition")] + public int AddModuleDefinition(ModuleDefinitionInfo objModuleDefinition) + { + return SaveModuleDefinition(objModuleDefinition, false, true); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleDefinitionByID(Integer)")] + public ModuleDefinitionInfo GetModuleDefinition(int moduleDefID) + { + return GetModuleDefinitionByID(moduleDefID); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleDefinitionByFriendlyName(String,Integer)")] + public ModuleDefinitionInfo GetModuleDefinitionByName(int desktopModuleID, string friendlyName) + { + return GetModuleDefinitionByFriendlyName(friendlyName, desktopModuleID); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleDefinitionsByDesktopModuleID(Integer)")] + public ArrayList GetModuleDefinitions(int DesktopModuleId) + { + var arrDefinitions = new ArrayList(); + arrDefinitions.AddRange(GetModuleDefinitionsByDesktopModuleID(DesktopModuleId).Values); + return arrDefinitions; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionInfo.cs b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionInfo.cs new file mode 100644 index 00000000000..ff00ec820d8 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionInfo.cs @@ -0,0 +1,346 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Entities.Modules.Definitions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules.Definitions + /// Class : ModuleDefinitionInfo + /// ----------------------------------------------------------------------------- + /// + /// ModuleDefinitionInfo provides the Entity Layer for Module Definitions + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ModuleDefinitionInfo : IXmlSerializable, IHydratable + { + private Dictionary _ModuleControls; + private int _TempModuleID; + private string _definitionName; + + public ModuleDefinitionInfo() + { + Permissions = new Dictionary(); + DesktopModuleID = Null.NullInteger; + ModuleDefID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module Definition ID + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int ModuleDefID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Default Cache Time + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int DefaultCacheTime { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the associated Desktop Module ID + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int DesktopModuleID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Friendly Name + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string FriendlyName { get; set; } + + /// + /// Gets the DefinitionName + /// + public string DefinitionName + { + get + { + if(String.IsNullOrEmpty(_definitionName)) + { + return FriendlyName; + } + + return _definitionName; + } + + set { _definitionName = value; } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Dictionary of ModuleControls that are part of this definition + /// + /// A Dictionary(Of String, ModuleControlInfo) + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public Dictionary ModuleControls + { + get + { + if (_ModuleControls == null) + { + LoadControls(); + } + return _ModuleControls; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Dictionary of Permissions that are part of this definition + /// + /// A String + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Permissions { get; private set; } + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ModuleDefinitionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/11/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + ModuleDefID = Null.SetNullInteger(dr["ModuleDefID"]); + DesktopModuleID = Null.SetNullInteger(dr["DesktopModuleID"]); + DefaultCacheTime = Null.SetNullInteger(dr["DefaultCacheTime"]); + FriendlyName = Null.SetNullString(dr["FriendlyName"]); + if (dr.GetSchemaTable().Select("ColumnName = 'DefinitionName'").Length > 0) + { + DefinitionName = Null.SetNullString(dr["DefinitionName"]); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return ModuleDefID; + } + set + { + ModuleDefID = value; + } + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the ModuleDefinitionInfo + /// + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a ModuleDefinitionInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + if (reader.NodeType == XmlNodeType.Element && reader.Name == "moduleControls") + { + ReadModuleControls(reader); + } + else + { + switch (reader.Name) + { + case "friendlyName": + FriendlyName = reader.ReadElementContentAsString(); + break; + case "defaultCacheTime": + string elementvalue = reader.ReadElementContentAsString(); + if (!string.IsNullOrEmpty(elementvalue)) + { + DefaultCacheTime = int.Parse(elementvalue); + } + break; + case "permissions": //Ignore permissons node + reader.Skip(); + break; + case "definitionName": + DefinitionName = reader.ReadElementContentAsString(); + break; + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a ModuleDefinitionInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("moduleDefinition"); + + //write out properties + writer.WriteElementString("friendlyName", FriendlyName); + writer.WriteElementString("definitionName", DefinitionName); + writer.WriteElementString("defaultCacheTime", DefaultCacheTime.ToString()); + + //Write start of Module Controls + writer.WriteStartElement("moduleControls"); + //Iterate through controls + foreach (ModuleControlInfo control in ModuleControls.Values) + { + control.WriteXml(writer); + } + //Write end of Module Controls + writer.WriteEndElement(); + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + + public void LoadControls() + { + _ModuleControls = ModuleDefID > Null.NullInteger ? ModuleControlController.GetModuleControlsByModuleDefinitionID(ModuleDefID) : new Dictionary(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads the ModuleControls from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void ReadModuleControls(XmlReader reader) + { + reader.ReadStartElement("moduleControls"); + do + { + reader.ReadStartElement("moduleControl"); + var moduleControl = new ModuleControlInfo(); + moduleControl.ReadXml(reader); + ModuleControls.Add(moduleControl.ControlKey, moduleControl); + } while (reader.ReadToNextSibling("moduleControl")); + } + + #region Obsolete Members + + [Obsolete("No longer used in DotNetNuke 5.0 as new Installer does not need this.")] + public int TempModuleID + { + get + { + return _TempModuleID; + } + set + { + _TempModuleID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionValidator.cs b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionValidator.cs new file mode 100644 index 00000000000..4f5dc474229 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Definitions/ModuleDefinitionValidator.cs @@ -0,0 +1,135 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Entities.Modules.Definitions +{ + public enum ModuleDefinitionVersion + { + VUnknown = 0, + V1 = 1, + V2 = 2, + V2_Skin = 3, + V2_Provider = 4, + V3 = 5 + } + + public class ModuleDefinitionValidator : XmlValidatorBase + { + private string GetDnnSchemaPath(Stream xmlStream) + { + ModuleDefinitionVersion Version = GetModuleDefinitionVersion(xmlStream); + string schemaPath = ""; + switch (Version) + { + case ModuleDefinitionVersion.V2: + schemaPath = "components\\ResourceInstaller\\ModuleDef_V2.xsd"; + break; + case ModuleDefinitionVersion.V3: + schemaPath = "components\\ResourceInstaller\\ModuleDef_V3.xsd"; + break; + case ModuleDefinitionVersion.V2_Skin: + schemaPath = "components\\ResourceInstaller\\ModuleDef_V2Skin.xsd"; + break; + case ModuleDefinitionVersion.V2_Provider: + schemaPath = "components\\ResourceInstaller\\ModuleDef_V2Provider.xsd"; + break; + case ModuleDefinitionVersion.VUnknown: + throw new Exception(GetLocalizedString("EXCEPTION_LoadFailed")); + } + return Path.Combine(Globals.ApplicationMapPath, schemaPath); + } + + private static string GetLocalizedString(string key) + { + var objPortalSettings = (PortalSettings) HttpContext.Current.Items["PortalSettings"]; + if (objPortalSettings == null) + { + return key; + } + return Localization.GetString(key, objPortalSettings); + } + + public ModuleDefinitionVersion GetModuleDefinitionVersion(Stream xmlStream) + { + ModuleDefinitionVersion retValue; + xmlStream.Seek(0, SeekOrigin.Begin); + var xmlReader = new XmlTextReader(xmlStream); + xmlReader.MoveToContent(); + + //This test assumes provides a simple validation + switch (xmlReader.LocalName.ToLower()) + { + case "module": + retValue = ModuleDefinitionVersion.V1; + break; + case "dotnetnuke": + switch (xmlReader.GetAttribute("type")) + { + case "Module": + switch (xmlReader.GetAttribute("version")) + { + case "2.0": + retValue = ModuleDefinitionVersion.V2; + break; + case "3.0": + retValue = ModuleDefinitionVersion.V3; + break; + default: + return ModuleDefinitionVersion.VUnknown; + } + break; + case "SkinObject": + retValue = ModuleDefinitionVersion.V2_Skin; + break; + case "Provider": + retValue = ModuleDefinitionVersion.V2_Provider; + break; + default: + retValue = ModuleDefinitionVersion.VUnknown; + break; + } + break; + default: + retValue = ModuleDefinitionVersion.VUnknown; + break; + } + return retValue; + } + + public override bool Validate(Stream XmlStream) + { + SchemaSet.Add("", GetDnnSchemaPath(XmlStream)); + return base.Validate(XmlStream); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/DesktopModuleController.cs b/DNN Platform/Library/Entities/Modules/DesktopModuleController.cs new file mode 100644 index 00000000000..d433fee3c67 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/DesktopModuleController.cs @@ -0,0 +1,728 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.EventQueue; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : DesktopModuleController + /// ----------------------------------------------------------------------------- + /// + /// DesktopModuleController provides the Busines Layer for Desktop Modules + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class DesktopModuleController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (DesktopModuleController)); + #region Private Methods + + private static readonly DataProvider DataProvider = DataProvider.Instance(); + + private static Dictionary GetDesktopModulesInternal(int portalID) + { + string cacheKey = string.Format(DataCache.DesktopModuleCacheKey, portalID); + var args = new CacheItemArgs(cacheKey, DataCache.DesktopModuleCacheTimeOut, DataCache.DesktopModuleCachePriority, portalID); + Dictionary desktopModules = (portalID == Null.NullInteger) + ? CBO.GetCachedObject>(args, GetDesktopModulesCallBack) + : CBO.GetCachedObject>(args, GetDesktopModulesByPortalCallBack); + return desktopModules; + } + + private static object GetDesktopModulesCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillDictionary("DesktopModuleID", DataProvider.GetDesktopModules(), new Dictionary()); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModulesByPortalCallBack gets a Dictionary of Desktop Modules by + /// Portal from the the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static object GetDesktopModulesByPortalCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillDictionary("DesktopModuleID", DataProvider.GetDesktopModulesByPortal(portalId), new Dictionary()); + } + + private static object GetPortalDesktopModulesByPortalIDCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillDictionary("PortalDesktopModuleID", DataProvider.Instance().GetPortalDesktopModules(portalId, Null.NullInteger), new Dictionary()); + } + + private static void CreateContentItem(DesktopModuleInfo desktopModule) + { + IContentTypeController typeController = new ContentTypeController(); + ContentType contentType = (from t in typeController.GetContentTypes() + where t.ContentType == "DesktopModule" + select t).SingleOrDefault(); + + if (contentType == null) + { + contentType = new ContentType { ContentType = "DesktopModule" }; + contentType.ContentTypeId = typeController.AddContentType(contentType); + } + + IContentController contentController = Util.GetContentController(); + desktopModule.Content = desktopModule.FriendlyName; + desktopModule.Indexed = false; + desktopModule.ContentTypeId = contentType.ContentTypeId; + desktopModule.ContentItemId = contentController.AddContentItem(desktopModule); + } + + #endregion + + #region DesktopModule Methods + + public static void AddModuleCategory(string category) + { + var termController = Util.GetTermController(); + var term = (from Term t in termController.GetTermsByVocabulary("Module_Categories") + where t.Name == category + select t) + .FirstOrDefault(); + + if (term == null) + { + var vocabularyController = Util.GetVocabularyController(); + var vocabulary = (from v in vocabularyController.GetVocabularies() + where v.Name == "Module_Categories" + select v) + .FirstOrDefault(); + + if (vocabulary != null) + { + term = new Term(vocabulary.VocabularyId) { Name = category }; + + termController.AddTerm(term); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModule deletes a Desktop Module + /// + /// Desktop Module Info + /// + /// [cnurse] 05/14/2009 Documented + /// + /// ----------------------------------------------------------------------------- + public void DeleteDesktopModule(DesktopModuleInfo objDesktopModule) + { + DeleteDesktopModule(objDesktopModule.DesktopModuleID); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModule deletes a Desktop Module By ID + /// + /// The ID of the Desktop Module to delete + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public void DeleteDesktopModule(int desktopModuleID) + { + DataProvider.DeleteDesktopModule(desktopModuleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModuleID", + desktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.DESKTOPMODULE_DELETED); + DataCache.ClearHostCache(true); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModule deletes a Desktop Module + /// + /// The Name of the Desktop Module to delete + /// + /// [cnurse] 05/14/2009 Documented + /// + /// ----------------------------------------------------------------------------- + public static void DeleteDesktopModule(string moduleName) + { + DesktopModuleInfo desktopModule = GetDesktopModuleByModuleName(moduleName, Null.NullInteger); + if (desktopModule != null) + { + var controller = new DesktopModuleController(); + controller.DeleteDesktopModule(desktopModule.DesktopModuleID); + //Delete the Package + PackageController.DeletePackage(desktopModule.PackageID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModule gets a Desktop Module by its ID + /// + /// This method uses the cached Dictionary of DesktopModules. It first checks + /// if the DesktopModule is in the cache. If it is not in the cache it then makes a call + /// to the Dataprovider. + /// The ID of the Desktop Module to get + /// The ID of the portal + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static DesktopModuleInfo GetDesktopModule(int desktopModuleID, int portalID) + { + var module = (from kvp in GetDesktopModulesInternal(portalID) + where kvp.Value.DesktopModuleID == desktopModuleID + select kvp.Value) + .FirstOrDefault(); + + if (module == null) + { + module = (from kvp in GetDesktopModulesInternal(Null.NullInteger) + where kvp.Value.DesktopModuleID == desktopModuleID + select kvp.Value) + .FirstOrDefault(); + } + + if (module == null) + Logger.WarnFormat("Unable to find module by module ID. ID:{0} PortalID:{1}", desktopModuleID, portalID); + + return module; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModuleByPackageID gets a Desktop Module by its Package ID + /// + /// The ID of the Package + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static DesktopModuleInfo GetDesktopModuleByPackageID(int packageID) + { + DesktopModuleInfo desktopModuleByPackageID = (from kvp in GetDesktopModulesInternal(Null.NullInteger) + where kvp.Value.PackageID == packageID + select kvp.Value) + .FirstOrDefault(); + + if (desktopModuleByPackageID == null) + Logger.WarnFormat("Unable to find module by package ID. ID:{0}", packageID); + + return desktopModuleByPackageID; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModuleByModuleName gets a Desktop Module by its Name + /// + /// This method uses the cached Dictionary of DesktopModules. It first checks + /// if the DesktopModule is in the cache. If it is not in the cache it then makes a call + /// to the Dataprovider. + /// The name of the Desktop Module to get + /// The ID of the portal + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static DesktopModuleInfo GetDesktopModuleByModuleName(string moduleName, int portalID) + { + DesktopModuleInfo desktopModuleByModuleName = (from kvp in GetDesktopModulesInternal(portalID) + where kvp.Value.ModuleName == moduleName + select kvp.Value).FirstOrDefault(); + + if (desktopModuleByModuleName == null) + Logger.WarnFormat("Unable to find module by name. Name:{0} portalId:{1}", moduleName, portalID); + + return desktopModuleByModuleName; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModules gets a Dictionary of Desktop Modules + /// + /// The ID of the Portal (Use PortalID = Null.NullInteger (-1) to get + /// all the DesktopModules including Modules not allowed for the current portal + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetDesktopModules(int portalID) + { + return new Dictionary(GetDesktopModulesInternal(portalID)); + } + + public static DesktopModuleInfo GetDesktopModuleByFriendlyName(string friendlyName) + { + var module = (from kvp in GetDesktopModulesInternal(Null.NullInteger) where kvp.Value.FriendlyName == friendlyName select kvp.Value).FirstOrDefault(); + + if (module== null) + Logger.WarnFormat("Unable to find module by friendly name. Name:{0}", friendlyName); + + return module; + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveDesktopModule saves the Desktop Module to the database + /// + /// The Desktop Module to save + /// A flag that determines whether the child objects are also saved + /// A flag that determines whether to clear the host cache + /// + /// [cnurse] 01/13/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SaveDesktopModule(DesktopModuleInfo desktopModule, bool saveChildren, bool clearCache) + { + return SaveDesktopModule(desktopModule, saveChildren, clearCache, true); + } + + internal static int SaveDesktopModule(DesktopModuleInfo desktopModule, bool saveChildren, bool clearCache, bool saveTerms) + { + var desktopModuleID = desktopModule.DesktopModuleID; + var eventLogController = new EventLogController(); + if (desktopModuleID == Null.NullInteger) + { + CreateContentItem(desktopModule); + desktopModuleID = DataProvider.AddDesktopModule(desktopModule.PackageID, + desktopModule.ModuleName, + desktopModule.FolderName, + desktopModule.FriendlyName, + desktopModule.Description, + desktopModule.Version, + desktopModule.IsPremium, + desktopModule.IsAdmin, + desktopModule.BusinessControllerClass, + desktopModule.SupportedFeatures, + (int)desktopModule.Shareable, + desktopModule.CompatibleVersions, + desktopModule.Dependencies, + desktopModule.Permissions, + desktopModule.ContentItemId, + UserController.GetCurrentUserInfo().UserID); + eventLogController.AddLog(desktopModule, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.DESKTOPMODULE_CREATED); + } + else + { + //Update ContentItem If neccessary + if (desktopModule.ContentItemId == Null.NullInteger) + { + CreateContentItem(desktopModule); + } + + DataProvider.UpdateDesktopModule(desktopModule.DesktopModuleID, + desktopModule.PackageID, + desktopModule.ModuleName, + desktopModule.FolderName, + desktopModule.FriendlyName, + desktopModule.Description, + desktopModule.Version, + desktopModule.IsPremium, + desktopModule.IsAdmin, + desktopModule.BusinessControllerClass, + desktopModule.SupportedFeatures, + (int)desktopModule.Shareable, + desktopModule.CompatibleVersions, + desktopModule.Dependencies, + desktopModule.Permissions, + desktopModule.ContentItemId, + UserController.GetCurrentUserInfo().UserID); + + //Update Tags + if (saveTerms) + { + var termController = Util.GetTermController(); + termController.RemoveTermsFromContent(desktopModule); + foreach (var term in desktopModule.Terms) + { + termController.AddTermToContent(term, desktopModule); + } + } + + eventLogController.AddLog(desktopModule, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.DESKTOPMODULE_UPDATED); + } + if (saveChildren) + { + foreach (var definition in desktopModule.ModuleDefinitions.Values) + { + definition.DesktopModuleID = desktopModuleID; + var moduleDefinition = ModuleDefinitionController.GetModuleDefinitionByDefinitionName(definition.DefinitionName, desktopModuleID); + if (moduleDefinition != null) + { + definition.ModuleDefID = moduleDefinition.ModuleDefID; + } + ModuleDefinitionController.SaveModuleDefinition(definition, true, clearCache); + } + } + if (clearCache) + { + DataCache.ClearHostCache(true); + } + return desktopModuleID; + } + + public void UpdateModuleInterfaces(ref DesktopModuleInfo desktopModuleInfo) + { + UpdateModuleInterfaces(ref desktopModuleInfo, (UserController.GetCurrentUserInfo() == null) ? "" : UserController.GetCurrentUserInfo().Username, true); + } + + public void UpdateModuleInterfaces(ref DesktopModuleInfo desktopModuleInfo, string sender, bool forceAppRestart) + { + CheckInterfacesImplementation(ref desktopModuleInfo); + var oAppStartMessage = new EventMessage + { + Sender = sender, + Priority = MessagePriority.High, + ExpirationDate = DateTime.Now.AddYears(-1), + SentDate = DateTime.Now, + Body = "", + ProcessorType = "DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke", + ProcessorCommand = "UpdateSupportedFeatures" + }; + oAppStartMessage.Attributes.Add("BusinessControllerClass", desktopModuleInfo.BusinessControllerClass); + oAppStartMessage.Attributes.Add("DesktopModuleId", desktopModuleInfo.DesktopModuleID.ToString()); + EventQueueController.SendMessage(oAppStartMessage, "Application_Start"); + if ((forceAppRestart)) + { + Config.Touch(); + } + + } + + private void CheckInterfacesImplementation(ref DesktopModuleInfo desktopModuleInfo) + { + var businessController = Reflection.CreateType(desktopModuleInfo.BusinessControllerClass); + var controller = Reflection.CreateObject(desktopModuleInfo.BusinessControllerClass, desktopModuleInfo.BusinessControllerClass); + + desktopModuleInfo.IsPortable = businessController.GetInterfaces().Contains(typeof (IPortable)); +#pragma warning disable 0618 + desktopModuleInfo.IsSearchable = (controller is ModuleSearchBase) || businessController.GetInterfaces().Contains(typeof(ISearchable)); +#pragma warning restore 0618 + desktopModuleInfo.IsUpgradeable = businessController.GetInterfaces().Contains(typeof(IUpgradeable)); + } + + #endregion + + #region PortalDesktopModuleMethods + + public static int AddDesktopModuleToPortal(int portalID, DesktopModuleInfo desktopModule, DesktopModulePermissionCollection permissions, bool clearCache) + { + int portalDesktopModuleID = AddDesktopModuleToPortal(portalID, desktopModule.DesktopModuleID, false, clearCache); + if (portalDesktopModuleID > Null.NullInteger) + { + DesktopModulePermissionController.DeleteDesktopModulePermissionsByPortalDesktopModuleID(portalDesktopModuleID); + foreach (DesktopModulePermissionInfo permission in permissions) + { + permission.PortalDesktopModuleID = portalDesktopModuleID; + DesktopModulePermissionController.AddDesktopModulePermission(permission); + } + } + return portalDesktopModuleID; + } + + public static int AddDesktopModuleToPortal(int portalID, int desktopModuleID, bool addPermissions, bool clearCache) + { + int portalDesktopModuleID; + PortalDesktopModuleInfo portalDesktopModule = GetPortalDesktopModule(portalID, desktopModuleID); + if (portalDesktopModule == null) + { + portalDesktopModuleID = DataProvider.Instance().AddPortalDesktopModule(portalID, desktopModuleID, UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalDesktopModuleID", + portalDesktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_CREATED); + if (addPermissions) + { + ArrayList permissions = PermissionController.GetPermissionsByPortalDesktopModule(); + if (permissions.Count > 0) + { + var permission = permissions[0] as PermissionInfo; + PortalInfo objPortal = new PortalController().GetPortal(portalID); + if (permission != null && objPortal != null) + { + var desktopModulePermission = new DesktopModulePermissionInfo(permission) { RoleID = objPortal.AdministratorRoleId, AllowAccess = true, PortalDesktopModuleID = portalDesktopModuleID }; + DesktopModulePermissionController.AddDesktopModulePermission(desktopModulePermission); + } + } + } + } + else + { + portalDesktopModuleID = portalDesktopModule.PortalDesktopModuleID; + } + if (clearCache) + { + DataCache.ClearPortalCache(portalID, true); + } + return portalDesktopModuleID; + } + + public static void AddDesktopModuleToPortals(int desktopModuleID) + { + var controller = new PortalController(); + foreach (PortalInfo portal in controller.GetPortals()) + { + AddDesktopModuleToPortal(portal.PortalID, desktopModuleID, true, false); + } + DataCache.ClearHostCache(true); + } + + public static void AddDesktopModulesToPortal(int portalID) + { + foreach (DesktopModuleInfo desktopModule in GetDesktopModulesInternal(Null.NullInteger).Values) + { + if (!desktopModule.IsPremium) + { + AddDesktopModuleToPortal(portalID, desktopModule.DesktopModuleID, !desktopModule.IsAdmin, false); + } + } + DataCache.ClearPortalCache(portalID, true); + } + + public static PortalDesktopModuleInfo GetPortalDesktopModule(int portalID, int desktopModuleID) + { + return CBO.FillObject(DataProvider.Instance().GetPortalDesktopModules(portalID, desktopModuleID)); + } + + public static Dictionary GetPortalDesktopModulesByDesktopModuleID(int desktopModuleID) + { + return CBO.FillDictionary("PortalDesktopModuleID", DataProvider.Instance().GetPortalDesktopModules(Null.NullInteger, desktopModuleID)); + } + + public static Dictionary GetPortalDesktopModulesByPortalID(int portalID) + { + string cacheKey = string.Format(DataCache.PortalDesktopModuleCacheKey, portalID); + return + CBO.GetCachedObject>( + new CacheItemArgs(cacheKey, DataCache.PortalDesktopModuleCacheTimeOut, DataCache.PortalDesktopModuleCachePriority, portalID), GetPortalDesktopModulesByPortalIDCallBack); + } + + public static SortedList GetPortalDesktopModules(int portalID) + { + Dictionary dicModules = GetPortalDesktopModulesByPortalID(portalID); + var lstModules = new SortedList(); + foreach (PortalDesktopModuleInfo desktopModule in dicModules.Values) + { + if (DesktopModulePermissionController.HasDesktopModulePermission(desktopModule.Permissions, "DEPLOY")) + { + lstModules.Add(desktopModule.FriendlyName, desktopModule); + } + } + return lstModules; + } + + public static void RemoveDesktopModuleFromPortal(int portalID, int desktopModuleID, bool clearCache) + { + DataProvider.Instance().DeletePortalDesktopModules(portalID, desktopModuleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModuleID", + desktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_DELETED); + if (clearCache) + { + DataCache.ClearPortalCache(portalID, false); + } + } + + public static void RemoveDesktopModuleFromPortals(int desktopModuleID) + { + DataProvider.Instance().DeletePortalDesktopModules(Null.NullInteger, desktopModuleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModuleID", + desktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_DELETED); + DataCache.ClearHostCache(true); + } + + public static void RemoveDesktopModulesFromPortal(int portalID) + { + DataProvider.Instance().DeletePortalDesktopModules(portalID, Null.NullInteger); + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalID", + portalID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_DELETED); + DataCache.ClearPortalCache(portalID, true); + } + + public static void SerializePortalDesktopModules(XmlWriter writer, int portalID) + { + writer.WriteStartElement("portalDesktopModules"); + foreach (PortalDesktopModuleInfo portalDesktopModule in GetPortalDesktopModulesByPortalID(portalID).Values) + { + writer.WriteStartElement("portalDesktopModule"); + writer.WriteElementString("friendlyname", portalDesktopModule.FriendlyName); + writer.WriteStartElement("portalDesktopModulePermissions"); + foreach (DesktopModulePermissionInfo permission in portalDesktopModule.Permissions) + { + writer.WriteStartElement("portalDesktopModulePermission"); + writer.WriteElementString("permissioncode", permission.PermissionCode); + writer.WriteElementString("permissionkey", permission.PermissionKey); + writer.WriteElementString("allowaccess", permission.AllowAccess.ToString().ToLower()); + writer.WriteElementString("rolename", permission.RoleName); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + + #endregion + + #region Obsolete + + /// ----------------------------------------------------------------------------- + /// + /// AddDesktopModule adds a new Desktop Module to the database + /// + /// The Desktop Module to save + /// + /// [cnurse] 01/11/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated In DotNetNuke 6.0. Replaced by SaveDesktopModule")] + public int AddDesktopModule(DesktopModuleInfo objDesktopModule) + { + return SaveDesktopModule(objDesktopModule, false, true); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method AddDesktopModuleToPortal(Integer, Integer)")] + public void AddPortalDesktopModule(int portalID, int desktopModuleID) + { + DataProvider.Instance().AddPortalDesktopModule(portalID, desktopModuleID, UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModuleID", + desktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_CREATED); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method RemoveDesktopModulesFromPortal(Integer)")] + public void DeletePortalDesktopModules(int portalID, int desktopModuleID) + { + DataProvider.Instance().DeletePortalDesktopModules(portalID, desktopModuleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModuleID", + desktopModuleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALDESKTOPMODULE_DELETED); + DataCache.ClearPortalCache(portalID, true); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetDesktopModule(Integer, Integer)")] + public DesktopModuleInfo GetDesktopModule(int desktopModuleId) + { + return (from kvp in GetDesktopModulesInternal(Null.NullInteger) where kvp.Value.DesktopModuleID == desktopModuleId select kvp.Value).FirstOrDefault(); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetDesktopModuleByModuleName(String, Integer)")] + public DesktopModuleInfo GetDesktopModuleByName(string friendlyName) + { + return (from kvp in GetDesktopModulesInternal(Null.NullInteger) where kvp.Value.FriendlyName == friendlyName select kvp.Value).FirstOrDefault(); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetDesktopModuleByModuleName(String, Integer)")] + public DesktopModuleInfo GetDesktopModuleByModuleName(string moduleName) + { + return (from kvp in GetDesktopModulesInternal(Null.NullInteger) where kvp.Value.ModuleName == moduleName select kvp.Value).FirstOrDefault(); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetDesktopModules(Integer)")] + public ArrayList GetDesktopModules() + { + return new ArrayList(GetDesktopModulesInternal(Null.NullInteger).Values); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetDesktopModules(Integer)")] + public ArrayList GetDesktopModulesByPortal(int portalID) + { + return CBO.FillCollection(DataProvider.GetDesktopModulesByPortal(portalID), typeof(DesktopModuleInfo)); + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetPortalDesktopModulesByPortalID(Integer) and GetPortalDesktopModulesByDesktopModuleID(Integer) And GetPortalDesktopModule(Integer, Integer)")] + public ArrayList GetPortalDesktopModules(int portalID, int desktopModuleID) + { + return CBO.FillCollection(DataProvider.Instance().GetPortalDesktopModules(portalID, desktopModuleID), typeof(PortalDesktopModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateDesktopModule saves the Desktop Module to the database + /// + /// The Desktop Module to save + /// + /// [cnurse] 01/11/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated In DotNetNuke 6.0. Replaced by SaveDesktopModule")] + public void UpdateDesktopModule(DesktopModuleInfo objDesktopModule) + { + SaveDesktopModule(objDesktopModule, false, true); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/DesktopModuleInfo.cs b/DNN Platform/Library/Entities/Modules/DesktopModuleInfo.cs new file mode 100644 index 00000000000..656d28959e4 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/DesktopModuleInfo.cs @@ -0,0 +1,718 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules.Definitions; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : DesktopModuleInfo + /// ----------------------------------------------------------------------------- + /// + /// DesktopModuleInfo provides the Entity Layer for Desktop Modules + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class DesktopModuleInfo : ContentItem, IXmlSerializable + { + private Dictionary _moduleDefinitions; + + public DesktopModuleInfo() + { + IsPremium = Null.NullBoolean; + IsAdmin = Null.NullBoolean; + CodeSubDirectory = Null.NullString; + PackageID = Null.NullInteger; + DesktopModuleID = Null.NullInteger; + SupportedFeatures = Null.NullInteger; + Shareable = ModuleSharing.Unknown; + } + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ID of the Desktop Module + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int DesktopModuleID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ID of the Package for this Desktop Module + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int PackageID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the BusinessControllerClass of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string BusinessControllerClass { get; set; } + + public string Category + { + get + { + Term term = (from Term t in Terms select t).FirstOrDefault(); + return (term != null) ? term.Name : String.Empty; + } + set + { + Terms.Clear(); + ITermController termController = Util.GetTermController(); + var term = (from Term t in termController.GetTermsByVocabulary("Module_Categories") + where t.Name == value + select t) + .FirstOrDefault(); + if (term != null) + { + Terms.Add(term); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the AppCode Folder Name of the Desktop Module + /// + /// A String + /// + /// [cnurse] 02/20/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string CodeSubDirectory { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a Regular Expression that matches the versions of the core + /// that this module is compatible with + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string CompatibleVersions { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a list of Dependencies for the module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string Dependencies { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Description of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string Description { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Folder Name of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string FolderName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Friendly Name of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string FriendlyName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Module is an Admin Module + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsAdmin { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Module is Portable + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsPortable + { + get + { + return GetFeature(DesktopModuleSupportedFeature.IsPortable); + } + set + { + UpdateFeature(DesktopModuleSupportedFeature.IsPortable, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Module is a Premium Module + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsPremium { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Module is Searchable + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsSearchable + { + get + { + return GetFeature(DesktopModuleSupportedFeature.IsSearchable); + } + set + { + UpdateFeature(DesktopModuleSupportedFeature.IsSearchable, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Module is Upgradable + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsUpgradeable + { + get + { + return GetFeature(DesktopModuleSupportedFeature.IsUpgradeable); + } + set + { + UpdateFeature(DesktopModuleSupportedFeature.IsUpgradeable, value); + } + } + + /// + /// Is the module allowed to be shared across sites? + /// + public ModuleSharing Shareable + { + get; + set; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Definitions for this Desktop Module + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public Dictionary ModuleDefinitions + { + get + { + if (_moduleDefinitions == null) + { + if (DesktopModuleID > Null.NullInteger) + { + _moduleDefinitions = ModuleDefinitionController.GetModuleDefinitionsByDesktopModuleID(DesktopModuleID); + } + else + { + _moduleDefinitions = new Dictionary(); + } + } + return _moduleDefinitions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Name of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string ModuleName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a list of Permissions for the module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string Permissions { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Supported Features of the Module + /// + /// An Integer + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int SupportedFeatures { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Version of the Desktop Module + /// + /// A String + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string Version { get; set; } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a DesktopModuleInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/11/2008 Created + /// + /// ----------------------------------------------------------------------------- + public override void Fill(IDataReader dr) + { + DesktopModuleID = Null.SetNullInteger(dr["DesktopModuleID"]); + PackageID = Null.SetNullInteger(dr["PackageID"]); + ModuleName = Null.SetNullString(dr["ModuleName"]); + FriendlyName = Null.SetNullString(dr["FriendlyName"]); + Description = Null.SetNullString(dr["Description"]); + FolderName = Null.SetNullString(dr["FolderName"]); + Version = Null.SetNullString(dr["Version"]); + Description = Null.SetNullString(dr["Description"]); + IsPremium = Null.SetNullBoolean(dr["IsPremium"]); + IsAdmin = Null.SetNullBoolean(dr["IsAdmin"]); + BusinessControllerClass = Null.SetNullString(dr["BusinessControllerClass"]); + SupportedFeatures = Null.SetNullInteger(dr["SupportedFeatures"]); + CompatibleVersions = Null.SetNullString(dr["CompatibleVersions"]); + Dependencies = Null.SetNullString(dr["Dependencies"]); + Permissions = Null.SetNullString(dr["Permissions"]); + Shareable = (ModuleSharing)Null.SetNullInteger(dr["Shareable"]); + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the DesktopModule + /// + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a DesktopModuleInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + if (reader.NodeType == XmlNodeType.Element && reader.Name == "moduleDefinitions" && !reader.IsEmptyElement) + { + ReadModuleDefinitions(reader); + } + else if (reader.NodeType == XmlNodeType.Element && reader.Name == "supportedFeatures" && !reader.IsEmptyElement) + { + ReadSupportedFeatures(reader); + } + else if (reader.NodeType == XmlNodeType.Element && reader.Name == "shareable" && !reader.IsEmptyElement) + { + ReadModuleSharing(reader); + } + else + { + switch (reader.Name) + { + case "desktopModule": + break; + case "moduleName": + ModuleName = reader.ReadElementContentAsString(); + break; + case "foldername": + FolderName = reader.ReadElementContentAsString(); + break; + case "businessControllerClass": + BusinessControllerClass = reader.ReadElementContentAsString(); + break; + case "codeSubDirectory": + CodeSubDirectory = reader.ReadElementContentAsString(); + break; + case "isAdmin": + bool isAdmin; + Boolean.TryParse(reader.ReadElementContentAsString(), out isAdmin); + IsAdmin = isAdmin; + break; + case "isPremium": + bool isPremium; + Boolean.TryParse(reader.ReadElementContentAsString(), out isPremium); + IsPremium = isPremium; + break; + default: + var content = reader.ReadElementContentAsString(); + break; + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a DesktopModuleInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("desktopModule"); + + //write out properties + writer.WriteElementString("moduleName", ModuleName); + writer.WriteElementString("foldername", FolderName); + writer.WriteElementString("businessControllerClass", BusinessControllerClass); + if (!string.IsNullOrEmpty(CodeSubDirectory)) + { + writer.WriteElementString("codeSubDirectory", CodeSubDirectory); + } + + //Write out Supported Features + writer.WriteStartElement("supportedFeatures"); + if (IsPortable) + { + writer.WriteStartElement("supportedFeature"); + writer.WriteAttributeString("type", "Portable"); + writer.WriteEndElement(); + } + if (IsSearchable) + { + writer.WriteStartElement("supportedFeature"); + writer.WriteAttributeString("type", "Searchable"); + writer.WriteEndElement(); + } + if (IsUpgradeable) + { + writer.WriteStartElement("supportedFeature"); + writer.WriteAttributeString("type", "Upgradeable"); + writer.WriteEndElement(); + } + + //Write end of Supported Features + writer.WriteEndElement(); + + // Module sharing + + if(Shareable != ModuleSharing.Unknown) + { + writer.WriteStartElement("shareable"); + switch (Shareable) + { + case ModuleSharing.Supported: + writer.WriteString("Supported"); + break; + case ModuleSharing.Unsupported: + writer.WriteString("Unsupported"); + break; + } + writer.WriteEndElement(); + } + + //Write start of Module Definitions + writer.WriteStartElement("moduleDefinitions"); + + //Iterate through definitions + foreach (ModuleDefinitionInfo definition in ModuleDefinitions.Values) + { + definition.WriteXml(writer); + } + //Write end of Module Definitions + writer.WriteEndElement(); + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + + #region "Private Helper Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Clears a Feature from the Features + /// + /// The feature to Clear + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private void ClearFeature(DesktopModuleSupportedFeature feature) + { + //And with the 1's complement of Feature to Clear the Feature flag + SupportedFeatures = SupportedFeatures & ~((int) feature); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Feature from the Features + /// + /// The feature to Get + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private bool GetFeature(DesktopModuleSupportedFeature feature) + { + return SupportedFeatures > Null.NullInteger && (SupportedFeatures & (int) feature) == (int) feature; + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets a Feature in the Features + /// + /// The feature to Set + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private void SetFeature(DesktopModuleSupportedFeature feature) + { + SupportedFeatures |= (int) feature; + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Feature in the Features + /// + /// The feature to Set + /// A Boolean indicating whether to set or clear the feature + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private void UpdateFeature(DesktopModuleSupportedFeature feature, bool isSet) + { + if (isSet) + { + SetFeature(feature); + } + else + { + ClearFeature(feature); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a Supported Features from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void ReadSupportedFeatures(XmlReader reader) + { + SupportedFeatures = 0; + reader.ReadStartElement("supportedFeatures"); + do + { + if (reader.HasAttributes) + { + reader.MoveToFirstAttribute(); + switch (reader.ReadContentAsString()) + { + case "Portable": + IsPortable = true; + break; + case "Searchable": + IsSearchable = true; + break; + case "Upgradeable": + IsUpgradeable = true; + break; + } + } + } while (reader.ReadToNextSibling("supportedFeature")); + } + + private void ReadModuleSharing(XmlReader reader) + { + var sharing = reader.ReadElementString("shareable"); + + if (string.IsNullOrEmpty(sharing)) + { + Shareable = ModuleSharing.Unknown; + } + else + { + switch (sharing.ToLowerInvariant()) + { + case "supported": + Shareable = ModuleSharing.Supported; + break; + case "unsupported": + Shareable = ModuleSharing.Unsupported; + break; + default: + case "unknown": + Shareable = ModuleSharing.Unknown; + break; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a Module Definitions from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void ReadModuleDefinitions(XmlReader reader) + { + reader.ReadStartElement("moduleDefinitions"); + do + { + reader.ReadStartElement("moduleDefinition"); + + //Create new ModuleDefinition object + var moduleDefinition = new ModuleDefinitionInfo(); + + //Load it from the Xml + moduleDefinition.ReadXml(reader); + + //Add to the collection + ModuleDefinitions.Add(moduleDefinition.FriendlyName, moduleDefinition); + } while (reader.ReadToNextSibling("moduleDefinition")); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/DesktopModuleSupportedFeature.cs b/DNN Platform/Library/Entities/Modules/DesktopModuleSupportedFeature.cs new file mode 100644 index 00000000000..6af6084081f --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/DesktopModuleSupportedFeature.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : DesktopModuleSupportedFeature + /// ----------------------------------------------------------------------------- + /// + /// The DesktopModuleSupportedFeature enum provides an enumeration of Supported + /// Features + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Flags] + public enum DesktopModuleSupportedFeature + { + IsPortable = 1, + IsSearchable = 2, + IsUpgradeable = 4 + } +} diff --git a/DNN Platform/Library/Entities/Modules/EventMessageProcessor.cs b/DNN Platform/Library/Entities/Modules/EventMessageProcessor.cs new file mode 100644 index 00000000000..511d74b0cae --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/EventMessageProcessor.cs @@ -0,0 +1,195 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.EventQueue; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public class EventMessageProcessor : EventMessageProcessorBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (EventMessageProcessor)); + private static void ImportModule(EventMessage message) + { + try + { + string BusinessControllerClass = message.Attributes["BusinessControllerClass"]; + object controller = Reflection.CreateObject(BusinessControllerClass, ""); + if (controller is IPortable) + { + int ModuleId = Convert.ToInt32(message.Attributes["ModuleId"]); + string Content = HttpUtility.HtmlDecode(message.Attributes["Content"]); + string Version = message.Attributes["Version"]; + int UserID = Convert.ToInt32(message.Attributes["UserId"]); + //call the IPortable interface for the module/version + ((IPortable) controller).ImportModule(ModuleId, Content, Version, UserID); + //Synchronize Module Cache + ModuleController.SynchronizeModule(ModuleId); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + } + + private static void UpgradeModule(EventMessage message) + { + try + { + int desktopModuleId = Convert.ToInt32(message.Attributes["DesktopModuleId"]); + var desktopModule = DesktopModuleController.GetDesktopModule(desktopModuleId, Null.NullInteger); + + string BusinessControllerClass = message.Attributes["BusinessControllerClass"]; + object controller = Reflection.CreateObject(BusinessControllerClass, ""); + var eventLogController = new EventLogController(); + LogInfo eventLogInfo; + if (controller is IUpgradeable) + { + //get the list of applicable versions + string[] UpgradeVersions = message.Attributes["UpgradeVersionsList"].Split(','); + foreach (string Version in UpgradeVersions) + { + //call the IUpgradeable interface for the module/version + string Results = ((IUpgradeable) controller).UpgradeModule(Version); + //log the upgrade results + eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("Module Upgraded", BusinessControllerClass); + eventLogInfo.AddProperty("Version", Version); + if (!string.IsNullOrEmpty(Results)) + { + eventLogInfo.AddProperty("Results", Results); + } + eventLogInfo.LogTypeKey = EventLogController.EventLogType.MODULE_UPDATED.ToString(); + eventLogController.AddLog(eventLogInfo); + } + } + UpdateSupportedFeatures(controller, Convert.ToInt32(message.Attributes["DesktopModuleId"])); + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + } + + private static void UpdateSupportedFeatures(EventMessage message) + { + string BusinessControllerClass = message.Attributes["BusinessControllerClass"]; + object controller = Reflection.CreateObject(BusinessControllerClass, ""); + UpdateSupportedFeatures(controller, Convert.ToInt32(message.Attributes["DesktopModuleId"])); + } + + private static void UpdateSupportedFeatures(object objController, int desktopModuleId) + { + try + { + DesktopModuleInfo desktopModule = DesktopModuleController.GetDesktopModule(desktopModuleId, Null.NullInteger); + if ((desktopModule != null)) + { + //Initialise the SupportedFeatures + desktopModule.SupportedFeatures = 0; + + //Test the interfaces + desktopModule.IsPortable = (objController is IPortable); +#pragma warning disable 0618 + desktopModule.IsSearchable = (objController is ModuleSearchBase) || (objController is ISearchable); +#pragma warning restore 0618 + desktopModule.IsUpgradeable = (objController is IUpgradeable); + DesktopModuleController.SaveDesktopModule(desktopModule, false, false, false); + + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + DataCache.RemoveCache(String.Format(DataCache.DesktopModuleCacheKey, portal.PortalID)); + DataCache.RemoveCache(String.Format(DataCache.PortalDesktopModuleCacheKey, portal.PortalID)); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + } + + public static void CreateImportModuleMessage(ModuleInfo objModule, string content, string version, int userID) + { + var appStartMessage = new EventMessage + { + Priority = MessagePriority.High, + ExpirationDate = DateTime.Now.AddYears(-1), + SentDate = DateTime.Now, + Body = "", + ProcessorType = "DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke", + ProcessorCommand = "ImportModule" + }; + + //Add custom Attributes for this message + appStartMessage.Attributes.Add("BusinessControllerClass", objModule.DesktopModule.BusinessControllerClass); + appStartMessage.Attributes.Add("ModuleId", objModule.ModuleID.ToString()); + appStartMessage.Attributes.Add("Content", content); + appStartMessage.Attributes.Add("Version", version); + appStartMessage.Attributes.Add("UserID", userID.ToString()); + + //send it to occur on next App_Start Event + EventQueueController.SendMessage(appStartMessage, "Application_Start_FirstRequest"); + } + + public override bool ProcessMessage(EventMessage message) + { + try + { + switch (message.ProcessorCommand) + { + case "UpdateSupportedFeatures": + UpdateSupportedFeatures(message); + break; + case "UpgradeModule": + UpgradeModule(message); + break; + case "ImportModule": + ImportModule(message); + break; + default: + //other events can be added here + break; + } + } + catch (Exception ex) + { + Logger.Error(ex); + message.ExceptionMessage = ex.Message; + return false; + } + return true; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/IActionable.cs b/DNN Platform/Library/Entities/Modules/IActionable.cs new file mode 100644 index 00000000000..bf7e43a2cf2 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/IActionable.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Entities.Modules.Actions; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public interface IActionable + { + ModuleActionCollection ModuleActions { get; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/IHydratable.cs b/DNN Platform/Library/Entities/Modules/IHydratable.cs new file mode 100644 index 00000000000..1df0453627d --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/IHydratable.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Data; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public interface IHydratable + { + int KeyID { get; set; } + + void Fill(IDataReader dr); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/IPortable.cs b/DNN Platform/Library/Entities/Modules/IPortable.cs new file mode 100644 index 00000000000..408b0f193c6 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/IPortable.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules +{ + public interface IPortable + { + string ExportModule(int ModuleID); + + void ImportModule(int ModuleID, string Content, string Version, int UserID); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ISearchable.cs b/DNN Platform/Library/Entities/Modules/ISearchable.cs new file mode 100644 index 00000000000..c7c4e0b4c72 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ISearchable.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Search; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + [Obsolete("Deprecated in DNN 7.1. Replaced by ModuleSearchBase")] + public interface ISearchable + { + [Obsolete("Deprecated in DNN 7.1. Replaced by ModuleSearchBase.GetModifiedSearchDocuments")] + SearchItemInfoCollection GetSearchItems(ModuleInfo ModInfo); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/IShareable.cs b/DNN Platform/Library/Entities/Modules/IShareable.cs new file mode 100644 index 00000000000..85aeb2df04d --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/IShareable.cs @@ -0,0 +1,28 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public interface IShareable + { + /// Does this module support Module Sharing (i.e., sharing modules between sites within a SiteGroup)? + ModuleSharing SharingSupport { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/IUpgradeable.cs b/DNN Platform/Library/Entities/Modules/IUpgradeable.cs new file mode 100644 index 00000000000..3be0b42185e --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/IUpgradeable.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules +{ + public interface IUpgradeable + { + string UpgradeModule(string Version); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Internal/IModuleController.cs b/DNN Platform/Library/Entities/Modules/Internal/IModuleController.cs new file mode 100644 index 00000000000..62806461463 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Internal/IModuleController.cs @@ -0,0 +1,57 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +namespace DotNetNuke.Entities.Modules.Internal +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IModuleController + { + /// + /// Gets the module. + /// + /// The module ID. + /// The tab ID. + /// module info + ModuleInfo GetModule(int moduleId, int tabId); + + /// + /// Adds or updates a module's setting value + /// + /// ID of the tabmodule, the setting belongs to + /// name of the setting property + /// value of the setting (String). + /// Empty SettingValue will remove the setting + void UpdateModuleSetting(int moduleId, string settingName, string settingValue); + + /// + /// Adds or updates a tab module's setting value + /// + /// ID of the tabmodule, the setting belongs to + /// name of the setting property + /// value of the setting (String). + /// Empty SettingValue will remove the setting + void UpdateTabModuleSetting(int tabModuleId, string settingName, string settingValue); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Internal/ModuleControllerImpl.cs b/DNN Platform/Library/Entities/Modules/Internal/ModuleControllerImpl.cs new file mode 100644 index 00000000000..4346663c995 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Internal/ModuleControllerImpl.cs @@ -0,0 +1,41 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. +using System; + +namespace DotNetNuke.Entities.Modules.Internal +{ + internal class ModuleControllerImpl : IModuleController + { + readonly ModuleController _legacyController = new ModuleController(); + + public ModuleInfo GetModule(int moduleId, int tabId) + { + return _legacyController.GetModule(moduleId, tabId); + } + + public void UpdateModuleSetting(int moduleId, string settingName, string settingValue) + { + _legacyController.UpdateModuleSetting(moduleId, settingName, settingValue); + } + + public void UpdateTabModuleSetting(int tabModuleId, string settingName, string settingValue) + { + _legacyController.UpdateTabModuleSetting(tabModuleId, settingName, settingValue); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/Internal/TestableModuleController.cs b/DNN Platform/Library/Entities/Modules/Internal/TestableModuleController.cs new file mode 100644 index 00000000000..e49e149c654 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/Internal/TestableModuleController.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Framework; + +namespace DotNetNuke.Entities.Modules.Internal +{ + public class TestableModuleController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new ModuleControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ModuleControlController.cs b/DNN Platform/Library/Entities/Modules/ModuleControlController.cs new file mode 100644 index 00000000000..f8f8db7f33a --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleControlController.cs @@ -0,0 +1,257 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ModuleControlController + /// ----------------------------------------------------------------------------- + /// + /// ModuleControlController provides the Business Layer for Module Controls + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class ModuleControlController + { + private const string key = "ModuleControlID"; + private static readonly DataProvider dataProvider = DataProvider.Instance(); + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleControls gets a Dictionary of Module Controls from + /// the Cache. + /// + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static Dictionary GetModuleControls() + { + return CBO.GetCachedObject>(new CacheItemArgs(DataCache.ModuleControlsCacheKey, + DataCache.ModuleControlsCacheTimeOut, + DataCache.ModuleControlsCachePriority), + GetModuleControlsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleControlsCallBack gets a Dictionary of Module Controls from + /// the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static object GetModuleControlsCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillDictionary(key, dataProvider.GetModuleControls(), new Dictionary()); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleControl adds a new Module Control to the database + /// + /// The Module Control to save + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static void AddModuleControl(ModuleControlInfo objModuleControl) + { + SaveModuleControl(objModuleControl, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteModuleControl deletes a Module Control in the database + /// + /// The ID of the Module Control to delete + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static void DeleteModuleControl(int moduleControlID) + { + dataProvider.DeleteModuleControl(moduleControlID); + DataCache.ClearHostCache(true); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleControl gets a single Module Control from the database + /// + /// The ID of the Module Control to fetch + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static ModuleControlInfo GetModuleControl(int moduleControlID) + { + return (from kvp in GetModuleControls() + where kvp.Key == moduleControlID + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleControl gets a Dictionary of Module Controls by Module Definition + /// + /// The ID of the Module Definition + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetModuleControlsByModuleDefinitionID(int moduleDefID) + { + return GetModuleControls().Where(kvp => kvp.Value.ModuleDefID == moduleDefID) + .ToDictionary(kvp => kvp.Value.ControlKey, kvp => kvp.Value); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleControlByControlKey gets a single Module Control from the database + /// + /// The key for the control + /// The ID of the Module Definition + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static ModuleControlInfo GetModuleControlByControlKey(string controlKey, int moduleDefID) + { + return (from kvp in GetModuleControls() + where kvp.Value.ControlKey.ToLowerInvariant() == controlKey.ToLowerInvariant() + && kvp.Value.ModuleDefID == moduleDefID + select kvp.Value) + .FirstOrDefault(); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveModuleControl updates a Module Control in the database + /// + /// The Module Control to save + /// A flag that determines whether to clear the host cache + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static int SaveModuleControl(ModuleControlInfo moduleControl, bool clearCache) + { + int moduleControlID = moduleControl.ModuleControlID; + if (moduleControlID == Null.NullInteger) + { + //Add new Module Definition + moduleControlID = dataProvider.AddModuleControl(moduleControl.ModuleDefID, + moduleControl.ControlKey, + moduleControl.ControlTitle, + moduleControl.ControlSrc, + moduleControl.IconFile, + Convert.ToInt32(moduleControl.ControlType), + moduleControl.ViewOrder, + moduleControl.HelpURL, + moduleControl.SupportsPartialRendering, + moduleControl.SupportsPopUps, + UserController.GetCurrentUserInfo().UserID); + } + else + { + //Upgrade Module Control + dataProvider.UpdateModuleControl(moduleControl.ModuleControlID, + moduleControl.ModuleDefID, + moduleControl.ControlKey, + moduleControl.ControlTitle, + moduleControl.ControlSrc, + moduleControl.IconFile, + Convert.ToInt32(moduleControl.ControlType), + moduleControl.ViewOrder, + moduleControl.HelpURL, + moduleControl.SupportsPartialRendering, + moduleControl.SupportsPopUps, + UserController.GetCurrentUserInfo().UserID); + } + if (clearCache) + { + DataCache.ClearHostCache(true); + } + return moduleControlID; + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateModuleControl updates a Module Control in the database + /// + /// The Module Control to save + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static void UpdateModuleControl(ModuleControlInfo objModuleControl) + { + SaveModuleControl(objModuleControl, true); + } + + #region "Obsolete" + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleControlsByModuleDefinitionID(Integer)")] + public static ArrayList GetModuleControls(int moduleDefID) + { + var arrControls = new ArrayList(); + arrControls.AddRange(GetModuleControlsByModuleDefinitionID(moduleDefID).Values); + return arrControls; + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleControlByControlKey(String, Integer)")] + public static ArrayList GetModuleControlsByKey(string controlKey, int moduleDefID) + { + var arrControls = new ArrayList {GetModuleControlByControlKey(controlKey, moduleDefID)}; + return arrControls; + } + + [Obsolete("This method replaced in DotNetNuke 5.0 by Shared method GetModuleControlByControlKey(String, Integer)")] + public static ModuleControlInfo GetModuleControlByKeyAndSrc(int moduleDefID, string controlKey, string controlSrc) + { + return GetModuleControlByControlKey(controlKey, moduleDefID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/ModuleControlInfo.cs b/DNN Platform/Library/Entities/Modules/ModuleControlInfo.cs new file mode 100644 index 00000000000..a449980e041 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleControlInfo.cs @@ -0,0 +1,295 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ModuleControlInfo + /// ----------------------------------------------------------------------------- + /// + /// ModuleControlInfo provides the Entity Layer for Module Controls + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ModuleControlInfo : ControlInfo, IXmlSerializable, IHydratable + { + public ModuleControlInfo() + { + ModuleControlID = Null.NullInteger; + ModuleDefID = Null.NullInteger; + ControlType = SecurityAccessLevel.Anonymous; + SupportsPopUps = false; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Control Title + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string ControlTitle { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Control Type + /// + /// A SecurityAccessLevel + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public SecurityAccessLevel ControlType { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Help URL + /// + /// A String + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public string HelpURL { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Icon Source + /// + /// A String + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public string IconFile { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module Control ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int ModuleControlID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module Definition ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int ModuleDefID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether to support popup. + /// + /// A Boolean value + /// ----------------------------------------------------------------------------- + public bool SupportsPopUps { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the View Order + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int ViewOrder { get; set; } + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ModuleControlInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + ModuleControlID = Null.SetNullInteger(dr["ModuleControlID"]); + FillInternal(dr); + ModuleDefID = Null.SetNullInteger(dr["ModuleDefID"]); + ControlTitle = Null.SetNullString(dr["ControlTitle"]); + IconFile = Null.SetNullString(dr["IconFile"]); + HelpURL = Null.SetNullString(dr["HelpUrl"]); + ControlType = (SecurityAccessLevel) Enum.Parse(typeof (SecurityAccessLevel), Null.SetNullString(dr["ControlType"])); + ViewOrder = Null.SetNullInteger(dr["ViewOrder"]); + SupportsPopUps = Null.SetNullBoolean(dr["SupportsPopUps"]); + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return ModuleControlID; + } + set + { + ModuleControlID = value; + } + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the ModuleControlInfo + /// + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a ModuleControlInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + ReadXmlInternal(reader); + switch (reader.Name) + { + case "controlTitle": + ControlTitle = reader.ReadElementContentAsString(); + break; + case "controlType": + ControlType = (SecurityAccessLevel) Enum.Parse(typeof (SecurityAccessLevel), reader.ReadElementContentAsString()); + break; + case "iconFile": + IconFile = reader.ReadElementContentAsString(); + break; + case "helpUrl": + HelpURL = reader.ReadElementContentAsString(); + break; + case "supportsPopUps": + SupportsPopUps = Boolean.Parse(reader.ReadElementContentAsString()); + break; + case "viewOrder": + string elementvalue = reader.ReadElementContentAsString(); + if (!string.IsNullOrEmpty(elementvalue)) + { + ViewOrder = int.Parse(elementvalue); + } + break; + default: + if(reader.NodeType == XmlNodeType.Element && !String.IsNullOrEmpty(reader.Name)) + { + reader.ReadElementContentAsString(); + } + break; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a ModuleControlInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 01/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("moduleControl"); + + //write out properties + WriteXmlInternal(writer); + writer.WriteElementString("controlTitle", ControlTitle); + writer.WriteElementString("controlType", ControlType.ToString()); + writer.WriteElementString("iconFile", IconFile); + writer.WriteElementString("helpUrl", HelpURL); + writer.WriteElementString("supportsPopUps", SupportsPopUps.ToString()); + if (ViewOrder > Null.NullInteger) + { + writer.WriteElementString("viewOrder", ViewOrder.ToString()); + } + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/ModuleController.cs b/DNN Platform/Library/Entities/Modules/ModuleController.cs new file mode 100644 index 00000000000..be350c58f97 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleController.cs @@ -0,0 +1,2490 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Threading; +using System.Web; +using System.Xml; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.ModuleCache; +using DotNetNuke.Services.OutputCache; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ModuleController + /// ----------------------------------------------------------------------------- + /// + /// ModuleController provides the Business Layer for Modules + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class ModuleController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModuleController)); + private static readonly DataProvider dataProvider = DataProvider.Instance(); + + #region Private Methods + + private static Hashtable ParsedLocalizedModuleGuid + { + get + { + if (HttpContext.Current.Items["ParsedLocalizedModuleGuid"] == null) + HttpContext.Current.Items["ParsedLocalizedModuleGuid"] = new Hashtable(); + + return (Hashtable)HttpContext.Current.Items["ParsedLocalizedModuleGuid"]; + } + } + + private static void AddContent(XmlNode nodeModule, ModuleInfo module) + { + if (!String.IsNullOrEmpty(module.DesktopModule.BusinessControllerClass) && module.DesktopModule.IsPortable) + { + try + { + object businessController = Reflection.CreateObject(module.DesktopModule.BusinessControllerClass, module.DesktopModule.BusinessControllerClass); + var controller = businessController as IPortable; + if (controller != null) + { + string Content = Convert.ToString(controller.ExportModule(module.ModuleID)); + if (!String.IsNullOrEmpty(Content)) + { + //add attributes to XML document + if (nodeModule.OwnerDocument != null) + { + var existing = nodeModule.OwnerDocument.GetElementById("content"); + if (existing != null) + { + nodeModule.OwnerDocument.RemoveChild(existing); + } + + XmlNode newnode = nodeModule.OwnerDocument.CreateElement("content"); + XmlAttribute xmlattr = nodeModule.OwnerDocument.CreateAttribute("type"); + xmlattr.Value = Globals.CleanName(module.DesktopModule.ModuleName); + if (newnode.Attributes != null) + { + newnode.Attributes.Append(xmlattr); + } + xmlattr = nodeModule.OwnerDocument.CreateAttribute("version"); + xmlattr.Value = module.DesktopModule.Version; + if (newnode.Attributes != null) + { + newnode.Attributes.Append(xmlattr); + } + Content = HttpContext.Current.Server.HtmlEncode(Content); + newnode.InnerXml = XmlUtils.XMLEncode(Content); + nodeModule.AppendChild(newnode); + } + } + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + } + + private void AddModuleInternal(ModuleInfo module) + { + var eventLogController = new EventLogController(); + // add module + if (Null.IsNull(module.ModuleID)) + { + CreateContentItem(module); + + //Add Module + module.ModuleID = dataProvider.AddModule(module.ContentItemId, + module.PortalID, + module.ModuleDefID, + module.AllTabs, + module.StartDate, + module.EndDate, + module.InheritViewPermissions, + module.IsShareable, + module.IsShareableViewOnly, + module.IsDeleted, + UserController.GetCurrentUserInfo().UserID); + + //Now we have the ModuleID - update the contentItem + var contentController = Util.GetContentController(); + contentController.UpdateContentItem(module); + + eventLogController.AddLog(module, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.MODULE_CREATED); + + // set module permissions + ModulePermissionController.SaveModulePermissions(module); + } + + //Save ModuleSettings + UpdateModuleSettings(module); + } + + private static void AddModulePermission(ref ModuleInfo module, int portalId, string roleName, PermissionInfo permission, string permissionKey) + { + var perm = module.ModulePermissions.Where(tp => tp.RoleName == roleName && tp.PermissionKey == permissionKey).SingleOrDefault(); + if (permission != null && perm == null) + { + var modulePermission = new ModulePermissionInfo(permission); +// ReSharper disable ImplicitlyCapturedClosure + var role = TestableRoleController.Instance.GetRole(portalId, r => (r.RoleName == roleName)); +// ReSharper restore ImplicitlyCapturedClosure + if (role != null) + { + modulePermission.RoleID = role.RoleID; + modulePermission.AllowAccess = true; + + module.ModulePermissions.Add(modulePermission); + } + } + } + + private ModulePermissionInfo AddModulePermission(ModuleInfo module, PermissionInfo permission, int roleId, int userId, bool allowAccess) + { + var modulePermission = new ModulePermissionInfo + { + ModuleID = module.ModuleID, + PermissionID = permission.PermissionID, + RoleID = roleId, + UserID = userId, + PermissionKey = permission.PermissionKey, + AllowAccess = allowAccess + }; + + // add the permission to the collection + if (!module.ModulePermissions.Contains(modulePermission)) + { + module.ModulePermissions.Add(modulePermission); + } + + return modulePermission; + } + + private static bool CheckIsInstance(int templateModuleID, Hashtable hModules) + { + //will be instance or module? + bool IsInstance = false; + if (templateModuleID > 0) + { + if (hModules[templateModuleID] != null) + { + //this module has already been processed -> process as instance + IsInstance = true; + } + } + return IsInstance; + } + + private static ModuleInfo DeserializeModule(XmlNode nodeModule, XmlNode nodePane, int portalId, int tabId, int moduleDefId) + { + //Create New Module + var module = new ModuleInfo + { + PortalID = portalId, + TabID = tabId, + ModuleOrder = -1, + ModuleTitle = XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "title"), + PaneName = XmlUtils.GetNodeValue(nodePane.CreateNavigator(), "name"), + ModuleDefID = moduleDefId, + CacheTime = XmlUtils.GetNodeValueInt(nodeModule, "cachetime"), + CacheMethod = XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "cachemethod"), + Alignment = XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "alignment"), + IconFile = Globals.ImportFile(portalId, XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "iconfile")), + AllTabs = XmlUtils.GetNodeValueBoolean(nodeModule, "alltabs"), + CultureCode = XmlUtils.GetNodeValue(nodeModule, "cultureCode") + }; + + // Localization + var oldGuid = XmlUtils.GetNodeValue(nodeModule, "defaultLanguageGuid"); + if (!string.IsNullOrEmpty(oldGuid)) + { + // get new default module language guid + if (ParsedLocalizedModuleGuid.ContainsKey(oldGuid)) + { + module.DefaultLanguageGuid = new Guid(ParsedLocalizedModuleGuid[oldGuid].ToString()); + } + } + + switch (XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "visibility")) + { + case "Maximized": + module.Visibility = VisibilityState.Maximized; + break; + case "Minimized": + module.Visibility = VisibilityState.Minimized; + break; + case "None": + module.Visibility = VisibilityState.None; + break; + } + module.Color = XmlUtils.GetNodeValue(nodeModule, "color", ""); + module.Border = XmlUtils.GetNodeValue(nodeModule, "border", ""); + module.Header = XmlUtils.GetNodeValue(nodeModule, "header", ""); + module.Footer = XmlUtils.GetNodeValue(nodeModule, "footer", ""); + module.InheritViewPermissions = XmlUtils.GetNodeValueBoolean(nodeModule, "inheritviewpermissions", false); + module.IsShareable = XmlUtils.GetNodeValueBoolean(nodeModule, "isshareable", true); + module.IsShareableViewOnly = XmlUtils.GetNodeValueBoolean(nodeModule, "isshareableviewonly", true); + module.StartDate = XmlUtils.GetNodeValueDate(nodeModule, "startdate", Null.NullDate); + module.EndDate = XmlUtils.GetNodeValueDate(nodeModule, "enddate", Null.NullDate); + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeModule, "containersrc", ""))) + { + module.ContainerSrc = XmlUtils.GetNodeValue(nodeModule, "containersrc", ""); + } + module.DisplayTitle = XmlUtils.GetNodeValueBoolean(nodeModule, "displaytitle", true); + module.DisplayPrint = XmlUtils.GetNodeValueBoolean(nodeModule, "displayprint", true); + module.DisplaySyndicate = XmlUtils.GetNodeValueBoolean(nodeModule, "displaysyndicate", false); + module.IsWebSlice = XmlUtils.GetNodeValueBoolean(nodeModule, "iswebslice", false); + if (module.IsWebSlice) + { + module.WebSliceTitle = XmlUtils.GetNodeValue(nodeModule, "webslicetitle", module.ModuleTitle); + module.WebSliceExpiryDate = XmlUtils.GetNodeValueDate(nodeModule, "websliceexpirydate", module.EndDate); + module.WebSliceTTL = XmlUtils.GetNodeValueInt(nodeModule, "webslicettl", module.CacheTime / 60); + } + return module; + } + + private static void DeserializeModulePermissions(XmlNodeList nodeModulePermissions, int portalId, ModuleInfo module) + { + var permissionController = new PermissionController(); + foreach (XmlNode node in nodeModulePermissions) + { + string permissionKey = XmlUtils.GetNodeValue(node.CreateNavigator(), "permissionkey"); + string permissionCode = XmlUtils.GetNodeValue(node.CreateNavigator(), "permissioncode"); + string roleName = XmlUtils.GetNodeValue(node.CreateNavigator(), "rolename"); + int roleID = int.MinValue; + switch (roleName) + { + case Globals.glbRoleAllUsersName: + roleID = Convert.ToInt32(Globals.glbRoleAllUsers); + break; + case Globals.glbRoleUnauthUserName: + roleID = Convert.ToInt32(Globals.glbRoleUnauthUser); + break; + default: + var role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleName == roleName); + if (role != null) + { + roleID = role.RoleID; + } + break; + } + if (roleID != int.MinValue) + { + int permissionID = -1; + ArrayList permissions = permissionController.GetPermissionByCodeAndKey(permissionCode, permissionKey); + for (int i = 0; i <= permissions.Count - 1; i++) + { + var permission = (PermissionInfo)permissions[i]; + permissionID = permission.PermissionID; + } + + //if role was found add, otherwise ignore + if (permissionID != -1) + { + var modulePermission = new ModulePermissionInfo + { + ModuleID = module.ModuleID, + PermissionID = permissionID, + RoleID = roleID, + AllowAccess = Convert.ToBoolean(XmlUtils.GetNodeValue(node.CreateNavigator(), "allowaccess")) + }; + + // do not add duplicate ModulePermissions + bool canAdd = !module.ModulePermissions.Cast() + .Any(mp => mp.ModuleID == modulePermission.ModuleID + && mp.PermissionID == modulePermission.PermissionID + && mp.RoleID == modulePermission.RoleID + && mp.UserID == modulePermission.UserID); + if (canAdd) + { + module.ModulePermissions.Add(modulePermission); + } + } + } + } + } + + private static void DeserializeModuleSettings(XmlNodeList nodeModuleSettings, ModuleInfo objModule) + { + foreach (XmlNode moduleSettingNode in nodeModuleSettings) + { + string key = XmlUtils.GetNodeValue(moduleSettingNode.CreateNavigator(), "settingname"); + string value = XmlUtils.GetNodeValue(moduleSettingNode.CreateNavigator(), "settingvalue"); + objModule.ModuleSettings[key] = value; + } + } + + private static void DeserializeTabModuleSettings(XmlNodeList nodeTabModuleSettings, ModuleInfo objModule) + { + foreach (XmlNode tabModuleSettingNode in nodeTabModuleSettings) + { + string key = XmlUtils.GetNodeValue(tabModuleSettingNode.CreateNavigator(), "settingname"); + string value = XmlUtils.GetNodeValue(tabModuleSettingNode.CreateNavigator(), "settingvalue"); + objModule.TabModuleSettings[key] = value; + } + } + + private static bool FindModule(XmlNode nodeModule, int tabId, PortalTemplateModuleAction mergeTabs) + { + var moduleController = new ModuleController(); + var modules = moduleController.GetTabModules(tabId); + + bool moduleFound = false; + string modTitle = XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "title"); + if (mergeTabs == PortalTemplateModuleAction.Merge) + { + if (modules.Select(kvp => kvp.Value).Any(module => modTitle == module.ModuleTitle)) + { + moduleFound = true; + } + } + return moduleFound; + } + + private static void GetModuleContent(XmlNode nodeModule, int ModuleId, int TabId, int PortalId) + { + var moduleController = new ModuleController(); + ModuleInfo module = moduleController.GetModule(ModuleId, TabId, true); + if (nodeModule != null) + { + // ReSharper disable PossibleNullReferenceException + string version = nodeModule.SelectSingleNode("content").Attributes["version"].Value; + string content = nodeModule.SelectSingleNode("content").InnerXml; + content = content.Substring(9, content.Length - 12); + if (!String.IsNullOrEmpty(module.DesktopModule.BusinessControllerClass) && !String.IsNullOrEmpty(content)) + { + var portalController = new PortalController(); + PortalInfo portal = portalController.GetPortal(PortalId); + + content = HttpContext.Current.Server.HtmlDecode(content); + + //Determine if the Module is copmpletely installed + //(ie are we running in the same request that installed the module). + if (module.DesktopModule.SupportedFeatures == Null.NullInteger) + { + //save content in eventqueue for processing after an app restart, + //as modules Supported Features are not updated yet so we + //cannot determine if the module supports IsPortable + EventMessageProcessor.CreateImportModuleMessage(module, content, version, portal.AdministratorId); + } + else + { + if (module.DesktopModule.IsPortable) + { + try + { + object businessController = Reflection.CreateObject(module.DesktopModule.BusinessControllerClass, module.DesktopModule.BusinessControllerClass); + var controller = businessController as IPortable; + if (controller != null) + { + controller.ImportModule(module.ModuleID, content, version, portal.AdministratorId); + } + } + catch + { + //if there is an error then the type cannot be loaded at this time, so add to EventQueue + EventMessageProcessor.CreateImportModuleMessage(module, content, version, portal.AdministratorId); + } + } + } + } + // ReSharper restore PossibleNullReferenceException + } + } + + private static ModuleDefinitionInfo GetModuleDefinition(XmlNode nodeModule) + { + ModuleDefinitionInfo moduleDefinition = null; + + //Templates prior to v4.3.5 only have the node to define the Module Type + //This node was populated with the DesktopModuleInfo.ModuleName property + //Thus there is no mechanism to determine to which module definition the module belongs. + // + //Template from v4.3.5 on also have the element that is populated + //with the ModuleDefinitionInfo.FriendlyName. Therefore the module Instance identifies + //which Module Definition it belongs to. + + //Get the DesktopModule defined by the element + var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "definition"), Null.NullInteger); + if (desktopModule != null) + { + //Get the moduleDefinition from the element + string friendlyName = XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "moduledefinition"); + if (string.IsNullOrEmpty(friendlyName)) + { + //Module is pre 4.3.5 so get the first Module Definition (at least it won't throw an error then) + foreach (ModuleDefinitionInfo md in ModuleDefinitionController.GetModuleDefinitionsByDesktopModuleID(desktopModule.DesktopModuleID).Values) + { + moduleDefinition = md; + break; + } + } + else + { + //Module is 4.3.5 or later so get the Module Defeinition by its friendly name + moduleDefinition = ModuleDefinitionController.GetModuleDefinitionByFriendlyName(friendlyName, desktopModule.DesktopModuleID); + } + } + return moduleDefinition; + } + + private static object GetTabModulesCallBack(CacheItemArgs cacheItemArgs) + { + var tabID = (int)cacheItemArgs.ParamList[0]; + return CBO.FillDictionary("ModuleID", dataProvider.GetTabModules(tabID), new Dictionary()); + } + + private int LocalizeModuleInternal(ModuleInfo sourceModule) + { + int moduleId = Null.NullInteger; + + if (sourceModule != null) + { + // clone the module object ( to avoid creating an object reference to the data cache ) + var newModule = sourceModule.Clone(); + newModule.ModuleID = Null.NullInteger; + + string translatorRoles = PortalController.GetPortalSetting(string.Format("DefaultTranslatorRoles-{0}", sourceModule.CultureCode), sourceModule.PortalID, "").TrimEnd(';'); + + //Add the default translators for this language, view and edit permissions + var permissionController = new PermissionController(); + var viewPermissionsList = permissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", "VIEW"); + var editPermissionsList = permissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", "EDIT"); + PermissionInfo viewPermisison = null; + PermissionInfo editPermisison = null; + + //View + if (viewPermissionsList != null && viewPermissionsList.Count > 0) + { + viewPermisison = (PermissionInfo)viewPermissionsList[0]; + } + + //Edit + if (editPermissionsList != null && editPermissionsList.Count > 0) + { + editPermisison = (PermissionInfo)editPermissionsList[0]; + } + + if (viewPermisison != null || editPermisison != null) + { + foreach (string translatorRole in translatorRoles.Split(';')) + { + AddModulePermission(ref newModule, sourceModule.PortalID, translatorRole, viewPermisison, "VIEW"); + AddModulePermission(ref newModule, sourceModule.PortalID, translatorRole, editPermisison, "EDIT"); + } + } + + //Add Module + AddModuleInternal(newModule); + + //copy module settings + Hashtable settings = GetModuleSettings(sourceModule.ModuleID); + + //Copy each setting to the new TabModule instance + foreach (DictionaryEntry setting in settings) + { + UpdateModuleSetting(newModule.ModuleID, Convert.ToString(setting.Key), Convert.ToString(setting.Value)); + } + + // update tabmodule + dataProvider.UpdateTabModule(newModule.TabModuleID, + newModule.TabID, + newModule.ModuleID, + newModule.ModuleTitle, + newModule.Header, + newModule.Footer, + newModule.ModuleOrder, + newModule.PaneName, + newModule.CacheTime, + newModule.CacheMethod, + newModule.Alignment, + newModule.Color, + newModule.Border, + newModule.IconFile, + (int)newModule.Visibility, + newModule.ContainerSrc, + newModule.DisplayTitle, + newModule.DisplayPrint, + newModule.DisplaySyndicate, + newModule.IsWebSlice, + newModule.WebSliceTitle, + newModule.WebSliceExpiryDate, + newModule.WebSliceTTL, + newModule.VersionGuid, + newModule.DefaultLanguageGuid, + newModule.LocalizedVersionGuid, + newModule.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + if (!string.IsNullOrEmpty(newModule.DesktopModule.BusinessControllerClass)) + { + try + { + object businessController = Reflection.CreateObject(newModule.DesktopModule.BusinessControllerClass, newModule.DesktopModule.BusinessControllerClass); + var portableModule = businessController as IPortable; + if (portableModule != null) + { + string Content = portableModule.ExportModule(sourceModule.ModuleID); + if (!string.IsNullOrEmpty(Content)) + { + portableModule.ImportModule(newModule.ModuleID, Content, newModule.DesktopModule.Version, UserController.GetCurrentUserInfo().UserID); + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + } + + moduleId = newModule.ModuleID; + + //Clear Caches + ClearCache(newModule.TabID); + ClearCache(sourceModule.TabID); + } + + return moduleId; + } + + private void UpdateModuleSettingInternal(int moduleId, string settingName, string settingValue, bool updateVersion) + { + IDataReader dr = null; + try + { + dr = dataProvider.GetModuleSetting(moduleId, settingName); + if (dr.Read()) + { + if (dr.GetString(0) != settingValue) + { + dataProvider.UpdateModuleSetting(moduleId, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.MODULE_SETTING_UPDATED, + "ModuleId", moduleId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + } + else + { + dataProvider.AddModuleSetting(moduleId, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.MODULE_SETTING_CREATED, + "ModuleId", moduleId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + + if (updateVersion) + { + UpdateTabModuleVersionsByModuleID(moduleId); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + // Ensure DataReader is closed + CBO.CloseDataReader(dr, true); + } + + DataCache.RemoveCache("GetModuleSettings" + moduleId); + } + + private void UpdateModuleSettings(ModuleInfo updatedModule) + { + foreach (string key in updatedModule.ModuleSettings.Keys) + { + string sKey = key; + UpdateModuleSettingInternal(updatedModule.ModuleID, sKey, Convert.ToString(updatedModule.ModuleSettings[sKey]), false); + } + UpdateTabModuleVersionsByModuleID(updatedModule.ModuleID); + } + + private void UpdateTabModuleSettings(ModuleInfo updatedTabModule) + { + foreach (string sKey in updatedTabModule.TabModuleSettings.Keys) + { + UpdateTabModuleSetting(updatedTabModule.TabModuleID, sKey, Convert.ToString(updatedTabModule.TabModuleSettings[sKey])); + } + } + + private static void UpdateTabModuleVersion(int tabModuleId) + { + dataProvider.UpdateTabModuleVersion(tabModuleId, Guid.NewGuid()); + } + + private void UpdateTabModuleVersionsByModuleID(int moduleID) + { + // Update the version guid of each TabModule linked to the updated module + foreach (ModuleInfo modInfo in GetAllTabsModulesByModuleID(moduleID)) + { + ClearCache(modInfo.TabID); + } + dataProvider.UpdateTabModuleVersionByModule(moduleID); + } + + #endregion + + #region Public Methods + + /// + /// Deserializes the module. + /// + /// The node module. + /// The node pane. + /// The portal id. + /// The tab id. + /// The merge tabs. + /// The modules. + public static void DeserializeModule(XmlNode nodeModule, XmlNode nodePane, int portalId, int tabId, PortalTemplateModuleAction mergeTabs, Hashtable hModules) + { + var moduleController = new ModuleController(); + var moduleDefinition = GetModuleDefinition(nodeModule); + //will be instance or module? + int templateModuleID = XmlUtils.GetNodeValueInt(nodeModule, "moduleID"); + bool isInstance = CheckIsInstance(templateModuleID, hModules); + if (moduleDefinition != null) + { + //If Mode is Merge Check if Module exists + if (!FindModule(nodeModule, tabId, mergeTabs)) + { + ModuleInfo module = DeserializeModule(nodeModule, nodePane, portalId, tabId, moduleDefinition.ModuleDefID); + //if the module is marked as show on all tabs, then check whether the module is exist in current website and it also + //still marked as shown on all tabs, this action will make sure there is no duplicate modules created on new tab. + if (module.AllTabs) + { + var existModule = moduleController.GetModule(templateModuleID); + if (existModule != null && !existModule.IsDeleted && existModule.AllTabs) + { + return; + } + } + //deserialize Module's settings + XmlNodeList nodeModuleSettings = nodeModule.SelectNodes("modulesettings/modulesetting"); + DeserializeModuleSettings(nodeModuleSettings, module); + XmlNodeList nodeTabModuleSettings = nodeModule.SelectNodes("tabmodulesettings/tabmodulesetting"); + DeserializeTabModuleSettings(nodeTabModuleSettings, module); + + // DNN-24983 get culture from page + var tabInfo = new TabController().GetTab(tabId, portalId, false); + if (tabInfo != null) + { + module.CultureCode = tabInfo.CultureCode; + } + + int intModuleId; + if (!isInstance) + { + //Add new module + intModuleId = moduleController.AddModule(module); + if (templateModuleID > 0) + { + hModules.Add(templateModuleID, intModuleId); + } + } + else + { + //Add instance + module.ModuleID = Convert.ToInt32(hModules[templateModuleID]); + intModuleId = moduleController.AddModule(module); + } + + // save localization info + string oldGuid = XmlUtils.GetNodeValue(nodeModule, "uniqueId"); + if (!ParsedLocalizedModuleGuid.ContainsKey(oldGuid)) + ParsedLocalizedModuleGuid.Add(oldGuid, module.UniqueId.ToString()); + + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeModule.CreateNavigator(), "content")) && !isInstance) + { + GetModuleContent(nodeModule, intModuleId, tabId, portalId); + } + //Process permissions only once + if (!isInstance && portalId != Null.NullInteger) + { + XmlNodeList nodeModulePermissions = nodeModule.SelectNodes("modulepermissions/permission"); + DeserializeModulePermissions(nodeModulePermissions, portalId, module); + + //Persist the permissions to the Data base + ModulePermissionController.SaveModulePermissions(module); + } + } + } + } + + /// + /// SerializeModule + /// + /// The Xml Document to use for the Module + /// The ModuleInfo object to serialize + /// A flak that determines whether the content of the module is serialised. + public static XmlNode SerializeModule(XmlDocument xmlModule, ModuleInfo module, bool includeContent) + { + var serializer = new XmlSerializer(typeof(ModuleInfo)); + var sw = new StringWriter(); + serializer.Serialize(sw, module); + xmlModule.LoadXml(sw.GetStringBuilder().ToString()); + XmlNode moduleNode = xmlModule.SelectSingleNode("module"); + if (moduleNode != null) + { + // ReSharper disable AssignNullToNotNullAttribute + if (moduleNode.Attributes != null) + { + moduleNode.Attributes.Remove(moduleNode.Attributes["xmlns:xsd"]); + moduleNode.Attributes.Remove(moduleNode.Attributes["xmlns:xsi"]); + } + + //remove unwanted elements + moduleNode.RemoveChild(moduleNode.SelectSingleNode("portalid")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("tabid")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("tabmoduleid")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("moduleorder")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("panename")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("isdeleted")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("versionGuid")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("localizedVersionGuid")); + moduleNode.RemoveChild(moduleNode.SelectSingleNode("content")); + + // support for localized templates + //moduleNode.RemoveChild(moduleNode.SelectSingleNode("uniqueId")); + //moduleNode.RemoveChild(moduleNode.SelectSingleNode("defaultLanguageGuid")); + //moduleNode.RemoveChild(moduleNode.SelectSingleNode("cultureCode")); + + if (Null.IsNull(module.DefaultLanguageGuid)) + moduleNode.RemoveChild(moduleNode.SelectSingleNode("defaultLanguageGuid")); + + var xmlNodeList = moduleNode.SelectNodes("modulepermissions/permission"); + if (xmlNodeList != null) + { + foreach (XmlNode nodePermission in xmlNodeList) + { + nodePermission.RemoveChild(nodePermission.SelectSingleNode("modulepermissionid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("permissionid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("moduleid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("roleid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("userid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("username")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("displayname")); + } + } + if (includeContent) + { + AddContent(moduleNode, module); + } + //serialize ModuleSettings and TabModuleSettings + XmlUtils.SerializeHashtable(module.ModuleSettings, xmlModule, moduleNode, "modulesetting", "settingname", "settingvalue"); + XmlUtils.SerializeHashtable(module.TabModuleSettings, xmlModule, moduleNode, "tabmodulesetting", "settingname", "settingvalue"); + + // ReSharper restore AssignNullToNotNullAttribute + } + XmlNode newNode = xmlModule.CreateElement("definition"); + ModuleDefinitionInfo objModuleDef = ModuleDefinitionController.GetModuleDefinitionByID(module.ModuleDefID); + newNode.InnerText = DesktopModuleController.GetDesktopModule(objModuleDef.DesktopModuleID, module.PortalID).ModuleName; + if (moduleNode != null) + { + moduleNode.AppendChild(newNode); + } + //Add Module Definition Info + XmlNode definitionNode = xmlModule.CreateElement("moduledefinition"); + definitionNode.InnerText = objModuleDef.FriendlyName; + if (moduleNode != null) + { + moduleNode.AppendChild(definitionNode); + } + return moduleNode; + } + + /// + /// Synchronizes the module content between cache and database. + /// + /// The module ID. + public static void SynchronizeModule(int moduleID) + { + var moduleController = new ModuleController(); + ArrayList modules = moduleController.GetModuleTabs(moduleID); + var tabController = new TabController(); + foreach (ModuleInfo module in modules) + { + Hashtable tabSettings = tabController.GetTabSettings(module.TabID); + if (tabSettings["CacheProvider"] != null && tabSettings["CacheProvider"].ToString().Length > 0) + { + var outputProvider = OutputCachingProvider.Instance(tabSettings["CacheProvider"].ToString()); + if (outputProvider != null) + { + outputProvider.Remove(module.TabID); + } + } + + if (module.CacheTime > 0) + { + var moduleProvider = ModuleCachingProvider.Instance(module.GetEffectiveCacheMethod()); + if (moduleProvider != null) + { + moduleProvider.Remove(module.TabModuleID); + } + } + + //Synchronize module is called when a module needs to indicate that the content + //has changed and the cache's should be refreshed. So we can update the Version + //and also the LastContentModificationDate + UpdateTabModuleVersion(module.TabModuleID); + dataProvider.UpdateModuleLastContentModifiedOnDate(module.ModuleID); + + //We should also indicate that the Transalation Status has changed + if (PortalController.GetPortalSettingAsBoolean("ContentLocalizationEnabled", module.PortalID, false)) + { + moduleController.UpdateTranslationStatus(module, false); + } + } + } + + /// + /// add a module to a page + /// + /// moduleInfo for the module to create + /// ID of the created module + /// + /// [sleupold] 2007-09-24 documented + /// + public int AddModule(ModuleInfo module) + { + var eventLogController = new EventLogController(); + //add module + AddModuleInternal(module); + + //Lets see if the module already exists + ModuleInfo tmpModule = GetModule(module.ModuleID, module.TabID); + if (tmpModule != null) + { + //Module Exists already + if (tmpModule.IsDeleted) + { + var order = module.ModuleOrder; + var pane = module.PaneName; + + //Restore Module + RestoreModule(module); + + //Set Module Order as expected + UpdateModuleOrder(module.TabID, module.ModuleID, order, pane); + UpdateTabModuleOrder(module.TabID); + } + } + else + { + //add tabmodule + dataProvider.AddTabModule(module.TabID, + module.ModuleID, + module.ModuleTitle, + module.Header, + module.Footer, + module.ModuleOrder, + module.PaneName, + module.CacheTime, + module.CacheMethod, + module.Alignment, + module.Color, + module.Border, + module.IconFile, + (int)module.Visibility, + module.ContainerSrc, + module.DisplayTitle, + module.DisplayPrint, + module.DisplaySyndicate, + module.IsWebSlice, + module.WebSliceTitle, + module.WebSliceExpiryDate, + module.WebSliceTTL, + module.UniqueId, + module.VersionGuid, + module.DefaultLanguageGuid, + module.LocalizedVersionGuid, + module.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + var eventLogInfo = new LogInfo(); + eventLogInfo.LogProperties.Add(new LogDetailInfo("TabPath", module.ParentTab.TabPath)); + eventLogInfo.LogProperties.Add(new LogDetailInfo("Module Type", module.ModuleDefinition.FriendlyName)); + eventLogInfo.LogProperties.Add(new LogDetailInfo("TabId", module.TabID.ToString())); + eventLogInfo.LogProperties.Add(new LogDetailInfo("ModuleID", module.ModuleID.ToString())); + eventLogInfo.LogTypeKey = EventLogController.EventLogType.TABMODULE_CREATED.ToString(); + eventLogInfo.LogPortalID = module.PortalID; + eventLogController.AddLog(eventLogInfo); + if (module.ModuleOrder == -1) + { + //position module at bottom of pane + UpdateModuleOrder(module.TabID, module.ModuleID, module.ModuleOrder, module.PaneName); + } + else + { + //position module in pane + UpdateTabModuleOrder(module.TabID); + } + } + + //Save ModuleSettings + if (module.TabModuleID == -1) + { + if (tmpModule == null) + { + tmpModule = GetModule(module.ModuleID, module.TabID); + } + module.TabModuleID = tmpModule.TabModuleID; + } + UpdateTabModuleSettings(module); + ClearCache(module.TabID); + return module.ModuleID; + } + + /// + /// Clears the cache. + /// + /// The tab id. + public void ClearCache(int TabId) + { + DataCache.ClearModuleCache(TabId); + } + + + /// + /// Copies the module to a new page. + /// + /// The source module. + /// The destination tab. + /// Name of to pane. + /// if set to true include settings. + public void CopyModule(ModuleInfo sourceModule, TabInfo destinationTab, string toPaneName, bool includeSettings) + { + PortalInfo portal = new PortalController().GetPortal(destinationTab.PortalID); + + //Clone Module + ModuleInfo destinationModule = sourceModule.Clone(); + if (!String.IsNullOrEmpty(toPaneName)) + { + destinationModule.PaneName = toPaneName; + } + + destinationModule.TabID = destinationTab.TabID; + + //The new reference copy should have the same culture as the destination Tab + destinationModule.UniqueId = Guid.NewGuid(); + destinationModule.CultureCode = destinationTab.CultureCode; + destinationModule.VersionGuid = Guid.NewGuid(); + destinationModule.LocalizedVersionGuid = Guid.NewGuid(); + + //Figure out the DefaultLanguage Guid + if (!String.IsNullOrEmpty(sourceModule.CultureCode) && sourceModule.CultureCode == portal.DefaultLanguage && destinationModule.CultureCode != sourceModule.CultureCode && + !String.IsNullOrEmpty(destinationModule.CultureCode)) + { + //Tab is localized so set Default language Guid reference + destinationModule.DefaultLanguageGuid = sourceModule.UniqueId; + } + else if (!String.IsNullOrEmpty(sourceModule.CultureCode) && sourceModule.CultureCode != portal.DefaultLanguage && destinationModule.CultureCode != sourceModule.CultureCode && + !String.IsNullOrEmpty(destinationModule.CultureCode)) + { + // tab is localized, but the source is not in the default language (it was on a single culture page) + // this wires up all the connections + sourceModule.DefaultLanguageGuid = destinationModule.UniqueId; + UpdateModule(sourceModule); + } + else if (sourceModule.AllTabs && sourceModule.CultureCode != portal.DefaultLanguage) + { + if (sourceModule.DefaultLanguageModule != null && destinationTab.DefaultLanguageTab != null) + { + ModuleInfo defaultLanguageModule = GetModule(sourceModule.DefaultLanguageModule.ModuleID, destinationTab.DefaultLanguageTab.TabID); + + if (defaultLanguageModule != null) + { + destinationModule.DefaultLanguageGuid = defaultLanguageModule.UniqueId; + } + } + } + + //This will fail if the page already contains this module + try + { + //Add a copy of the module to the bottom of the Pane for the new Tab + dataProvider.AddTabModule(destinationModule.TabID, + destinationModule.ModuleID, + destinationModule.ModuleTitle, + destinationModule.Header, + destinationModule.Footer, + destinationModule.ModuleOrder, + destinationModule.PaneName, + destinationModule.CacheTime, + destinationModule.CacheMethod, + destinationModule.Alignment, + destinationModule.Color, + destinationModule.Border, + destinationModule.IconFile, + (int)destinationModule.Visibility, + destinationModule.ContainerSrc, + destinationModule.DisplayTitle, + destinationModule.DisplayPrint, + destinationModule.DisplaySyndicate, + destinationModule.IsWebSlice, + destinationModule.WebSliceTitle, + destinationModule.WebSliceExpiryDate, + destinationModule.WebSliceTTL, + destinationModule.UniqueId, + destinationModule.VersionGuid, + destinationModule.DefaultLanguageGuid, + destinationModule.LocalizedVersionGuid, + destinationModule.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + //Optionally copy the TabModuleSettings + if (includeSettings) + { + CopyTabModuleSettings(sourceModule, destinationModule); + } + } + catch (Exception exc) + { + // module already in the page, ignore error + Logger.Error(exc); + } + + ClearCache(sourceModule.TabID); + ClearCache(destinationTab.TabID); + + //Optionally copy the TabModuleSettings + if (includeSettings) + { + destinationModule = GetModule(destinationModule.ModuleID, destinationModule.TabID); + CopyTabModuleSettings(sourceModule, destinationModule); + } + } + + /// + /// Copies all modules in source page to a new page. + /// + /// The source tab. + /// The destination tab. + /// if set to true will use source module directly, else will create new module info by source module. + public void CopyModules(TabInfo sourceTab, TabInfo destinationTab, bool asReference) + { + foreach (KeyValuePair kvp in GetTabModules(sourceTab.TabID)) + { + ModuleInfo sourceModule = kvp.Value; + + // if the module shows on all pages does not need to be copied since it will + // be already added to this page + if (!sourceModule.AllTabs && !sourceModule.IsDeleted) + { + if (!asReference) + { + //Deep Copy + var newModule = sourceModule.Clone(); + newModule.ModuleID = Null.NullInteger; + newModule.TabID = destinationTab.TabID; + AddModule(sourceModule); + } + else + { + //Shallow (Reference Copy) + CopyModule(sourceModule, destinationTab, Null.NullString, true); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// CopyTabModuleSettings copies the TabModuleSettings from one instance to another + /// + /// + /// + /// The module to copy from + /// The module to copy to + /// + /// [cnurse] 2005-01-11 created + /// + /// ----------------------------------------------------------------------------- + public void CopyTabModuleSettings(ModuleInfo fromModule, ModuleInfo toModule) + { + //Get the TabModuleSettings + Hashtable settings = GetTabModuleSettings(fromModule.TabModuleID); + + //Copy each setting to the new TabModule instance + foreach (DictionaryEntry setting in settings) + { + UpdateTabModuleSetting(toModule.TabModuleID, Convert.ToString(setting.Key), Convert.ToString(setting.Value)); + } + } + + /// + /// + /// + /// + /// + /// + /// [vnguyen] 20110-05-10 Modified: Added update tabmodule versionguids + /// + public void CreateContentItem(ModuleInfo module) + { + IContentTypeController typeController = new ContentTypeController(); + ContentType contentType = (from t in typeController.GetContentTypes() + where t.ContentType == "Module" + select t).SingleOrDefault(); + //This module does not have a valid ContentItem + //create ContentItem + IContentController contentController = Util.GetContentController(); + module.Content = module.ModuleTitle; + module.Indexed = false; + if (contentType != null) + { + module.ContentTypeId = contentType.ContentTypeId; + } + module.ContentItemId = contentController.AddContentItem(module); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteAllModules deletes all instances of a Module (from a collection). This overload + /// soft deletes the instances + /// + /// The Id of the module to copy + /// The Id of the current tab + /// An ArrayList of TabItem objects + /// + /// [cnurse] 2009-03-24 created + /// + /// ----------------------------------------------------------------------------- + public void DeleteAllModules(int moduleId, int tabId, List fromTabs) + { + DeleteAllModules(moduleId, tabId, fromTabs, true, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteAllModules deletes all instances of a Module (from a collection), optionally excluding the + /// current instance, and optionally including deleting the Module itself. + /// + /// + /// Note - the base module is not removed unless both the flags are set, indicating + /// to delete all instances AND to delete the Base Module + /// + /// The Id of the module to copy + /// The Id of the current tab + /// A flag that determines whether the instance should be soft-deleted + /// An ArrayList of TabItem objects + /// A flag to indicate whether to delete from the current tab + /// as identified ny tabId + /// A flag to indicate whether to delete the Module itself + /// + /// [cnurse] 2004-10-22 created + /// + /// ----------------------------------------------------------------------------- + public void DeleteAllModules(int moduleId, int tabId, List fromTabs, bool softDelete, bool includeCurrent, bool deleteBaseModule) + { + //Iterate through collection deleting the module from each Tab (except the current) + foreach (TabInfo objTab in fromTabs) + { + if (objTab.TabID != tabId || includeCurrent) + { + DeleteTabModule(objTab.TabID, moduleId, softDelete); + } + } + //Optionally delete the Module + if (includeCurrent && deleteBaseModule && !softDelete) + { + DeleteModule(moduleId); + } + ClearCache(tabId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Delete a module instance permanently from the database + /// + /// ID of the module instance + /// + /// [sleupold] 1007-09-24 documented + /// + /// ----------------------------------------------------------------------------- + public void DeleteModule(int moduleId) + { + //Get the module + ModuleInfo module = GetModule(moduleId); + //Delete Module + dataProvider.DeleteModule(moduleId); + + //Remove the Content Item + if (module != null && module.ContentItemId > Null.NullInteger) + { + IContentController contentController = Util.GetContentController(); + contentController.DeleteContentItem(module); + } + + //Log deletion + var eventLogController = new EventLogController(); + eventLogController.AddLog("ModuleId", moduleId.ToString(), PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.MODULE_DELETED); + + //Delete Search Items for this Module + dataProvider.DeleteSearchItems(moduleId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Delete a module reference permanently from the database. + /// if there are no other references, the module instance is deleted as well + /// + /// ID of the page + /// ID of the module instance + /// A flag that determines whether the instance should be soft-deleted + /// + /// [sleupold] 1007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added logic to update tabmodule version guid + /// + /// ----------------------------------------------------------------------------- + public void DeleteTabModule(int tabId, int moduleId, bool softDelete) + { + //save moduleinfo + ModuleInfo objModule = GetModule(moduleId, tabId, false); + + if (objModule != null) + { + //delete the module instance for the tab + dataProvider.DeleteTabModule(tabId, moduleId, softDelete); + var eventLog = new EventLogController(); + var logInfo = new LogInfo(); + logInfo.LogProperties.Add(new LogDetailInfo("tabId", tabId.ToString())); + logInfo.LogProperties.Add(new LogDetailInfo("moduleId", moduleId.ToString())); + logInfo.LogTypeKey = EventLogController.EventLogType.TABMODULE_DELETED.ToString(); + eventLog.AddLog(logInfo); + + //reorder all modules on tab + UpdateTabModuleOrder(tabId); + + //check if all modules instances have been deleted + if (GetModule(moduleId, Null.NullInteger, true).TabID == Null.NullInteger) + { + //hard delete the module + DeleteModule(moduleId); + } + } + ClearCache(tabId); + } + + /// + /// Des the localize module. + /// + /// The source module. + /// new module id + public int DeLocalizeModule(ModuleInfo sourceModule) + { + int moduleId = Null.NullInteger; + + if (sourceModule != null && sourceModule.DefaultLanguageModule != null) + { + // clone the module object ( to avoid creating an object reference to the data cache ) + ModuleInfo newModule = sourceModule.Clone(); + + //Get the Module ID of the default language instance + newModule.ModuleID = sourceModule.DefaultLanguageModule.ModuleID; + + if (newModule.ModuleID != sourceModule.ModuleID) + { + // update tabmodule + dataProvider.UpdateTabModule(newModule.TabModuleID, + newModule.TabID, + newModule.ModuleID, + newModule.ModuleTitle, + newModule.Header, + newModule.Footer, + newModule.ModuleOrder, + newModule.PaneName, + newModule.CacheTime, + newModule.CacheMethod, + newModule.Alignment, + newModule.Color, + newModule.Border, + newModule.IconFile, + (int)newModule.Visibility, + newModule.ContainerSrc, + newModule.DisplayTitle, + newModule.DisplayPrint, + newModule.DisplaySyndicate, + newModule.IsWebSlice, + newModule.WebSliceTitle, + newModule.WebSliceExpiryDate, + newModule.WebSliceTTL, + newModule.VersionGuid, + newModule.DefaultLanguageGuid, + newModule.LocalizedVersionGuid, + newModule.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + //check if all modules instances have been deleted + if (GetModule(sourceModule.ModuleID, Null.NullInteger, true).TabID == Null.NullInteger) + { + //delete the deep copy "module info" + DeleteModule(sourceModule.ModuleID); + } + + } + + moduleId = newModule.ModuleID; + + //Clear Caches + ClearCache(newModule.TabID); + ClearCache(sourceModule.TabID); + } + + return moduleId; + } + + /// ----------------------------------------------------------------------------- + /// + /// get info of all modules in any portal of the installation + /// + /// moduleInfo of all modules + /// created for upgrade purposes + /// + /// [sleupold] 2007-09-24 documented + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetAllModules() + { + return CBO.FillCollection(dataProvider.GetAllModules(), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// get Module objects of a portal, either only those, to be placed on all tabs or not + /// + /// ID of the portal + /// specify, whether to return modules to be shown on all tabs or those to be shown on specified tabs + /// ArrayList of TabModuleInfo objects + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetAllTabsModules(int portalID, bool allTabs) + { + return CBO.FillCollection(dataProvider.GetAllTabsModules(portalID, allTabs), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// get TabModule objects that are linked to a particular ModuleID + /// + /// ID of the module + /// ArrayList of TabModuleInfo objects + /// + /// [vnguyen] 2010-05-10 Created + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetAllTabsModulesByModuleID(int moduleID) + { + return CBO.FillCollection(dataProvider.GetAllTabsModulesByModuleID(moduleID), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// get a Module object + /// + /// ID of the module + /// a ModuleInfo object - note that this method will always hit the database as no TabID cachekey is provided + /// + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetModule(int moduleID) + { + return GetModule(moduleID, Null.NullInteger, true); + } + + /// + /// Gets the module. + /// + /// The module ID. + /// The tab ID. + /// module info + public ModuleInfo GetModule(int moduleID, int tabID) + { + return GetModule(moduleID, tabID, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// get a Module object + /// + /// + /// + /// + /// + /// + /// [vnguyen] 2010/05/11 Created + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetModuleByUniqueID(Guid uniqueID) + { + return CBO.FillObject(dataProvider.GetModuleByUniqueID(uniqueID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// get a Module object + /// + /// ID of the module + /// ID of the page + /// flag, if data shall not be taken from cache + /// ArrayList of ModuleInfo objects + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetModule(int moduleID, int tabID, bool ignoreCache) + { + ModuleInfo modInfo = null; + bool bFound = false; + if (!ignoreCache) + { + //First try the cache + var dicModules = GetTabModules(tabID); + bFound = dicModules.TryGetValue(moduleID, out modInfo); + } + if (ignoreCache || !bFound) + { + modInfo = CBO.FillObject(dataProvider.GetModule(moduleID, tabID)); + } + return modInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// get Module by specific locale + /// + /// ID of the module + /// ID of the tab + /// ID of the portal + /// The wanted locale + /// ModuleInfo associated to submitted locale + /// + /// [manzoni Fausto] 2010-10-27 commented + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetModuleByCulture(int ModuleId, int tabid, int portalId, Locale locale) + { + ModuleInfo localizedModule = null; + + //Get Module specified by Id + ModuleInfo originalModule = GetModule(ModuleId, tabid); + + if (locale != null && originalModule != null) + { + //Check if tab is in the requested culture + if (string.IsNullOrEmpty(originalModule.CultureCode) || originalModule.CultureCode == locale.Code) + { + localizedModule = originalModule; + } + else + { + //See if tab exists for culture + if (originalModule.IsDefaultLanguage) + { + originalModule.LocalizedModules.TryGetValue(locale.Code, out localizedModule); + } + else + { + if (originalModule.DefaultLanguageModule != null) + { + if (originalModule.DefaultLanguageModule.CultureCode == locale.Code) + { + localizedModule = originalModule.DefaultLanguageModule; + } + else + { + if (!originalModule.DefaultLanguageModule.LocalizedModules.TryGetValue(locale.Code, out localizedModule)) + { + localizedModule = originalModule.DefaultLanguageModule; + } + } + } + } + } + } + return localizedModule; + } + + /// ----------------------------------------------------------------------------- + /// + /// get all Module objects of a portal + /// + /// ID of the portal + /// ArrayList of ModuleInfo objects + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetModules(int portalID) + { + return CBO.FillCollection(dataProvider.GetModules(portalID), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get ModuleInfo object of first module instance with a given friendly name of the module definition + /// + /// ID of the portal, where to look for the module + /// friendly name of module definition + /// ModuleInfo of first module instance + /// preferably used for admin and host modules + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetModuleByDefinition(int portalId, string friendlyName) + { + //declare return object + ModuleInfo module; + + //format cache key + string key = string.Format(DataCache.ModuleCacheKey, portalId); + + //get module dictionary from cache + var modules = DataCache.GetCache>(key) ?? new Dictionary(); + if (modules.ContainsKey(friendlyName)) + { + module = modules[friendlyName]; + } + else + { + //clone the dictionary so that we have a local copy + var clonemodules = new Dictionary(); + foreach (ModuleInfo m in modules.Values) + { + clonemodules[m.ModuleDefinition.FriendlyName] = m; + } + //get from database + IDataReader dr = DataProvider.Instance().GetModuleByDefinition(portalId, friendlyName); + try + { + //hydrate object + module = CBO.FillObject(dr); + } + finally + { + //close connection + CBO.CloseDataReader(dr, true); + } + if (module != null) + { + //add the module to the dictionary + clonemodules[module.ModuleDefinition.FriendlyName] = module; + + //set module caching settings + Int32 timeOut = DataCache.ModuleCacheTimeOut * Convert.ToInt32(Host.Host.PerformanceSetting); + + //cache module dictionary + if (timeOut > 0) + { + DataCache.SetCache(key, clonemodules, TimeSpan.FromMinutes(timeOut)); + } + } + } + return module; + } + + /// + /// Gets the modules by definition. + /// + /// The portal ID. + /// Name of the friendly. + /// module collection + public ArrayList GetModulesByDefinition(int portalID, string friendlyName) + { + return CBO.FillCollection(DataProvider.Instance().GetModuleByDefinition(portalID, friendlyName), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get a list of all TabModule references of a module instance + /// + /// ID of the Module + /// ArrayList of ModuleInfo + /// + /// [sleupold] 2007-09-24 documented + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetModuleTabs(int moduleID) + { + return CBO.FillCollection(dataProvider.GetModule(moduleID, Null.NullInteger), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// For a portal get a list of all active module and tabmodule references that are Searchable + /// either by inheriting from ModuleSearchBase or implementing the older ISearchable interface. + /// + /// ID of the portal to be searched + /// Arraylist of ModuleInfo for modules supporting search. + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetSearchModules(int portalID) + { + return CBO.FillCollection(dataProvider.GetSearchModules(portalID), typeof(ModuleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// get a Module object + /// + /// ID of the tabmodule + /// An ModuleInfo object + /// + /// [vnguyen] 04-07-2010 + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo GetTabModule(int tabModuleID) + { + return CBO.FillObject(dataProvider.GetTabModule(tabModuleID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get all Module references on a tab + /// + /// + /// Dictionary of ModuleID and ModuleInfo + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public Dictionary GetTabModules(int tabId) + { + string cacheKey = string.Format(DataCache.TabModuleCacheKey, tabId); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.TabModuleCacheTimeOut, DataCache.TabModuleCachePriority, tabId), GetTabModulesCallBack); + } + + public void LocalizeModule(ModuleInfo sourceModule, Locale locale) + { + try + { + // we could be working from a single culture page that is not in the default language, + // so we need to test whether or not the module is going to be localized for the default locale + var defaultLocale = LocaleController.Instance.GetDefaultLocale(sourceModule.PortalID); + ModuleInfo defaultModule = locale.Code == defaultLocale.Code ? sourceModule : sourceModule.DefaultLanguageModule; + + if (defaultModule != null) + { + ArrayList tabModules = GetModuleTabs(defaultModule.ModuleID); + if (tabModules.Count > 1) + { + //default language version is a reference copy + + //Localize first tabModule + int newModuleID = LocalizeModuleInternal(sourceModule); + + //Update Reference Copies + foreach (ModuleInfo tm in tabModules) + { + if (tm.IsDefaultLanguage) + { + ModuleInfo localModule; + if (tm.LocalizedModules.TryGetValue(locale.Code, out localModule)) + { + localModule.ModuleID = newModuleID; + UpdateModule(localModule); + } + } + } + } + else + { + LocalizeModuleInternal(sourceModule); + } + } + } + catch (Exception ex) + { + Logger.ErrorFormat("Error localizing module, moduleId: {0}, full exception: {1}", sourceModule.ModuleID, ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// MoveModule moes a Module from one Tab to another including all the + /// TabModule settings + /// + /// The Id of the module to move + /// The Id of the source tab + /// The Id of the destination tab + /// The name of the Pane on the destination tab where the module will end up + /// + /// [cnurse] 10/21/2004 created + /// + /// ----------------------------------------------------------------------------- + public void MoveModule(int moduleId, int fromTabId, int toTabId, string toPaneName) + { + //Move the module to the Tab + dataProvider.MoveTabModule(fromTabId, moduleId, toTabId, toPaneName, UserController.GetCurrentUserInfo().UserID); + + //Update Module Order for source tab, also updates the tabmodule version guid + UpdateTabModuleOrder(fromTabId); + + //Update Module Order for target tab, also updates the tabmodule version guid + UpdateTabModuleOrder(toTabId); + } + + /// + /// Restores the module. + /// + /// The module. + public void RestoreModule(ModuleInfo objModule) + { + dataProvider.RestoreTabModule(objModule.TabID, objModule.ModuleID); + ClearCache(objModule.TabID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Update module settings and permissions in database from ModuleInfo + /// + /// ModuleInfo of the module to update + /// + /// [sleupold] 2007-09-24 commented + /// [vnguyen] 2010-05-10 Modified: Added update tabmodule version guid + /// [sleupold] 2010-12-09 Fixed .AllModule updates + /// + /// ----------------------------------------------------------------------------- + public void UpdateModule(ModuleInfo module) + { + //Update ContentItem If neccessary + if (module.ContentItemId == Null.NullInteger && module.ModuleID != Null.NullInteger) + { + CreateContentItem(module); + } + + //update module + dataProvider.UpdateModule(module.ModuleID, + module.ModuleDefID, + module.ContentItemId, + module.AllTabs, + module.StartDate, + module.EndDate, + module.InheritViewPermissions, + module.IsShareable, + module.IsShareableViewOnly, + module.IsDeleted, + UserController.GetCurrentUserInfo().UserID); + + //Update Tags + ITermController termController = Util.GetTermController(); + termController.RemoveTermsFromContent(module); + foreach (Term _Term in module.Terms) + { + termController.AddTermToContent(_Term, module); + } + + var eventLogController = new EventLogController(); + eventLogController.AddLog(module, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.MODULE_UPDATED); + + //save module permissions + ModulePermissionController.SaveModulePermissions(module); + UpdateModuleSettings(module); + module.VersionGuid = Guid.NewGuid(); + module.LocalizedVersionGuid = Guid.NewGuid(); + + if (!Null.IsNull(module.TabID)) + { + //update tabmodule + dataProvider.UpdateTabModule(module.TabModuleID, + module.TabID, + module.ModuleID, + module.ModuleTitle, + module.Header, + module.Footer, + module.ModuleOrder, + module.PaneName, + module.CacheTime, + module.CacheMethod, + module.Alignment, + module.Color, + module.Border, + module.IconFile, + (int)module.Visibility, + module.ContainerSrc, + module.DisplayTitle, + module.DisplayPrint, + module.DisplaySyndicate, + module.IsWebSlice, + module.WebSliceTitle, + module.WebSliceExpiryDate, + module.WebSliceTTL, + module.VersionGuid, + module.DefaultLanguageGuid, + module.LocalizedVersionGuid, + module.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + eventLogController.AddLog(module, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.TABMODULE_UPDATED); + + //update module order in pane + UpdateModuleOrder(module.TabID, module.ModuleID, module.ModuleOrder, module.PaneName); + + //set the default module + if (PortalSettings.Current != null) + { + if (module.IsDefaultModule) + { + if (module.ModuleID != PortalSettings.Current.DefaultModuleId) + { + //Update Setting + PortalController.UpdatePortalSetting(module.PortalID, "defaultmoduleid", module.ModuleID.ToString()); + } + if (module.TabID != PortalSettings.Current.DefaultTabId) + { + //Update Setting + PortalController.UpdatePortalSetting(module.PortalID, "defaulttabid", module.TabID.ToString()); + } + } + else + { + if (module.ModuleID == PortalSettings.Current.DefaultModuleId && module.TabID == PortalSettings.Current.DefaultTabId) + { + //Clear setting + PortalController.DeletePortalSetting(module.PortalID, "defaultmoduleid"); + PortalController.DeletePortalSetting(module.PortalID, "defaulttabid"); + } + } + } + //apply settings to all desktop modules in portal + if (module.AllModules) + { + var tabController = new TabController(); + foreach (KeyValuePair tabPair in tabController.GetTabsByPortal(module.PortalID)) + { + TabInfo tab = tabPair.Value; + foreach (KeyValuePair modulePair in GetTabModules(tab.TabID)) + { + var targetModule = modulePair.Value; + targetModule.VersionGuid = Guid.NewGuid(); + targetModule.LocalizedVersionGuid = Guid.NewGuid(); + + dataProvider.UpdateTabModule(targetModule.TabModuleID, + targetModule.TabID, + targetModule.ModuleID, + targetModule.ModuleTitle, + targetModule.Header, + targetModule.Footer, + targetModule.ModuleOrder, + targetModule.PaneName, + targetModule.CacheTime, + targetModule.CacheMethod, + module.Alignment, + module.Color, + module.Border, + module.IconFile, + (int)module.Visibility, + module.ContainerSrc, + module.DisplayTitle, + module.DisplayPrint, + module.DisplaySyndicate, + module.IsWebSlice, + module.WebSliceTitle, + module.WebSliceExpiryDate, + module.WebSliceTTL, + targetModule.VersionGuid, + targetModule.DefaultLanguageGuid, + targetModule.LocalizedVersionGuid, + targetModule.CultureCode, + UserController.GetCurrentUserInfo().UserID); + + ClearCache(targetModule.TabID); + } + } + } + } + //Clear Cache for all TabModules + foreach (ModuleInfo tabModule in GetModuleTabs(module.ModuleID)) + { + ClearCache(tabModule.TabID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// set/change the module position within a pane on a page + /// + /// ID of the page + /// ID of the module on the page + /// position within the controls list on page, -1 if to be added at the end + /// name of the pane, the module is placed in on the page + /// + /// [sleupold] 2007-09-24 commented + /// + /// ----------------------------------------------------------------------------- + public void UpdateModuleOrder(int TabId, int ModuleId, int ModuleOrder, string PaneName) + { + ModuleInfo objModule = GetModule(ModuleId, TabId, false); + if (objModule != null) + { + //adding a module to a new pane - places the module at the bottom of the pane + if (ModuleOrder == -1) + { + IDataReader dr = null; + try + { + dr = dataProvider.GetTabModuleOrder(TabId, PaneName); + while (dr.Read()) + { + ModuleOrder = Convert.ToInt32(dr["ModuleOrder"]); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + ModuleOrder += 2; + } + dataProvider.UpdateModuleOrder(TabId, ModuleId, ModuleOrder, PaneName); + + //clear cache + ClearCache(TabId); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// set/change all module's positions within a page + /// + /// ID of the page + /// + /// [sleupold] 2007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added update tabmodule version guid + /// + /// ----------------------------------------------------------------------------- + public void UpdateTabModuleOrder(int TabId) + { + IDataReader dr = dataProvider.GetTabPanes(TabId); + try + { + while (dr.Read()) + { + int moduleCounter = 0; + IDataReader dr2 = dataProvider.GetTabModuleOrder(TabId, Convert.ToString(dr["PaneName"])); + try + { + while (dr2.Read()) + { + moduleCounter += 1; + dataProvider.UpdateModuleOrder(TabId, Convert.ToInt32(dr2["ModuleID"]), (moduleCounter * 2) - 1, Convert.ToString(dr["PaneName"])); + } + } + catch (Exception ex2) + { + Exceptions.LogException(ex2); + } + finally + { + CBO.CloseDataReader(dr2, true); + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + //clear module cache + ClearCache(TabId); + } + + /// + /// Updates the translation status. + /// + /// The localized module. + /// if set to true will mark the module as translated]. + public void UpdateTranslationStatus(ModuleInfo localizedModule, bool isTranslated) + { + if (isTranslated && (localizedModule.DefaultLanguageModule != null)) + { + localizedModule.LocalizedVersionGuid = localizedModule.DefaultLanguageModule.LocalizedVersionGuid; + } + else + { + localizedModule.LocalizedVersionGuid = Guid.NewGuid(); + } + DataProvider.Instance().UpdateTabModuleTranslationStatus(localizedModule.TabModuleID, localizedModule.LocalizedVersionGuid, UserController.GetCurrentUserInfo().UserID); + + //Clear Tab Caches + ClearCache(localizedModule.TabID); + } + + #region ModuleSettings Methods + + /// + /// Delete a Setting of a module instance + /// + /// ID of the affected module + /// Name of the setting to be deleted + /// + /// [sleupold] 2007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added update tab module version + /// + public void DeleteModuleSetting(int ModuleId, string SettingName) + { + dataProvider.DeleteModuleSetting(ModuleId, SettingName); + var eventLogController = new EventLogController(); + var logInfo = new LogInfo(); + logInfo.LogProperties.Add(new LogDetailInfo("ModuleId", ModuleId.ToString())); + logInfo.LogProperties.Add(new LogDetailInfo("SettingName", SettingName)); + logInfo.LogTypeKey = EventLogController.EventLogType.MODULE_SETTING_DELETED.ToString(); + eventLogController.AddLog(logInfo); + UpdateTabModuleVersionsByModuleID(ModuleId); + DataCache.RemoveCache("GetModuleSettings" + ModuleId); + } + + /// + /// Delete all Settings of a module instance + /// + /// ID of the affected module + /// + /// [sleupold] 2007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added update tab module version + /// + public void DeleteModuleSettings(int ModuleId) + { + dataProvider.DeleteModuleSettings(ModuleId); + var eventLogController = new EventLogController(); + var logInfo = new LogInfo(); + logInfo.LogProperties.Add(new LogDetailInfo("ModuleId", ModuleId.ToString())); + logInfo.LogTypeKey = EventLogController.EventLogType.MODULE_SETTING_DELETED.ToString(); + eventLogController.AddLog(logInfo); + UpdateTabModuleVersionsByModuleID(ModuleId); + DataCache.RemoveCache("GetModuleSettings" + ModuleId); + } + + /// + /// read all settings for a module from ModuleSettings table + /// + /// ID of the module + /// (cached) hashtable containing all settings + /// TabModuleSettings are not included + /// + /// [sleupold] 2007-09-24 commented + /// + public Hashtable GetModuleSettings(int ModuleId) + { + string strCacheKey = "GetModuleSettings" + ModuleId; + var settings = (Hashtable)DataCache.GetCache(strCacheKey); + if (settings == null) + { + settings = new Hashtable(); + IDataReader dr = null; + try + { + dr = dataProvider.GetModuleSettings(ModuleId); + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + settings[dr.GetString(0)] = dr.GetString(1); + } + else + { + settings[dr.GetString(0)] = string.Empty; + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + //Ensure DataReader is closed + CBO.CloseDataReader(dr, true); + } + //cache data + int intCacheTimeout = 20 * Convert.ToInt32(Host.Host.PerformanceSetting); + DataCache.SetCache(strCacheKey, settings, TimeSpan.FromMinutes(intCacheTimeout)); + } + return settings; + } + + /// + /// Adds or updates a module's setting value + /// + /// ID of the module, the setting belongs to + /// name of the setting property + /// value of the setting (String). + /// empty SettingValue will remove the setting, if not preserveIfEmpty is true + /// + /// [sleupold] 2007-09-24 added removal for empty settings + /// [vnguyen] 2010-05-10 Modified: Added update tab module version + /// + public void UpdateModuleSetting(int ModuleId, string SettingName, string SettingValue) + { + UpdateModuleSettingInternal(ModuleId, SettingName, SettingValue, true); + } + + #endregion + + #region TabModuleSettings Methods + + /// + /// Delete a specific setting of a tabmodule reference + /// + /// ID of the affected tabmodule + /// Name of the setting to remove + /// + /// [sleupold] 2007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added update tabmodule version guid + /// + public void DeleteTabModuleSetting(int TabModuleId, string SettingName) + { + dataProvider.DeleteTabModuleSetting(TabModuleId, SettingName); + UpdateTabModuleVersion(TabModuleId); + var eventLogController = new EventLogController(); + var logInfo = new LogInfo(); + logInfo.LogProperties.Add(new LogDetailInfo("TabModuleId", TabModuleId.ToString())); + logInfo.LogProperties.Add(new LogDetailInfo("SettingName", SettingName)); + logInfo.LogTypeKey = EventLogController.EventLogType.TABMODULE_SETTING_DELETED.ToString(); + eventLogController.AddLog(logInfo); + DataCache.RemoveCache("GetTabModuleSettings" + TabModuleId); + } + + /// + /// Delete all settings of a tabmodule reference + /// + /// ID of the affected tabmodule + /// + /// [sleupold] 2007-09-24 documented + /// [vnguyen] 2010-05-10 Modified: Added update module version guid + /// + public void DeleteTabModuleSettings(int TabModuleId) + { + dataProvider.DeleteTabModuleSettings(TabModuleId); + UpdateTabModuleVersion(TabModuleId); + var eventLog = new EventLogController(); + eventLog.AddLog("TabModuleID", + TabModuleId.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.TABMODULE_SETTING_DELETED); + DataCache.RemoveCache("GetTabModuleSettings" + TabModuleId); + } + + /// + /// read all settings for a module on a page from TabModuleSettings Table + /// + /// ID of the tabModule + /// (cached) hashtable containing all settings + /// ModuleSettings are not included + /// + /// [sleupold] 2007-09-24 documented + /// + public Hashtable GetTabModuleSettings(int TabModuleId) + { + string cacheKey = "GetTabModuleSettings" + TabModuleId; + var settings = (Hashtable)DataCache.GetCache(cacheKey); + if (settings == null) + { + settings = new Hashtable(); + IDataReader dr = null; + try + { + dr = dataProvider.GetTabModuleSettings(TabModuleId); + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + settings[dr.GetString(0)] = dr.GetString(1); + } + else + { + settings[dr.GetString(0)] = string.Empty; + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + int intCacheTimeout = 20 * Convert.ToInt32(Host.Host.PerformanceSetting); + DataCache.SetCache(cacheKey, settings, TimeSpan.FromMinutes(intCacheTimeout)); + } + return settings; + } + + /// + /// Adds or updates a module's setting value + /// + /// ID of the tabmodule, the setting belongs to + /// name of the setting property + /// value of the setting (String). + /// empty SettingValue will relove the setting + /// + /// [sleupold] 2007-09-24 added removal for empty settings + /// [vnguyen] 2010-05-10 Modified: Added update tabmodule version guid + /// + public void UpdateTabModuleSetting(int tabModuleId, string settingName, string settingValue) + { + IDataReader dr = null; + try + { + dr = dataProvider.GetTabModuleSetting(tabModuleId, settingName); + if (dr.Read()) + { + if(dr.GetString(1) != settingValue) + { + dataProvider.UpdateTabModuleSetting(tabModuleId, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.MODULE_SETTING_UPDATED, + "TabModuleId", tabModuleId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + } + else + { + dataProvider.AddTabModuleSetting(tabModuleId, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.TABMODULE_SETTING_CREATED, + "TabModuleId", tabModuleId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + UpdateTabModuleVersion(tabModuleId); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + //Ensure DataReader is closed + CBO.CloseDataReader(dr, true); + } + DataCache.RemoveCache("GetTabModuleSettings" + tabModuleId); + } + + #endregion + + public void InitialModulePermission(ModuleInfo module, int tabId, int permissionType) + { + var tabPermissions = TabPermissionController.GetTabPermissions(tabId, module.PortalID); + var permissionController = new PermissionController(); + + module.InheritViewPermissions = permissionType == 0; + + // get the default module view permissions + ArrayList systemModuleViewPermissions = permissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", "VIEW"); + + // get the permissions from the page + foreach (TabPermissionInfo tabPermission in tabPermissions) + { + if (tabPermission.PermissionKey == "VIEW" && permissionType == 0) + { + //Don't need to explicitly add View permisisons if "Same As Page" + continue; + } + + // get the system module permissions for the permissionkey + ArrayList systemModulePermissions = permissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", tabPermission.PermissionKey); + // loop through the system module permissions + int j; + for (j = 0; j <= systemModulePermissions.Count - 1; j++) + { + // create the module permission + var systemModulePermission = (PermissionInfo) systemModulePermissions[j]; + if (systemModulePermission.PermissionKey == "VIEW" && permissionType == 1 && tabPermission.PermissionKey != "EDIT") + { + //Only Page Editors get View permissions if "Page Editors Only" + continue; + } + + ModulePermissionInfo modulePermission = AddModulePermission(module, systemModulePermission, tabPermission.RoleID, tabPermission.UserID, tabPermission.AllowAccess); + + // ensure that every EDIT permission which allows access also provides VIEW permission + if (modulePermission.PermissionKey == "EDIT" && modulePermission.AllowAccess) + { + AddModulePermission(module, (PermissionInfo) systemModuleViewPermissions[0], modulePermission.RoleID, modulePermission.UserID, true); + } + } + + //Get the custom Module Permissions, Assume that roles with Edit Tab Permissions + //are automatically assigned to the Custom Module Permissions + if (tabPermission.PermissionKey == "EDIT") + { + ArrayList customModulePermissions = permissionController.GetPermissionsByModuleDefID(module.ModuleDefID); + + // loop through the custom module permissions + for (j = 0; j <= customModulePermissions.Count - 1; j++) + { + // create the module permission + var customModulePermission = (PermissionInfo)customModulePermissions[j]; + + AddModulePermission(module, customModulePermission, tabPermission.RoleID, tabPermission.UserID, tabPermission.AllowAccess); + } + } + } + } + + #endregion + + #region Obsolete Methods + [Obsolete("The module caching feature has been updated in version 5.2.0. This method is no longer used.")] + public static string CacheDirectory() + { + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache"; + } + + [Obsolete("The module caching feature has been updated in version 5.2.0. This method is no longer used.")] + public static string CacheFileName(int TabModuleID) + { + string strCacheKey = "TabModule:"; + strCacheKey += TabModuleID + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache" + "\\" + Globals.CleanFileName(strCacheKey) + ".resources"; + } + + [Obsolete("The module caching feature has been updated in version 5.2.0. This method is no longer used.")] + public static string CacheKey(int TabModuleID) + { + string strCacheKey = "TabModule:"; + strCacheKey += TabModuleID + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return strCacheKey; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by CopyModule(ModuleInfo, TabInfo, String, Boolean)")] + public void CopyModule(int moduleId, int fromTabId, List toTabs, bool includeSettings) + { + ModuleInfo objModule = GetModule(moduleId, fromTabId, false); + //Iterate through collection copying the module to each Tab (except the source) + foreach (TabInfo objTab in toTabs) + { + if (objTab.TabID != fromTabId) + { + CopyModule(objModule, objTab, "", includeSettings); + } + } + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by CopyModule(ModuleInfo, TabInfo, String, Boolean)")] + public void CopyModule(int moduleId, int fromTabId, int toTabId, string toPaneName, bool includeSettings) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + ModuleInfo objModule = GetModule(moduleId, fromTabId, false); + TabInfo objTab = new TabController().GetTab(toTabId, _portalSettings.PortalId, false); + CopyModule(objModule, objTab, toPaneName, includeSettings); + } + + [Obsolete("Replaced in DotNetNuke 5.0 by CopyModule(Integer, integer, List(Of TabInfo), Boolean)")] + public void CopyModule(int moduleId, int fromTabId, ArrayList toTabs, bool includeSettings) + { + ModuleInfo objModule = GetModule(moduleId, fromTabId, false); + //Iterate through collection copying the module to each Tab (except the source) + foreach (TabInfo objTab in toTabs) + { + if (objTab.TabID != fromTabId) + { + CopyModule(objModule, objTab, "", includeSettings); + } + } + } + + [Obsolete("Deprectaed in DNN 5.1. Replaced By DeleteAllModules(Integer,Integer, List(Of TabInfo), Boolean, Boolean, Boolean)")] + public void DeleteAllModules(int moduleId, int tabId, List fromTabs, bool includeCurrent, bool deleteBaseModule) + { + DeleteAllModules(moduleId, tabId, fromTabs, true, includeCurrent, deleteBaseModule); + } + + [Obsolete("Replaced in DotNetNuke 5.0 by DeleteAllModules(Integer, integer, List(Of TabInfo), Boolean, boolean)")] + public void DeleteAllModules(int moduleId, int tabId, ArrayList fromTabs, bool includeCurrent, bool deleteBaseModule) + { + var listTabs = fromTabs.Cast().ToList(); + DeleteAllModules(moduleId, tabId, listTabs, true, includeCurrent, deleteBaseModule); + } + + [Obsolete("Deprectaed in DNN 5.1. Replaced by DeleteTabModule(Integer, integer, boolean)")] + public void DeleteTabModule(int tabId, int moduleId) + { + DeleteTabModule(tabId, moduleId, true); + } + + [Obsolete("Replaced in DotNetNuke 5.0 by GetTabModules(Integer)")] + public ArrayList GetPortalTabModules(int portalID, int tabID) + { + var arr = new ArrayList(); + foreach (KeyValuePair kvp in GetTabModules(tabID)) + { + arr.Add(kvp.Value); + } + return arr; + } + + [Obsolete("Replaced in DotNetNuke 5.0 by GetModules(Integer)")] + public ArrayList GetModules(int portalID, bool includePermissions) + { + return CBO.FillCollection(dataProvider.GetModules(portalID), typeof(ModuleInfo)); + } + + [Obsolete("Replaced in DotNetNuke 5.0 by UpdateTabModuleOrder(Integer)")] + public void UpdateTabModuleOrder(int tabId, int portalId) + { + UpdateTabModuleOrder(tabId); + } + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ModuleInfo.cs b/DNN Platform/Library/Entities/Modules/ModuleInfo.cs new file mode 100644 index 00000000000..ecd0e9dcfe0 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleInfo.cs @@ -0,0 +1,1444 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.ModuleCache; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ModuleInfo + /// ----------------------------------------------------------------------------- + /// + /// ModuleInfo provides the Entity Layer for Modules + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlRoot("module", IsNullable = false)] + [Serializable] + public class ModuleInfo : ContentItem, IPropertyAccess + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModuleInfo)); + private string _authorizedEditRoles; + private string _authorizedViewRoles; + private string _cultureCode; + private Guid _defaultLanguageGuid; + private ModuleInfo _defaultLanguageModule; + private DesktopModuleInfo _desktopModule; + private Dictionary _localizedModules; + private Guid _localizedVersionGuid; + private ModuleControlInfo _moduleControl; + private ModuleDefinitionInfo _moduleDefinition; + private ModulePermissionCollection _modulePermissions; + private Hashtable _moduleSettings; + private TabInfo _parentTab; + private Hashtable _tabModuleSettings; + private TabPermissionCollection _tabPermissions; + + public ModuleInfo() + { + //initialize the properties that can be null + //in the database + PortalID = Null.NullInteger; + OwnerPortalID = Null.NullInteger; + TabModuleID = Null.NullInteger; + DesktopModuleID = Null.NullInteger; + ModuleDefID = Null.NullInteger; + ModuleTitle = Null.NullString; + _authorizedEditRoles = Null.NullString; + _authorizedViewRoles = Null.NullString; + Alignment = Null.NullString; + Color = Null.NullString; + Border = Null.NullString; + IconFile = Null.NullString; + Header = Null.NullString; + Footer = Null.NullString; + StartDate = Null.NullDate; + EndDate = Null.NullDate; + ContainerSrc = Null.NullString; + DisplayTitle = true; + DisplayPrint = true; + DisplaySyndicate = false; + + //Guid, Version Guid, and Localized Version Guid should be initialised to a new value + UniqueId = Guid.NewGuid(); + VersionGuid = Guid.NewGuid(); + _localizedVersionGuid = Guid.NewGuid(); + + //Default Language Guid should be initialised to a null Guid + _defaultLanguageGuid = Null.NullGuid; + } + + [XmlElement("alignment")] + public string Alignment { get; set; } + + [XmlIgnore] + public bool AllModules { get; set; } + + [XmlElement("alltabs")] + public bool AllTabs { get; set; } + + [XmlElement("border")] + public string Border { get; set; } + + [XmlElement("cachemethod")] + public string CacheMethod { get; set; } + + [XmlElement("cachetime")] + public int CacheTime { get; set; } + + [XmlElement("color")] + public string Color { get; set; } + + [XmlIgnore] + public string ContainerPath { get; set; } + + [XmlElement("containersrc")] + public string ContainerSrc { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Associated Desktop Module + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public DesktopModuleInfo DesktopModule + { + get { + return _desktopModule ?? + (_desktopModule = DesktopModuleID > Null.NullInteger + ? DesktopModuleController.GetDesktopModule(DesktopModuleID, PortalID) + : new DesktopModuleInfo()); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ID of the Associated Desktop Module + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int DesktopModuleID { get; set; } + + [XmlElement("displayprint")] + public bool DisplayPrint { get; set; } + + [XmlElement("displaysyndicate")] + public bool DisplaySyndicate { get; set; } + + [XmlElement("displaytitle")] + public bool DisplayTitle { get; set; } + + [XmlElement("enddate")] + public DateTime EndDate { get; set; } + + [XmlElement("footer")] + public string Footer { get; set; } + + [XmlElement("header")] + public string Header { get; set; } + + [XmlIgnore] + public bool HideAdminBorder + { + get + { + object setting = TabModuleSettings["hideadminborder"]; + if (setting == null || string.IsNullOrEmpty(setting.ToString())) + { + return false; + } + + bool val; + Boolean.TryParse(setting.ToString(), out val); + return val; + } + } + + [XmlElement("iconfile")] + public string IconFile { get; set; } + + [XmlElement("inheritviewpermissions")] + public bool InheritViewPermissions { get; set; } + + [XmlIgnore] + public bool IsDefaultModule { get; set; } + + [XmlElement("isdeleted")] + public bool IsDeleted { get; set; } + + [XmlIgnore] + public bool IsShareable { get; set; } + + [XmlIgnore] + public bool IsShared + { + get { return OwnerPortalID != PortalID; } + } + + [XmlIgnore] + public bool IsShareableViewOnly { get; set; } + + [XmlElement("iswebslice")] + public bool IsWebSlice { get; set; } + + [XmlIgnore] + public DateTime LastContentModifiedOnDate { get; set; } + + public ModuleControlInfo ModuleControl + { + get { + return _moduleControl ?? + (_moduleControl = ModuleControlId > Null.NullInteger + ? ModuleControlController.GetModuleControl(ModuleControlId) + : new ModuleControlInfo()); + } + } + + [XmlIgnore] + public int ModuleControlId { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ID of the Associated Module Definition + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int ModuleDefID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Associated Module Definition + /// + /// A ModuleDefinitionInfo + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public ModuleDefinitionInfo ModuleDefinition + { + get { + return _moduleDefinition ?? + (_moduleDefinition = ModuleDefID > Null.NullInteger + ? ModuleDefinitionController.GetModuleDefinitionByID(ModuleDefID) + : new ModuleDefinitionInfo()); + } + } + + [XmlElement("moduleorder")] + public int ModuleOrder { get; set; } + + /// + /// Get the ModulePermissions for the Module DO NOT USE THE SETTTER + /// + /// Since 5.0 the setter has been obsolete, directly setting the ModulePermissionCollection is likely an error, change the contenst of the collection instead. + /// The setter still exists to preserve binary compatibility without the obsolete attribute since c# will not allow only a setter to be obsolete. + /// + /// + [XmlArray("modulepermissions"), XmlArrayItem("permission")] + public ModulePermissionCollection ModulePermissions + { + get + { + return _modulePermissions ?? + (_modulePermissions = ModuleID > 0 + ? new ModulePermissionCollection(ModulePermissionController.GetModulePermissions(ModuleID, TabID)) + : new ModulePermissionCollection()); + } + set + { + _modulePermissions = value; + } + } + + [XmlIgnore] + public Hashtable ModuleSettings + { + get + { + if (_moduleSettings == null) + { + if (ModuleID == Null.NullInteger) + { + _moduleSettings = new Hashtable(); + } + else + { + var oModuleCtrl = new ModuleController(); + _moduleSettings = oModuleCtrl.GetModuleSettings(ModuleID); + } + } + return _moduleSettings; + } + } + + [XmlElement("title")] + public string ModuleTitle { get; set; } + + [XmlIgnore] + public int OwnerPortalID { get; set; } + + [XmlIgnore] + public int PaneModuleCount { get; set; } + + [XmlIgnore] + public int PaneModuleIndex { get; set; } + + [XmlElement("panename")] + public string PaneName { get; set; } + + [XmlElement("portalid")] + public int PortalID { get; set; } + + [XmlElement("startdate")] + public DateTime StartDate { get; set; } + + [XmlElement("tabmoduleid")] + public int TabModuleID { get; set; } + + [XmlIgnore] + public Hashtable TabModuleSettings + { + get + { + if (_tabModuleSettings == null) + { + if (TabModuleID == Null.NullInteger) + { + _tabModuleSettings = new Hashtable(); + } + else + { + var oModuleCtrl = new ModuleController(); + _tabModuleSettings = oModuleCtrl.GetTabModuleSettings(TabModuleID); + } + } + return _tabModuleSettings; + } + } + + [XmlElement("uniqueId")] + public Guid UniqueId { get; set; } + + [XmlElement("versionGuid")] + public Guid VersionGuid { get; set; } + + [XmlElement("visibility")] + public VisibilityState Visibility { get; set; } + + [XmlElement("websliceexpirydate")] + public DateTime WebSliceExpiryDate { get; set; } + + [XmlElement("webslicetitle")] + public string WebSliceTitle { get; set; } + + [XmlElement("webslicettl")] + public int WebSliceTTL { get; set; } + + #region Localization Properties + + [XmlElement("cultureCode")] + public string CultureCode + { + get + { + return _cultureCode; + } + set + { + _cultureCode = value; + } + } + + [XmlElement("defaultLanguageGuid")] + public Guid DefaultLanguageGuid + { + get + { + return _defaultLanguageGuid; + } + set + { + _defaultLanguageGuid = value; + } + } + + [XmlIgnore] + public ModuleInfo DefaultLanguageModule + { + get + { + if (_defaultLanguageModule == null && (!DefaultLanguageGuid.Equals(Null.NullGuid)) && ParentTab != null && ParentTab.DefaultLanguageTab != null && + ParentTab.DefaultLanguageTab.ChildModules != null) + { + _defaultLanguageModule = (from kvp in ParentTab.DefaultLanguageTab.ChildModules where kvp.Value.UniqueId == DefaultLanguageGuid select kvp.Value).SingleOrDefault(); + } + return _defaultLanguageModule; + } + } + + public bool IsDefaultLanguage + { + get + { + return (DefaultLanguageGuid == Null.NullGuid); + } + } + + public bool IsLocalized + { + get + { + bool isLocalized = true; + if (DefaultLanguageModule != null) + { + //Child language + isLocalized = ModuleID != DefaultLanguageModule.ModuleID; + } + return isLocalized; + } + } + + public bool IsNeutralCulture + { + get + { + return string.IsNullOrEmpty(CultureCode); + } + } + + [XmlIgnore] + public bool IsTranslated + { + get + { + bool isTranslated = true; + if (DefaultLanguageModule != null) + { + //Child language + isTranslated = (LocalizedVersionGuid == DefaultLanguageModule.LocalizedVersionGuid); + } + return isTranslated; + } + } + + [XmlIgnore] + public Dictionary LocalizedModules + { + get + { + if (_localizedModules == null && (DefaultLanguageGuid.Equals(Null.NullGuid)) && ParentTab != null && ParentTab.LocalizedTabs != null) + { + //Cycle through all localized tabs looking for this module + _localizedModules = new Dictionary(); + foreach (TabInfo t in ParentTab.LocalizedTabs.Values) + { + foreach (ModuleInfo m in t.ChildModules.Values) + { + ModuleInfo tempModuleInfo; + if (m.DefaultLanguageGuid == UniqueId && !m.IsDeleted && !_localizedModules.TryGetValue(m.CultureCode, out tempModuleInfo)) + { + _localizedModules.Add(m.CultureCode, m); + } + } + } + } + return _localizedModules; + } + } + + [XmlElement("localizedVersionGuid")] + public Guid LocalizedVersionGuid + { + get + { + return _localizedVersionGuid; + } + set + { + _localizedVersionGuid = value; + } + } + + #endregion + + #region Tab Properties + + public TabInfo ParentTab + { + get + { + if (_parentTab == null) + { + var tabCtrl = new TabController(); + if (PortalID == Null.NullInteger || string.IsNullOrEmpty(CultureCode)) + { + _parentTab = tabCtrl.GetTab(TabID, PortalID, false); + } + else + { + Locale locale = LocaleController.Instance.GetLocale(CultureCode); + _parentTab = tabCtrl.GetTabByCulture(TabID, PortalID, locale); + } + } + return _parentTab; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ModuleInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public override void Fill(IDataReader dr) + { + //Call the base classes fill method to populate base class properties + base.FillInternal(dr); + + UniqueId = Null.SetNullGuid(dr["UniqueId"]); + VersionGuid = Null.SetNullGuid(dr["VersionGuid"]); + DefaultLanguageGuid = Null.SetNullGuid(dr["DefaultLanguageGuid"]); + LocalizedVersionGuid = Null.SetNullGuid(dr["LocalizedVersionGuid"]); + CultureCode = Null.SetNullString(dr["CultureCode"]); + + PortalID = Null.SetNullInteger(dr["PortalID"]); + if (dr.GetSchemaTable().Select("ColumnName = 'OwnerPortalID'").Length > 0) + { + OwnerPortalID = Null.SetNullInteger(dr["OwnerPortalID"]); + } + + ModuleDefID = Null.SetNullInteger(dr["ModuleDefID"]); + ModuleTitle = Null.SetNullString(dr["ModuleTitle"]); + AllTabs = Null.SetNullBoolean(dr["AllTabs"]); + IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]); + InheritViewPermissions = Null.SetNullBoolean(dr["InheritViewPermissions"]); + + if (dr.GetSchemaTable().Select("ColumnName = 'IsShareable'").Length > 0) + { + IsShareable = Null.SetNullBoolean(dr["IsShareable"]); + } + + if (dr.GetSchemaTable().Select("ColumnName = 'IsShareableViewOnly'").Length > 0) + { + IsShareableViewOnly = Null.SetNullBoolean(dr["IsShareableViewOnly"]); + } + + Header = Null.SetNullString(dr["Header"]); + Footer = Null.SetNullString(dr["Footer"]); + StartDate = Null.SetNullDateTime(dr["StartDate"]); + EndDate = Null.SetNullDateTime(dr["EndDate"]); + LastContentModifiedOnDate = Null.SetNullDateTime(dr["LastContentModifiedOnDate"]); + try + { + TabModuleID = Null.SetNullInteger(dr["TabModuleID"]); + ModuleOrder = Null.SetNullInteger(dr["ModuleOrder"]); + PaneName = Null.SetNullString(dr["PaneName"]); + CacheTime = Null.SetNullInteger(dr["CacheTime"]); + CacheMethod = Null.SetNullString(dr["CacheMethod"]); + Alignment = Null.SetNullString(dr["Alignment"]); + Color = Null.SetNullString(dr["Color"]); + Border = Null.SetNullString(dr["Border"]); + IconFile = Null.SetNullString(dr["IconFile"]); + int visible = Null.SetNullInteger(dr["Visibility"]); + if (visible == Null.NullInteger) + { + Visibility = VisibilityState.Maximized; + } + else + { + switch (visible) + { + case 0: + Visibility = VisibilityState.Maximized; + break; + case 1: + Visibility = VisibilityState.Minimized; + break; + case 2: + Visibility = VisibilityState.None; + break; + } + } + ContainerSrc = Null.SetNullString(dr["ContainerSrc"]); + DisplayTitle = Null.SetNullBoolean(dr["DisplayTitle"]); + DisplayPrint = Null.SetNullBoolean(dr["DisplayPrint"]); + DisplaySyndicate = Null.SetNullBoolean(dr["DisplaySyndicate"]); + IsWebSlice = Null.SetNullBoolean(dr["IsWebSlice"]); + if (IsWebSlice) + { + WebSliceTitle = Null.SetNullString(dr["WebSliceTitle"]); + WebSliceExpiryDate = Null.SetNullDateTime(dr["WebSliceExpiryDate"]); + WebSliceTTL = Null.SetNullInteger(dr["WebSliceTTL"]); + } + DesktopModuleID = Null.SetNullInteger(dr["DesktopModuleID"]); + ModuleControlId = Null.SetNullInteger(dr["ModuleControlID"]); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public override int KeyID + { + get + { + return ModuleID; + } + set + { + ModuleID = value; + } + } + + #endregion + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope currentScope, ref bool propertyNotFound) + { + string outputFormat = string.Empty; + if (format == string.Empty) + { + outputFormat = "g"; + } + if (currentScope == Scope.NoSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + propertyNotFound = true; + string result = string.Empty; + bool isPublic = true; + switch (propertyName.ToLower()) + { + case "portalid": + propertyNotFound = false; + result = (PortalID.ToString(outputFormat, formatProvider)); + break; + case "displayportalid": + propertyNotFound = false; + result = (OwnerPortalID.ToString(outputFormat, formatProvider)); + break; + case "tabid": + propertyNotFound = false; + result = (TabID.ToString(outputFormat, formatProvider)); + break; + case "tabmoduleid": + propertyNotFound = false; + result = (TabModuleID.ToString(outputFormat, formatProvider)); + break; + case "moduleid": + propertyNotFound = false; + result = (ModuleID.ToString(outputFormat, formatProvider)); + break; + case "moduledefid": + isPublic = false; + propertyNotFound = false; + result = (ModuleDefID.ToString(outputFormat, formatProvider)); + break; + case "moduleorder": + isPublic = false; + propertyNotFound = false; + result = (ModuleOrder.ToString(outputFormat, formatProvider)); + break; + case "panename": + propertyNotFound = false; + result = PropertyAccess.FormatString(PaneName, format); + break; + case "moduletitle": + propertyNotFound = false; + result = PropertyAccess.FormatString(ModuleTitle, format); + break; + case "cachetime": + isPublic = false; + propertyNotFound = false; + result = (CacheTime.ToString(outputFormat, formatProvider)); + break; + case "cachemethod": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(CacheMethod, format); + break; + case "alignment": + propertyNotFound = false; + result = PropertyAccess.FormatString(Alignment, format); + break; + case "color": + propertyNotFound = false; + result = PropertyAccess.FormatString(Color, format); + break; + case "border": + propertyNotFound = false; + result = PropertyAccess.FormatString(Border, format); + break; + case "iconfile": + propertyNotFound = false; + result = PropertyAccess.FormatString(IconFile, format); + break; + case "alltabs": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(AllTabs, formatProvider)); + break; + case "isdeleted": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsDeleted, formatProvider)); + break; + case "header": + propertyNotFound = false; + result = PropertyAccess.FormatString(Header, format); + break; + case "footer": + propertyNotFound = false; + result = PropertyAccess.FormatString(Footer, format); + break; + case "startdate": + isPublic = false; + propertyNotFound = false; + result = (StartDate.ToString(outputFormat, formatProvider)); + break; + case "enddate": + isPublic = false; + propertyNotFound = false; + result = (EndDate.ToString(outputFormat, formatProvider)); + break; + case "containersrc": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(ContainerSrc, format); + break; + case "displaytitle": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DisplayTitle, formatProvider)); + break; + case "displayprint": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DisplayPrint, formatProvider)); + break; + case "displaysyndicate": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DisplaySyndicate, formatProvider)); + break; + case "iswebslice": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsWebSlice, formatProvider)); + break; + case "webslicetitle": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(WebSliceTitle, format); + break; + case "websliceexpirydate": + isPublic = false; + propertyNotFound = false; + result = (WebSliceExpiryDate.ToString(outputFormat, formatProvider)); + break; + case "webslicettl": + isPublic = false; + propertyNotFound = false; + result = (WebSliceTTL.ToString(outputFormat, formatProvider)); + break; + case "inheritviewpermissions": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(InheritViewPermissions, formatProvider)); + break; + case "isshareable": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsShareable, formatProvider)); + break; + case "isshareableviewonly": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsShareableViewOnly, formatProvider)); + break; + case "desktopmoduleid": + isPublic = false; + propertyNotFound = false; + result = (DesktopModuleID.ToString(outputFormat, formatProvider)); + break; + case "friendlyname": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.FriendlyName, format); + break; + case "foldername": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.FolderName, format); + break; + case "description": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.Description, format); + break; + case "version": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.Version, format); + break; + case "ispremium": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DesktopModule.IsPremium, formatProvider)); + break; + case "isadmin": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DesktopModule.IsAdmin, formatProvider)); + break; + case "businesscontrollerclass": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.BusinessControllerClass, format); + break; + case "modulename": + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.ModuleName, format); + break; + case "supportedfeatures": + isPublic = false; + propertyNotFound = false; + result = (DesktopModule.SupportedFeatures.ToString(outputFormat, formatProvider)); + break; + case "compatibleversions": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.CompatibleVersions, format); + break; + case "dependencies": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.Dependencies, format); + break; + case "permissions": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(DesktopModule.Permissions, format); + break; + case "defaultcachetime": + isPublic = false; + propertyNotFound = false; + result = (ModuleDefinition.DefaultCacheTime.ToString(outputFormat, formatProvider)); + break; + case "modulecontrolid": + isPublic = false; + propertyNotFound = false; + result = (ModuleControlId.ToString(outputFormat, formatProvider)); + break; + case "controlsrc": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(ModuleControl.ControlSrc, format); + break; + case "controltitle": + propertyNotFound = false; + result = PropertyAccess.FormatString(ModuleControl.ControlTitle, format); + break; + case "helpurl": + propertyNotFound = false; + result = PropertyAccess.FormatString(ModuleControl.HelpURL, format); + break; + case "supportspartialrendering": + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(ModuleControl.SupportsPartialRendering, formatProvider)); + break; + case "containerpath": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(ContainerPath, format); + break; + case "panemoduleindex": + isPublic = false; + propertyNotFound = false; + result = (PaneModuleIndex.ToString(outputFormat, formatProvider)); + break; + case "panemodulecount": + isPublic = false; + propertyNotFound = false; + result = (PaneModuleCount.ToString(outputFormat, formatProvider)); + break; + case "isdefaultmodule": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsDefaultModule, formatProvider)); + break; + case "allmodules": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(AllModules, formatProvider)); + break; + case "isportable": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DesktopModule.IsPortable, formatProvider)); + break; + case "issearchable": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DesktopModule.IsSearchable, formatProvider)); + break; + case "isupgradeable": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DesktopModule.IsUpgradeable, formatProvider)); + break; + } + if (!isPublic && currentScope != Scope.Debug) + { + propertyNotFound = true; + result = PropertyAccess.ContentLocked; + } + return result; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.fullyCacheable; + } + } + + #endregion + + public ModuleInfo Clone() + { + var objModuleInfo = new ModuleInfo + { + PortalID = PortalID, + OwnerPortalID = OwnerPortalID, + TabID = TabID, + TabModuleID = TabModuleID, + ModuleID = ModuleID, + ModuleOrder = ModuleOrder, + PaneName = PaneName, + ModuleTitle = ModuleTitle, + CacheTime = CacheTime, + CacheMethod = CacheMethod, + Alignment = Alignment, + Color = Color, + Border = Border, + IconFile = IconFile, + AllTabs = AllTabs, + Visibility = Visibility, + IsDeleted = IsDeleted, + Header = Header, + Footer = Footer, + StartDate = StartDate, + EndDate = EndDate, + ContainerSrc = ContainerSrc, + DisplayTitle = DisplayTitle, + DisplayPrint = DisplayPrint, + DisplaySyndicate = DisplaySyndicate, + IsWebSlice = IsWebSlice, + WebSliceTitle = WebSliceTitle, + WebSliceExpiryDate = WebSliceExpiryDate, + WebSliceTTL = WebSliceTTL, + InheritViewPermissions = InheritViewPermissions, + IsShareable = IsShareable, + IsShareableViewOnly = IsShareableViewOnly, + DesktopModuleID = DesktopModuleID, + ModuleDefID = ModuleDefID, + ModuleControlId = ModuleControlId, + ContainerPath = ContainerPath, + PaneModuleIndex = PaneModuleIndex, + PaneModuleCount = PaneModuleCount, + IsDefaultModule = IsDefaultModule, + AllModules = AllModules, + UniqueId = Guid.NewGuid(), + VersionGuid = Guid.NewGuid(), + DefaultLanguageGuid = DefaultLanguageGuid, + LocalizedVersionGuid = LocalizedVersionGuid, + CultureCode = CultureCode + }; + + //localized properties + Clone(objModuleInfo, this); + return objModuleInfo; + } + + public string GetEffectiveCacheMethod() + { + string effectiveCacheMethod; + if (!string.IsNullOrEmpty(CacheMethod)) + { + effectiveCacheMethod = CacheMethod; + } + else if (!string.IsNullOrEmpty(Host.Host.ModuleCachingMethod)) + { + effectiveCacheMethod = Host.Host.ModuleCachingMethod; + } + else + { + var defaultModuleCache = ComponentFactory.GetComponent(); + effectiveCacheMethod = (from provider in ModuleCachingProvider.GetProviderList() where provider.Value.Equals(defaultModuleCache) select provider.Key).SingleOrDefault(); + } + if (string.IsNullOrEmpty(effectiveCacheMethod)) + { + throw new InvalidOperationException(Localization.GetString("EXCEPTION_ModuleCacheMissing")); + } + return effectiveCacheMethod; + } + + public void Initialize(int portalId) + { + PortalID = portalId; + OwnerPortalID = portalId; + ModuleDefID = Null.NullInteger; + ModuleOrder = Null.NullInteger; + PaneName = Null.NullString; + ModuleTitle = Null.NullString; + CacheTime = 0; + CacheMethod = Null.NullString; + Alignment = Null.NullString; + Color = Null.NullString; + Border = Null.NullString; + IconFile = Null.NullString; + AllTabs = Null.NullBoolean; + Visibility = VisibilityState.Maximized; + IsDeleted = Null.NullBoolean; + Header = Null.NullString; + Footer = Null.NullString; + StartDate = Null.NullDate; + EndDate = Null.NullDate; + DisplayTitle = true; + DisplayPrint = false; + DisplaySyndicate = Null.NullBoolean; + IsWebSlice = Null.NullBoolean; + WebSliceTitle = ""; + WebSliceExpiryDate = Null.NullDate; + WebSliceTTL = 0; + InheritViewPermissions = Null.NullBoolean; + IsShareable = true; + IsShareableViewOnly = true; + ContainerSrc = Null.NullString; + DesktopModuleID = Null.NullInteger; + ModuleControlId = Null.NullInteger; + ContainerPath = Null.NullString; + PaneModuleIndex = 0; + PaneModuleCount = 0; + IsDefaultModule = Null.NullBoolean; + AllModules = Null.NullBoolean; + if (PortalSettings.Current.DefaultModuleId > Null.NullInteger && PortalSettings.Current.DefaultTabId > Null.NullInteger) + { + var objModules = new ModuleController(); + ModuleInfo objModule = objModules.GetModule(PortalSettings.Current.DefaultModuleId, PortalSettings.Current.DefaultTabId, true); + if (objModule != null) + { + Alignment = objModule.Alignment; + Color = objModule.Color; + Border = objModule.Border; + IconFile = objModule.IconFile; + Visibility = objModule.Visibility; + ContainerSrc = objModule.ContainerSrc; + DisplayTitle = objModule.DisplayTitle; + DisplayPrint = objModule.DisplayPrint; + DisplaySyndicate = objModule.DisplaySyndicate; + } + } + } + + #region Obsolete Members + + [Obsolete("Deprecated in DNN 5.1. All permission checks are done through Permission Collections")] + [XmlIgnore] + public string AuthorizedEditRoles + { + get + { + if (string.IsNullOrEmpty(_authorizedEditRoles)) + { + _authorizedEditRoles = ModulePermissions.ToString("EDIT"); + } + return _authorizedEditRoles; + } + } + + [Obsolete("Deprecated in DNN 5.1. All permission checks are done through Permission Collections")] + [XmlIgnore] + public string AuthorizedViewRoles + { + get + { + if (string.IsNullOrEmpty(_authorizedViewRoles)) + { + _authorizedViewRoles = InheritViewPermissions ? TabPermissionController.GetTabPermissions(TabID, PortalID).ToString("VIEW") : ModulePermissions.ToString("VIEW"); + } + return _authorizedViewRoles; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.ModuleName")] + [XmlIgnore] + public string ModuleName + { + get + { + return DesktopModule.ModuleName; + } + set + { + DesktopModule.ModuleName = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.FriendlyName")] + [XmlIgnore] + public string FriendlyName + { + get + { + return DesktopModule.FriendlyName; + } + set + { + DesktopModule.FriendlyName = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.FolderName")] + [XmlIgnore] + public string FolderName + { + get + { + return DesktopModule.FolderName; + } + set + { + DesktopModule.FolderName = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.Description")] + [XmlIgnore] + public string Description + { + get + { + return DesktopModule.Description; + } + set + { + DesktopModule.Description = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by by DesktopModule.Version")] + [XmlIgnore] + public string Version + { + get + { + return DesktopModule.Version; + } + set + { + DesktopModule.Version = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.IsPremium")] + [XmlIgnore] + public bool IsPremium + { + get + { + return DesktopModule.IsPremium; + } + set + { + DesktopModule.IsPremium = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.IsAdmin")] + [XmlIgnore] + public bool IsAdmin + { + get + { + return DesktopModule.IsAdmin; + } + set + { + DesktopModule.IsAdmin = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.BusinessControllerClass")] + [XmlIgnore] + public string BusinessControllerClass + { + get + { + return DesktopModule.BusinessControllerClass; + } + set + { + DesktopModule.BusinessControllerClass = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.SupportedFeatures")] + [XmlIgnore] + public int SupportedFeatures + { + get + { + return DesktopModule.SupportedFeatures; + } + set + { + DesktopModule.SupportedFeatures = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.IsPortable")] + [XmlIgnore] + public bool IsPortable + { + get + { + return DesktopModule.IsPortable; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.IsSearchable")] + [XmlIgnore] + public bool IsSearchable + { + get + { + return DesktopModule.IsSearchable; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.IsUpgradeable")] + [XmlIgnore] + public bool IsUpgradeable + { + get + { + return DesktopModule.IsUpgradeable; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.CompatibleVersions")] + [XmlIgnore] + public string CompatibleVersions + { + get + { + return DesktopModule.CompatibleVersions; + } + set + { + DesktopModule.CompatibleVersions = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.Dependencies")] + [XmlIgnore] + public string Dependencies + { + get + { + return DesktopModule.Dependencies; + } + set + { + DesktopModule.Dependencies = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DesktopModule.Permisssions")] + [XmlIgnore] + public string Permissions + { + get + { + return DesktopModule.Permissions; + } + set + { + DesktopModule.Permissions = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleDefinition.DefaultCacheTime")] + [XmlIgnore] + public int DefaultCacheTime + { + get + { + return ModuleDefinition.DefaultCacheTime; + } + set + { + ModuleDefinition.DefaultCacheTime = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleControl.ControlSrc")] + [XmlIgnore] + public string ControlSrc + { + get + { + return ModuleControl.ControlSrc; + } + set + { + ModuleControl.ControlSrc = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleControl.ControlType")] + [XmlIgnore] + public SecurityAccessLevel ControlType + { + get + { + return ModuleControl.ControlType; + } + set + { + ModuleControl.ControlType = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleControl.ControlTitle")] + [XmlIgnore] + public string ControlTitle + { + get + { + return ModuleControl.ControlTitle; + } + set + { + ModuleControl.ControlTitle = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleControl.HelpUrl")] + [XmlIgnore] + public string HelpUrl + { + get + { + return ModuleControl.HelpURL; + } + set + { + ModuleControl.HelpURL = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModuleControl.SupportsPartialRendering")] + [XmlIgnore] + public bool SupportsPartialRendering + { + get + { + return ModuleControl.SupportsPartialRendering; + } + set + { + ModuleControl.SupportsPartialRendering = value; + } + } + + [Obsolete("Deprecated in DNN 5.1.")] + [XmlIgnore] + protected TabPermissionCollection TabPermissions + { + get { + return _tabPermissions ?? + (_tabPermissions = TabPermissionController.GetTabPermissions(TabID, PortalID)); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ModuleSearchBase.cs b/DNN Platform/Library/Entities/Modules/ModuleSearchBase.cs new file mode 100644 index 00000000000..60f4552f375 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleSearchBase.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// + /// Modules participating in Search should inherit from this class. A scheduled job will call the methods from this class. + /// + /// Since the methods will be called through a Scheduled job, there will be no Portal Context available by the module to take advantage of + public abstract class ModuleSearchBase + { + /// + /// Return a list of Modified Search Documents based on date. The documents will be stored in Search Index. + /// + /// Module Info + /// Provide modified content from this time in Utc + /// Collection of SearchDocument + /// Module must return New, Updated and Deleted Search Documents. + /// It is important to include all the relevant Properties for Updated content (sames as supplied for New document), as partial SearchDocument cannot be Updated in Search Index. + /// This is different from standard SQL Update where selective columns can updated. In this case, entire Document must be supplied during Update or else information will be lost. + /// For Deleted content, set IsActive = false property. + /// When IsActive = true, an attempt is made to delete any existing document with same UniqueKey, PortalId, SearchTypeId=Module, ModuleDefitionId and ModuleId(if specified). + /// System calls the module based on Scheduler Frequency. This call is performed for modules that have indicated supportedFeature type="Searchable" in manifest. + /// Call is performed for every Module Definition defined by the Module. If a module has more than one Module Defition, module must return data for the main Module Defition, + /// or else duplicate content may get stored. + /// Module must include ModuleDefition Id in the SearchDocument. In addition ModuleId and / or TabId can also be specified if module has TabId / ModuleId specific content. + public abstract IList GetModifiedSearchDocuments(ModuleInfo moduleInfo, DateTime beginDate); + } +} diff --git a/DNN Platform/Library/Entities/Modules/ModuleSettingsBase.cs b/DNN Platform/Library/Entities/Modules/ModuleSettingsBase.cs new file mode 100644 index 00000000000..c4bd073bcfa --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleSettingsBase.cs @@ -0,0 +1,98 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.ComponentModel; + +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public class ModuleSettingsBase : PortalModuleBase, ISettingsControl + { + private Hashtable _moduleSettings; + private Hashtable _settings; + private Hashtable _tabModuleSettings; + + public Hashtable ModuleSettings + { + get + { + if (_moduleSettings == null) + { + //Get ModuleSettings + _moduleSettings = new ModuleController().GetModuleSettings(ModuleId); + } + return _moduleSettings; + } + } + + public Hashtable TabModuleSettings + { + get + { + if (_tabModuleSettings == null) + { + //Get TabModuleSettings + _tabModuleSettings = new ModuleController().GetTabModuleSettings(TabModuleId); + } + return _tabModuleSettings; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new Hashtable Settings + { + get + { + if (_settings == null) + { + _settings = new Hashtable(); + //Merge the TabModuleSettings and ModuleSettings + foreach (string strKey in TabModuleSettings.Keys) + { + _settings[strKey] = TabModuleSettings[strKey]; + } + foreach (string strKey in ModuleSettings.Keys) + { + _settings[strKey] = ModuleSettings[strKey]; + } + } + return _settings; + } + } + + #region ISettingsControl Members + + public virtual void LoadSettings() + { + } + + public virtual void UpdateSettings() + { + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/ModuleSharing.cs b/DNN Platform/Library/Entities/Modules/ModuleSharing.cs new file mode 100644 index 00000000000..64f402b99bc --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ModuleSharing.cs @@ -0,0 +1,31 @@ +#region Copyright +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Entities.Modules +{ + public enum ModuleSharing + { + Unknown, + Unsupported, + Supported + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/PortalDesktopModuleInfo.cs b/DNN Platform/Library/Entities/Modules/PortalDesktopModuleInfo.cs new file mode 100644 index 00000000000..19393f6b7b5 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/PortalDesktopModuleInfo.cs @@ -0,0 +1,77 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + [Serializable] + public class PortalDesktopModuleInfo : BaseEntityInfo + { + private DesktopModuleInfo _desktopModule; + private DesktopModulePermissionCollection _permissions; + + [XmlIgnore] + public int PortalDesktopModuleID { get; set; } + + [XmlIgnore] + public DesktopModuleInfo DesktopModule + { + get + { + if (_desktopModule == null) + { + _desktopModule = DesktopModuleID > Null.NullInteger ? DesktopModuleController.GetDesktopModule(DesktopModuleID, PortalID) : new DesktopModuleInfo(); + } + return _desktopModule; + } + } + [XmlIgnore] + public int DesktopModuleID { get; set; } + + public string FriendlyName { get; set; } + + public DesktopModulePermissionCollection Permissions + { + get + { + if (_permissions == null) + { + _permissions = new DesktopModulePermissionCollection(DesktopModulePermissionController.GetDesktopModulePermissions(PortalDesktopModuleID)); + } + return _permissions; + } + } + + [XmlIgnore] + public int PortalID { get; set; } + + [XmlIgnore] + public string PortalName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Modules/PortalModuleBase.cs b/DNN Platform/Library/Entities/Modules/PortalModuleBase.cs new file mode 100644 index 00000000000..3535cddf63a --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/PortalModuleBase.cs @@ -0,0 +1,506 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; +using System.IO; +using System.Threading; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : PortalModuleBase + /// + /// ----------------------------------------------------------------------------- + /// + /// The PortalModuleBase class defines a custom base class inherited by all + /// desktop portal modules within the Portal. + /// + /// The PortalModuleBase class defines portal specific properties + /// that are used by the portal framework to correctly display portal modules + /// + /// + /// + /// + /// [cnurse] 09/17/2004 Added Documentation + /// Modified LocalResourceFile to be Writeable + /// [cnurse] 10/21/2004 Modified Settings property to get both + /// TabModuleSettings and ModuleSettings + /// [cnurse] 12/15/2007 Refactored to support the new IModuleControl + /// Interface + /// + /// ----------------------------------------------------------------------------- + public class PortalModuleBase : UserControlBase, IModuleControl + { + private string _localResourceFile; + private ModuleInstanceContext _moduleContext; + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public ModuleActionCollection Actions + { + get + { + return ModuleContext.Actions; + } + set + { + ModuleContext.Actions = value; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Control ContainerControl + { + get + { + return Globals.FindControlRecursive(this, "ctr" + ModuleId); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The EditMode property is used to determine whether the user is in the + /// Administrator role + /// Cache + /// + /// + /// + /// + /// [cnurse] 01/19/2006 Created + /// + /// ----------------------------------------------------------------------------- + public bool EditMode + { + get + { + return ModuleContext.EditMode; + } + } + + public string HelpURL + { + get + { + return ModuleContext.HelpURL; + } + set + { + ModuleContext.HelpURL = value; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public bool IsEditable + { + get + { + return ModuleContext.IsEditable; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public ModuleInfo ModuleConfiguration + { + get + { + return ModuleContext.Configuration; + } + set + { + ModuleContext.Configuration = value; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int PortalId + { + get + { + return ModuleContext.PortalId; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int TabId + { + get + { + return ModuleContext.TabId; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int TabModuleId + { + get + { + return ModuleContext.TabModuleId; + } + set + { + ModuleContext.TabModuleId = value; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int ModuleId + { + get + { + return ModuleContext.ModuleId; + } + set + { + ModuleContext.ModuleId = value; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public UserInfo UserInfo + { + get + { + return PortalSettings.UserInfo; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int UserId + { + get + { + return PortalSettings.UserId; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PortalAliasInfo PortalAlias + { + get + { + return PortalSettings.PortalAlias; + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Hashtable Settings + { + get + { + return ModuleContext.Settings; + } + } + + #region IModuleControl Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets the underlying base control for this ModuleControl + /// + /// A String + /// + /// [cnurse] 12/17/2007 created + /// + /// ----------------------------------------------------------------------------- + public Control Control + { + get + { + return this; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this control (used primarily for UserControls) + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlName + { + get + { + return GetType().Name.Replace("_", "."); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the local resource file for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string LocalResourceFile + { + get + { + string fileRoot; + if (string.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = Path.Combine(ControlPath, Localization.LocalResourceDirectory + "/" + ID); + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Context for this control + /// + /// A ModuleInstanceContext + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleInstanceContext ModuleContext + { + get + { + if (_moduleContext == null) + { + _moduleContext = new ModuleInstanceContext(this); + } + return _moduleContext; + } + } + + #endregion + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl() + { + return ModuleContext.EditUrl(); + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl(string ControlKey) + { + return ModuleContext.EditUrl(ControlKey); + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl(string KeyName, string KeyValue) + { + return ModuleContext.EditUrl(KeyName, KeyValue); + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl(string KeyName, string KeyValue, string ControlKey) + { + return ModuleContext.EditUrl(KeyName, KeyValue, ControlKey); + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl(string KeyName, string KeyValue, string ControlKey, params string[] AdditionalParameters) + { + return ModuleContext.EditUrl(KeyName, KeyValue, ControlKey, AdditionalParameters); + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string EditUrl(int TabID, string ControlKey, bool PageRedirect, params string[] AdditionalParameters) + { + return ModuleContext.NavigateUrl(TabID, ControlKey, PageRedirect, AdditionalParameters); + } + + /// ----------------------------------------------------------------------------- + /// + /// Helper method that can be used to add an ActionEventHandler to the Skin for this + /// Module Control + /// + /// + /// + /// + /// [cnurse] 17/9/2004 Added Documentation + /// + /// ----------------------------------------------------------------------------- + protected void AddActionHandler(ActionEventHandler e) + { + UI.Skins.Skin ParentSkin = UI.Skins.Skin.GetParentSkin(this); + if (ParentSkin != null) + { + ParentSkin.RegisterModuleActionEvent(ModuleId, e); + } + } + + protected string LocalizeString(string key) + { + return Localization.GetString(key, LocalResourceFile); + } + + + + public int GetNextActionID() + { + return ModuleContext.GetNextActionID(); + } + + #region "Obsolete methods" + + // CONVERSION: Remove obsoleted methods (FYI some core modules use these, such as Links) + /// ----------------------------------------------------------------------------- + /// + /// The CacheDirectory property is used to return the location of the "Cache" + /// Directory for the Module + /// + /// + /// + /// + /// [cnurse] 04/28/2005 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("This property is deprecated. Plaese use ModuleController.CacheDirectory()")] + public string CacheDirectory + { + get + { + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The CacheFileName property is used to store the FileName for this Module's + /// Cache + /// + /// + /// + /// + /// [cnurse] 04/28/2005 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("This property is deprecated. Please use ModuleController.CacheFileName(TabModuleID)")] + public string CacheFileName + { + get + { + string strCacheKey = "TabModule:"; + strCacheKey += TabModuleId + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache" + "\\" + Globals.CleanFileName(strCacheKey) + ".resources"; + } + } + + [Obsolete("This property is deprecated. Please use ModuleController.CacheKey(TabModuleID)")] + public string CacheKey + { + get + { + string strCacheKey = "TabModule:"; + strCacheKey += TabModuleId + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return strCacheKey; + } + } + + // CONVERSION: Obsolete pre 5.0 => Remove in 5.0 + [ObsoleteAttribute( + "The HelpFile() property was deprecated in version 2.2. Help files are now stored in the /App_LocalResources folder beneath the module with the following resource key naming convention: ModuleHelp.Text" + )] + public string HelpFile { get; set; } + + [Obsolete("ModulePath was renamed to ControlPath and moved to IModuleControl in version 5.0")] + public string ModulePath + { + get + { + return ControlPath; + } + } + + [Obsolete("This property is deprecated. Please use ModuleController.CacheFileName(TabModuleID)")] + public string GetCacheFileName(int tabModuleId) + { + string strCacheKey = "TabModule:"; + strCacheKey += tabModuleId + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache" + "\\" + Globals.CleanFileName(strCacheKey) + ".resources"; + } + + [Obsolete("This property is deprecated. Please use ModuleController.CacheKey(TabModuleID)")] + public string GetCacheKey(int tabModuleId) + { + string strCacheKey = "TabModule:"; + strCacheKey += tabModuleId + ":"; + strCacheKey += Thread.CurrentThread.CurrentUICulture.ToString(); + return strCacheKey; + } + + [Obsolete("Deprecated in DNN 5.0. Please use ModulePermissionController.HasModulePermission(ModuleConfiguration.ModulePermissions, PermissionKey) ")] + public bool HasModulePermission(string PermissionKey) + { + return ModulePermissionController.HasModulePermission(ModuleConfiguration.ModulePermissions, PermissionKey); + } + + [Obsolete("This method is deprecated. Plaese use ModuleController.SynchronizeModule(ModuleId)")] + public void SynchronizeModule() + { + ModuleController.SynchronizeModule(ModuleId); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/ProfileUserControlBase.cs b/DNN Platform/Library/Entities/Modules/ProfileUserControlBase.cs new file mode 100644 index 00000000000..f132d61ed6b --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/ProfileUserControlBase.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ProfileUserControlBase + /// ----------------------------------------------------------------------------- + /// + /// The ProfileUserControlBase class defines a custom base class for the profile Control. + /// + /// + /// + /// + /// [cnurse] 03/02/2007 + /// + /// ----------------------------------------------------------------------------- + public class ProfileUserControlBase : UserModuleBase + { + public event EventHandler ProfileUpdated; + public event EventHandler ProfileUpdateCompleted; + + /// ----------------------------------------------------------------------------- + /// + /// Raises the OnProfileUpdateCompleted Event + /// + /// + /// [cnurse] 07/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnProfileUpdateCompleted(EventArgs e) + { + if (ProfileUpdateCompleted != null) + { + ProfileUpdateCompleted(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the ProfileUpdated Event + /// + /// + /// [cnurse] 03/16/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnProfileUpdated(EventArgs e) + { + if (ProfileUpdated != null) + { + ProfileUpdated(this, e); + } + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/SkinControlController.cs b/DNN Platform/Library/Entities/Modules/SkinControlController.cs new file mode 100644 index 00000000000..2bdf4a00739 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/SkinControlController.cs @@ -0,0 +1,159 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : ModuleControlController + /// ----------------------------------------------------------------------------- + /// + /// ModuleControlController provides the Business Layer for Module Controls + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class SkinControlController + { + private static readonly DataProvider dataProvider = DataProvider.Instance(); + + /// ----------------------------------------------------------------------------- + /// + /// DeleteSkinControl deletes a Skin Control in the database + /// + /// The Skin Control to delete + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteSkinControl(SkinControlInfo skinControl) + { + dataProvider.DeleteSkinControl(skinControl.SkinControlID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(skinControl, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINCONTROL_DELETED); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSkinControl gets a single Skin Control from the database + /// + /// The ID of the SkinControl + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static SkinControlInfo GetSkinControl(int skinControlID) + { + return CBO.FillObject(dataProvider.GetSkinControl(skinControlID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSkinControlByPackageID gets a single Skin Control from the database + /// + /// The ID of the Package + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static SkinControlInfo GetSkinControlByPackageID(int packageID) + { + return CBO.FillObject(dataProvider.GetSkinControlByPackageID(packageID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSkinControlByKey gets a single Skin Control from the database + /// + /// The key of the Control + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static SkinControlInfo GetSkinControlByKey(string key) + { + return CBO.FillObject(dataProvider.GetSkinControlByKey(key)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSkinControls gets all the Skin Controls from the database + /// + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetSkinControls() + { + return CBO.FillDictionary("ControlKey", dataProvider.GetSkinControls(), new Dictionary()); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveSkinControl updates a Skin Control in the database + /// + /// The Skin Control to save + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int SaveSkinControl(SkinControlInfo skinControl) + { + int skinControlID = skinControl.SkinControlID; + var eventLogController = new EventLogController(); + if (skinControlID == Null.NullInteger) + { + //Add new Skin Control + skinControlID = dataProvider.AddSkinControl(skinControl.PackageID, + skinControl.ControlKey, + skinControl.ControlSrc, + skinControl.SupportsPartialRendering, + UserController.GetCurrentUserInfo().UserID); + eventLogController.AddLog(skinControl, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINCONTROL_CREATED); + } + else + { + //Upgrade Skin Control + dataProvider.UpdateSkinControl(skinControl.SkinControlID, + skinControl.PackageID, + skinControl.ControlKey, + skinControl.ControlSrc, + skinControl.SupportsPartialRendering, + UserController.GetCurrentUserInfo().UserID); + eventLogController.AddLog(skinControl, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINCONTROL_UPDATED); + } + return skinControlID; + } + } +} diff --git a/DNN Platform/Library/Entities/Modules/SkinControlInfo.cs b/DNN Platform/Library/Entities/Modules/SkinControlInfo.cs new file mode 100644 index 00000000000..85f1ad558d6 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/SkinControlInfo.cs @@ -0,0 +1,182 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : SkinControlInfo + /// ----------------------------------------------------------------------------- + /// + /// SkinControlInfo provides the Entity Layer for Skin Controls (SkinObjects) + /// + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class SkinControlInfo : ControlInfo, IXmlSerializable, IHydratable + { + public SkinControlInfo() + { + PackageID = Null.NullInteger; + SkinControlID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the SkinControl ID + /// + /// An Integer + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int SkinControlID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ID of the Package for this Desktop Module + /// + /// An Integer + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int PackageID { get; set; } + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a SkinControlInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + SkinControlID = Null.SetNullInteger(dr["SkinControlID"]); + PackageID = Null.SetNullInteger(dr["PackageID"]); + FillInternal(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return SkinControlID; + } + set + { + SkinControlID = value; + } + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the SkinControlInfo + /// + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a SkinControlInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + ReadXmlInternal(reader); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a SkinControlInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 03/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("moduleControl"); + + //write out properties + WriteXmlInternal(writer); + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/UserModuleBase.cs b/DNN Platform/Library/Entities/Modules/UserModuleBase.cs new file mode 100644 index 00000000000..0b32c97893c --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/UserModuleBase.cs @@ -0,0 +1,672 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Membership; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Social.Notifications; +using DotNetNuke.Services.Vendors; +using DotNetNuke.UI.Skins.Controls; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + public enum DisplayMode + { + All = 0, + FirstLetter = 1, + None = 2 + } + + public enum UsersControl + { + Combo = 0, + TextBox = 1 + } + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : UserModuleBase + /// ----------------------------------------------------------------------------- + /// + /// The UserModuleBase class defines a custom base class inherited by all + /// desktop portal modules within the Portal that manage Users. + /// + /// + /// + /// + /// [cnurse] 03/20/2006 + /// + /// ----------------------------------------------------------------------------- + public class UserModuleBase : PortalModuleBase + { + private UserInfo _User; + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether we are in Add User mode + /// + /// + /// [cnurse] 03/06/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool AddUser + { + get + { + return (UserId == Null.NullInteger); + } + } + + ///// + ///// Gets the effective portalId for User (returns the current PortalId unless Portal + ///// is in a PortalGroup, when it will return the PortalId of the Master Portal). + ///// + //protected int EffectivePortalId + //{ + // get { return PortalController.GetEffectivePortalId(PortalId); } + //} + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the current user is an Administrator (or SuperUser) + /// + /// + /// [cnurse] 03/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsAdmin + { + get + { + return Request.IsAuthenticated && PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName); + } + } + + /// + /// gets whether this is the current user or admin + /// + /// + /// + /// + protected bool IsUserOrAdmin + { + get + { + return IsUser || IsAdmin; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether this control is in the Host menu + /// + /// + /// [cnurse] 07/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsHostTab + { + get + { + return base.IsHostMenu; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the control is being called form the User Accounts module + /// + /// + /// [cnurse] 07/07/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsEdit + { + get + { + bool _IsEdit = false; + if (Request.QueryString["ctl"] != null) + { + string ctl = Request.QueryString["ctl"]; + if (ctl == "Edit") + { + _IsEdit = true; + } + } + return _IsEdit; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the current user is modifying their profile + /// + /// + /// [cnurse] 03/21/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsProfile + { + get + { + bool _IsProfile = false; + if (IsUser) + { + if (PortalSettings.UserTabId != -1) + { + //user defined tab + if (PortalSettings.ActiveTab.TabID == PortalSettings.UserTabId) + { + _IsProfile = true; + } + } + else + { + //admin tab + if (Request.QueryString["ctl"] != null) + { + string ctl = Request.QueryString["ctl"]; + if (ctl == "Profile") + { + _IsProfile = true; + } + } + } + } + return _IsProfile; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether an anonymous user is trying to register + /// + /// + /// [cnurse] 03/21/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsRegister + { + get + { + return !IsAdmin && !IsUser; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the User is editing their own information + /// + /// + /// [cnurse] 03/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected bool IsUser + { + get + { + return Request.IsAuthenticated && (User.UserID == UserInfo.UserID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PortalId to use for this control + /// + /// + /// [cnurse] 02/21/2007 Created + /// + /// ----------------------------------------------------------------------------- + protected int UserPortalID + { + get + { + return IsHostTab ? Null.NullInteger : PortalId; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User associated with this control + /// + /// + /// [cnurse] 03/02/2006 Created + /// + /// ----------------------------------------------------------------------------- + public UserInfo User + { + get + { + return _User ?? (_User = AddUser ? InitialiseUser() : UserController.GetUserById(UserPortalID, UserId)); + } + set + { + _User = value; + if (_User != null) + { + UserId = _User.UserID; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the UserId associated with this control + /// + /// + /// [cnurse] 03/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public new int UserId + { + get + { + int _UserId = Null.NullInteger; + if (ViewState["UserId"] == null) + { + if (Request.QueryString["userid"] != null) + { + _UserId = Int32.Parse(Request.QueryString["userid"]); + ViewState["UserId"] = _UserId; + } + } + else + { + _UserId = Convert.ToInt32(ViewState["UserId"]); + } + return _UserId; + } + set + { + ViewState["UserId"] = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Setting for the Module + /// + /// + /// + /// + /// [cnurse] 05/01/2006 Created + /// [cnurse] 02/07/2008 DNN-7003 Fixed GetSetting() in UserModuleBase so it handles situation where one or more settings are missing. + /// + /// ----------------------------------------------------------------------------- + public static object GetSetting(int portalId, string settingKey) + { + Hashtable settings = UserController.GetUserSettings(portalId); + if (settings[settingKey] == null) + { + settings = UserController.GetUserSettings(portalId, settings); + } + return settings[settingKey]; + } + + public static void UpdateSetting(int portalId, string key, string setting) + { + if (portalId == Null.NullInteger) + { + HostController.Instance.Update(new ConfigurationSetting {Value = setting, Key = key}); + } + else + { + PortalController.UpdatePortalSetting(portalId, key, setting); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates the Settings for the Module + /// + /// + /// + /// + /// [cnurse] 06/27/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static void UpdateSettings(int portalId, Hashtable settings) + { + string key; + string setting; + IDictionaryEnumerator settingsEnumerator = settings.GetEnumerator(); + while (settingsEnumerator.MoveNext()) + { + key = Convert.ToString(settingsEnumerator.Key); + setting = Convert.ToString(settingsEnumerator.Value); + UpdateSetting(portalId, key, setting); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// InitialiseUser initialises a "new" user + /// + /// + /// [cnurse] 03/13/2006 + /// + /// ----------------------------------------------------------------------------- + private UserInfo InitialiseUser() + { + var newUser = new UserInfo(); + if (IsHostMenu && !IsRegister) + { + newUser.IsSuperUser = true; + } + else + { + newUser.PortalID = PortalId; + } + + //Initialise the ProfileProperties Collection + string lc = new Localization().CurrentUICulture; + + newUser.Profile.InitialiseProfile(PortalId); + newUser.Profile.PreferredTimeZone = PortalSettings.TimeZone; + + newUser.Profile.PreferredLocale = lc; + + //Set default countr + string country = Null.NullString; + country = LookupCountry(); + if (!String.IsNullOrEmpty(country)) + { + newUser.Profile.Country = country; + } + //Set AffiliateId + int AffiliateId = Null.NullInteger; + if (Request.Cookies["AffiliateId"] != null) + { + AffiliateId = int.Parse(Request.Cookies["AffiliateId"].Value); + } + newUser.AffiliateID = AffiliateId; + return newUser; + } + + private string LookupCountry() + { + string IP; + bool IsLocal = false; + bool _CacheGeoIPData = true; + string _GeoIPFile; + _GeoIPFile = "controls/CountryListBox/Data/GeoIP.dat"; + if (Page.Request.UserHostAddress == "127.0.0.1") + { + //'The country cannot be detected because the user is local. + IsLocal = true; + //Set the IP address in case they didn't specify LocalhostCountryCode + IP = Page.Request.UserHostAddress; + } + else + { + //Set the IP address so we can find the country + IP = Page.Request.UserHostAddress; + } + //Check to see if we need to generate the Cache for the GeoIPData file + if (Context.Cache.Get("GeoIPData") == null && _CacheGeoIPData) + { + //Store it as well as setting a dependency on the file + Context.Cache.Insert("GeoIPData", CountryLookup.FileToMemory(Context.Server.MapPath(_GeoIPFile)), new CacheDependency(Context.Server.MapPath(_GeoIPFile))); + } + + //Check to see if the request is a localhost request + //and see if the LocalhostCountryCode is specified + if (IsLocal) + { + return Null.NullString; + } + + //Either this is a remote request or it is a local + //request with no LocalhostCountryCode specified + CountryLookup _CountryLookup; + + //Check to see if we are using the Cached + //version of the GeoIPData file + if (_CacheGeoIPData) + { + //Yes, get it from cache + _CountryLookup = new CountryLookup((MemoryStream) Context.Cache.Get("GeoIPData")); + } + else + { + //No, get it from file + _CountryLookup = new CountryLookup(Context.Server.MapPath(_GeoIPFile)); + } + //Get the country code based on the IP address + string country = Null.NullString; + try + { + country = _CountryLookup.LookupCountryName(IP); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + return country; + } + + /// ----------------------------------------------------------------------------- + /// + /// AddLocalizedModuleMessage adds a localized module message + /// + /// The localized message + /// The type of message + /// A flag that determines whether the message should be displayed + /// + /// [cnurse] 03/14/2006 + /// [cnurse] 07/03/2007 Moved to Base Class and changed to Protected + /// + /// ----------------------------------------------------------------------------- + protected void AddLocalizedModuleMessage(string message, ModuleMessage.ModuleMessageType type, bool display) + { + if (display) + { + UI.Skins.Skin.AddModuleMessage(this, message, type); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleMessage adds a module message + /// + /// The message + /// The type of message + /// A flag that determines whether the message should be displayed + /// + /// [cnurse] 03/14/2006 + /// [cnurse] 07/03/2007 Moved to Base Class and changed to Protected + /// + /// ----------------------------------------------------------------------------- + protected void AddModuleMessage(string message, ModuleMessage.ModuleMessageType type, bool display) + { + AddLocalizedModuleMessage(Localization.GetString(message, LocalResourceFile), type, display); + } + + protected string CompleteUserCreation(UserCreateStatus createStatus, UserInfo newUser, bool notify, bool register) + { + string strMessage = ""; + ModuleMessage.ModuleMessageType message = ModuleMessage.ModuleMessageType.RedError; + if (register) + { + //send notification to portal administrator of new user registration + //check the receive notification setting first, but if register type is Private, we will always send the notification email. + //because the user need administrators to do the approve action so that he can continue use the website. + if (PortalSettings.EnableRegisterNotification || PortalSettings.UserRegistration == (int)Globals.PortalRegistrationType.PrivateRegistration) + { + strMessage += Mail.SendMail(newUser, MessageType.UserRegistrationAdmin, PortalSettings); + SendAdminNotification(newUser, "NewUserRegistration", PortalSettings); + } + + var loginStatus = UserLoginStatus.LOGIN_FAILURE; + + //complete registration + switch (PortalSettings.UserRegistration) + { + case (int) Globals.PortalRegistrationType.PrivateRegistration: + strMessage += Mail.SendMail(newUser, MessageType.UserRegistrationPrivate, PortalSettings); + + //show a message that a portal administrator has to verify the user credentials + if (string.IsNullOrEmpty(strMessage)) + { + strMessage += string.Format(Localization.GetString("PrivateConfirmationMessage", Localization.SharedResourceFile), newUser.Email); + message = ModuleMessage.ModuleMessageType.GreenSuccess; + } + break; + case (int) Globals.PortalRegistrationType.PublicRegistration: + Mail.SendMail(newUser, MessageType.UserRegistrationPublic, PortalSettings); + UserController.UserLogin(PortalSettings.PortalId, newUser.Username, newUser.Membership.Password, "", PortalSettings.PortalName, "", ref loginStatus, false); + break; + case (int) Globals.PortalRegistrationType.VerifiedRegistration: + Mail.SendMail(newUser, MessageType.UserRegistrationVerified, PortalSettings); + UserController.UserLogin(PortalSettings.PortalId, newUser.Username, newUser.Membership.Password, "", PortalSettings.PortalName, "", ref loginStatus, false); + break; + } + //affiliate + if (!Null.IsNull(User.AffiliateID)) + { + var objAffiliates = new AffiliateController(); + objAffiliates.UpdateAffiliateStats(newUser.AffiliateID, 0, 1); + } + //store preferredlocale in cookie + Localization.SetLanguage(newUser.Profile.PreferredLocale); + if (IsRegister && message == ModuleMessage.ModuleMessageType.RedError) + { + AddLocalizedModuleMessage(string.Format(Localization.GetString("SendMail.Error", Localization.SharedResourceFile), strMessage), message, (!String.IsNullOrEmpty(strMessage))); + } + else + { + AddLocalizedModuleMessage(strMessage, message, (!String.IsNullOrEmpty(strMessage))); + } + } + else + { + if (notify) + { + //Send Notification to User + if (PortalSettings.UserRegistration == (int) Globals.PortalRegistrationType.VerifiedRegistration) + { + strMessage += Mail.SendMail(newUser, MessageType.UserRegistrationVerified, PortalSettings); + } + else + { + strMessage += Mail.SendMail(newUser, MessageType.UserRegistrationPublic, PortalSettings); + } + } + } + //Log Event to Event Log + var objEventLog = new EventLogController(); + objEventLog.AddLog(newUser, PortalSettings, UserId, newUser.Username, EventLogController.EventLogType.USER_CREATED); + return strMessage; + } + + + [Obsolete("In DotNetNuke 5.0 there is no longer the concept of an Admin Page. All pages are controlled by Permissions")] + protected bool IsAdminTab + { + get + { + return false; + } + } + + [Obsolete("In DotNetNuke 5.2 replaced by UserController.GetDefaultUserSettings().")] + public static Hashtable GetDefaultSettings() + { + return UserController.GetDefaultUserSettings(); + } + + [Obsolete("In DotNetNuke 5.2 replaced by UserController.GetUserSettings(settings).")] + public static Hashtable GetSettings(Hashtable settings) + { + return UserController.GetUserSettings(PortalController.GetCurrentPortalSettings().PortalId, settings); + } + + #region Private methods + private void SendAdminNotification(UserInfo newUser, string notificationType, PortalSettings portalSettings) + { + var notification = new Notification + { + NotificationTypeID = NotificationsController.Instance.GetNotificationType(notificationType).NotificationTypeId, + IncludeDismissAction = true, + SenderUserID = portalSettings.AdministratorId + }; + notification.Subject = GetNotificationSubject(notificationType, newUser.Profile.PreferredLocale, newUser, portalSettings); + notification.Body = GetNotificationBody(notificationType, newUser.Profile.PreferredLocale, newUser, portalSettings); + var roleController = new RoleController(); + var adminrole = roleController.GetRole(portalSettings.AdministratorRoleId, portalSettings.PortalId); + var roles = new List(); + roles.Add(adminrole); + NotificationsController.Instance.SendNotification(notification, portalSettings.PortalId, roles, new List()); + + } + + private string GetNotificationBody(string notificationType, string locale, UserInfo newUser, PortalSettings portalSettings) + { + string text = ""; + switch (notificationType) + { + case "NewUserRegistration": + text = "EMAIL_USER_REGISTRATION_ADMINISTRATOR_BODY"; + break; + } + return LocalizeNotificationText(text, locale, newUser, portalSettings); + } + + private string LocalizeNotificationText(string text, string locale, UserInfo user, PortalSettings portalSettings) + { + //This method could need a custom ArrayList in future notification types. Currently it is null + return Localization.GetSystemMessage(locale, portalSettings, text, user, Localization.GlobalResourceFile, null, "", portalSettings.AdministratorId); + } + + private string GetNotificationSubject(string notificationType, string locale, UserInfo newUser, PortalSettings portalSettings) + { + string text = ""; + switch (notificationType) + { + case "NewUserRegistration": + text = "EMAIL_USER_REGISTRATION_ADMINISTRATOR_SUBJECT"; + break; + } + return LocalizeNotificationText(text, locale, newUser, portalSettings); + } + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/UserUserControlBase.cs b/DNN Platform/Library/Entities/Modules/UserUserControlBase.cs new file mode 100644 index 00000000000..d4dd6eae696 --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/UserUserControlBase.cs @@ -0,0 +1,467 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Membership; + +#endregion + +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : UserUserControlBase + /// ----------------------------------------------------------------------------- + /// + /// The UserUserControlBase class defines a custom base class for the User Control. + /// + /// + /// + /// + /// [cnurse] 03/02/2007 + /// + /// ----------------------------------------------------------------------------- + public class UserUserControlBase : UserModuleBase + { + #region Delegates + public delegate void UserCreatedEventHandler(object sender, UserCreatedEventArgs e); + public delegate void UserDeletedEventHandler(object sender, UserDeletedEventArgs e); + public delegate void UserRestoredEventHandler(object sender, UserRestoredEventArgs e); + public delegate void UserRemovedEventHandler(object sender, UserRemovedEventArgs e); + public delegate void UserUpdateErrorEventHandler(object sender, UserUpdateErrorArgs e); + #endregion + + #region "Events" + public event UserCreatedEventHandler UserCreated; + public event UserCreatedEventHandler UserCreateCompleted; + public event UserDeletedEventHandler UserDeleted; + public event UserUpdateErrorEventHandler UserDeleteError; + public event UserRestoredEventHandler UserRestored; + public event UserUpdateErrorEventHandler UserRestoreError; + public event UserRemovedEventHandler UserRemoved; + public event UserUpdateErrorEventHandler UserRemoveError; + public event EventHandler UserUpdated; + public event EventHandler UserUpdateCompleted; + public event UserUpdateErrorEventHandler UserUpdateError; + #endregion + + #region "Event Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserCreateCompleted Event + /// + /// + /// [cnurse] 07/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserCreateCompleted(UserCreatedEventArgs e) + { + if (UserCreateCompleted != null) + { + UserCreateCompleted(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserCreated Event + /// + /// + /// [cnurse] 03/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserCreated(UserCreatedEventArgs e) + { + if (UserCreated != null) + { + UserCreated(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserDeleted Event + /// + /// + /// [cnurse] 03/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserDeleted(UserDeletedEventArgs e) + { + if (UserDeleted != null) + { + UserDeleted(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserDeleteError Event + /// + /// + /// [cnurse] 11/30/2007 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserDeleteError(UserUpdateErrorArgs e) + { + if (UserDeleteError != null) + { + UserDeleteError(this, e); + } + } + + public void OnUserRestored(UserRestoredEventArgs e) + { + if (UserRestored != null) + { + UserRestored(this, e); + } + } + + public void OnUserRestoreError(UserUpdateErrorArgs e) + { + if (UserRestoreError != null) + { + UserRestoreError(this, e); + } + } + + public void OnUserRemoved(UserRemovedEventArgs e) + { + if (UserRemoved != null) + { + UserRemoved(this, e); + } + } + + public void OnUserRemoveError(UserUpdateErrorArgs e) + { + if (UserRemoveError != null) + { + UserRemoveError(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserUpdated Event + /// + /// + /// [cnurse] 03/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserUpdated(EventArgs e) + { + if (UserUpdated != null) + { + UserUpdated(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserUpdated Event + /// + /// + /// [cnurse] 03/01/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserUpdateCompleted(EventArgs e) + { + if (UserUpdateCompleted != null) + { + UserUpdateCompleted(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Raises the UserUpdateError Event + /// + /// + /// [cnurse] 02/07/2007 Created + /// + /// ----------------------------------------------------------------------------- + public void OnUserUpdateError(UserUpdateErrorArgs e) + { + if (UserUpdateError != null) + { + UserUpdateError(this, e); + } + } + + #endregion + + #region Nested type: BaseUserEventArgs + + /// ----------------------------------------------------------------------------- + /// + /// The BaseUserEventArgs class provides a base for User EventArgs classes + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public class BaseUserEventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Id of the User + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public int UserId { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Id of the User + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public string UserName { get; set; } + } + + #endregion + + #region Nested type: UserCreatedEventArgs + + /// ----------------------------------------------------------------------------- + /// + /// The UserCreatedEventArgs class provides a customised EventArgs class for + /// the UserCreated Event + /// + /// + /// [cnurse] 03/08/2006 created + /// + /// ----------------------------------------------------------------------------- + public class UserCreatedEventArgs + { + private UserCreateStatus _createStatus = UserCreateStatus.Success; + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new UserCreatedEventArgs + /// + /// The newly Created User + /// + /// [cnurse] 03/08/2006 Created + /// + /// ----------------------------------------------------------------------------- + public UserCreatedEventArgs(UserInfo newUser) + { + NewUser = newUser; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Create Status + /// + /// + /// [cnurse] 03/08/2006 Created + /// + /// ----------------------------------------------------------------------------- + public UserCreateStatus CreateStatus + { + get + { + return _createStatus; + } + set + { + _createStatus = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the New User + /// + /// + /// [cnurse] 03/08/2006 Created + /// + /// ----------------------------------------------------------------------------- + public UserInfo NewUser { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a flag whether to Notify the new User of the Creation + /// + /// + /// [cnurse] 03/08/2006 Created + /// + /// ----------------------------------------------------------------------------- + public bool Notify { get; set; } + } + + #endregion + + #region Nested type: UserDeletedEventArgs + + /// ----------------------------------------------------------------------------- + /// + /// The UserDeletedEventArgs class provides a customised EventArgs class for + /// the UserDeleted Event + /// + /// + /// [cnurse] 03/08/2006 created + /// + /// ----------------------------------------------------------------------------- + public class UserDeletedEventArgs : BaseUserEventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new UserDeletedEventArgs + /// + /// The Id of the User + /// The user name of the User + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public UserDeletedEventArgs(int id, string name) + { + UserId = id; + UserName = name; + } + } + + #endregion + + #region Nested type: UserRestoredEventArgs + + /// ----------------------------------------------------------------------------- + /// + /// The UserRestoredEventArgs class provides a customised EventArgs class for + /// the UserRestored Event + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public class UserRestoredEventArgs : BaseUserEventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new UserRestoredEventArgs + /// + /// The Id of the User + /// The user name of the User + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public UserRestoredEventArgs(int id, string name) + { + UserId = id; + UserName = name; + } + } + + #endregion + + #region Nested type: UserRemovedEventArgs + + /// ----------------------------------------------------------------------------- + /// + /// The UserRemovedEventArgs class provides a customised EventArgs class for + /// the UserRemoved Event + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + + public class UserRemovedEventArgs : BaseUserEventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new UserRemovedEventArgs + /// + /// The Id of the User + /// The user name of the User + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public UserRemovedEventArgs(int id, string name) + { + UserId = id; + UserName = name; + } + } + + + #endregion + + #region Nested type: UserUpdateErrorArgs + + /// ----------------------------------------------------------------------------- + /// + /// The UserUpdateErrorArgs class provides a customised EventArgs class for + /// the UserUpdateError Event + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public class UserUpdateErrorArgs : BaseUserEventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new UserUpdateErrorArgs + /// + /// The Id of the User + /// The user name of the User + /// The error message + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public UserUpdateErrorArgs(int id, string name, string message) + { + UserId = id; + UserName = name; + Message = message; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the error message + /// + /// + /// [cnurse] 02/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Message { get; set; } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Modules/VisibilityState.cs b/DNN Platform/Library/Entities/Modules/VisibilityState.cs new file mode 100644 index 00000000000..395d138329e --- /dev/null +++ b/DNN Platform/Library/Entities/Modules/VisibilityState.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Entities.Modules + /// Class : VisibilityState + /// ----------------------------------------------------------------------------- + /// + /// The VisibilityState enum provides an enumeration of the Visibility options + /// + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public enum VisibilityState + { + Maximized, + Minimized, + None + } +} diff --git a/DNN Platform/Library/Entities/Portals/Data/DataService.cs b/DNN Platform/Library/Entities/Portals/Data/DataService.cs new file mode 100644 index 00000000000..f55f892be5c --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Data/DataService.cs @@ -0,0 +1,67 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Entities.Portals.Data +{ + public class DataService : ComponentBase, IDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + + public int AddPortalGroup(PortalGroupInfo portalGroup, int createdByUserId) + { + return _provider.ExecuteScalar("AddPortalGroup", + portalGroup.PortalGroupName, + portalGroup.PortalGroupDescription, + portalGroup.MasterPortalId, + portalGroup.AuthenticationDomain, + createdByUserId); + } + + public void DeletePortalGroup(PortalGroupInfo portalGroup) + { + _provider.ExecuteNonQuery("DeletePortalGroup", portalGroup.PortalGroupId); + } + + public IDataReader GetPortalGroups() + { + return _provider.ExecuteReader("GetPortalGroups"); + } + + public void UpdatePortalGroup(PortalGroupInfo portalGroup, int lastModifiedByUserId) + { + _provider.ExecuteNonQuery("UpdatePortalGroup", + portalGroup.PortalGroupId, + portalGroup.PortalGroupName, + portalGroup.PortalGroupDescription, + portalGroup.AuthenticationDomain, + lastModifiedByUserId); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Data/IDataService.cs b/DNN Platform/Library/Entities/Portals/Data/IDataService.cs new file mode 100644 index 00000000000..2fe56c31832 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Data/IDataService.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +#endregion + +namespace DotNetNuke.Entities.Portals.Data +{ + public interface IDataService + { + int AddPortalGroup(PortalGroupInfo portalGroup, int createdByUserId); + + void DeletePortalGroup(PortalGroupInfo portalGroup); + + IDataReader GetPortalGroups(); + + void UpdatePortalGroup(PortalGroupInfo portalGroup, int lastModifiedByUserId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/IPortalController.cs b/DNN Platform/Library/Entities/Portals/IPortalController.cs new file mode 100644 index 00000000000..f7f4f996084 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/IPortalController.cs @@ -0,0 +1,316 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Entities.Portals +{ + /// + /// Do not implement. This interface is meant for reference and unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IPortalController + { + /// ----------------------------------------------------------------------------- + /// + /// Creates a new portal alias + /// + /// Id of the portal + /// Portal Alias to be created + /// + /// + /// + /// [cnurse] 01/11/2005 created + /// + /// ----------------------------------------------------------------------------- + void AddPortalAlias(int portalId, string portalAlias); + + + + /// + /// Copies the page template. + /// + /// The template file. + /// The mapped home directory. + void CopyPageTemplate(string templateFile, string mappedHomeDirectory); + + + + /// + /// Creates the portal. + /// + /// Name of the portal. + /// The obj admin user. + /// The description. + /// The key words. + /// The template path. + /// The template file. + /// The home directory. + /// The portal alias. + /// The server path. + /// The child path. + /// if set to true means the portal is child portal. + /// Portal id. + int CreatePortal(string portalName, UserInfo adminUser, string description, string keyWords, string templatePath, string templateFile, string homeDirectory, string portalAlias, + string serverPath, string childPath, bool isChildPortal); + + + /// ----------------------------------------------------------------------------- + /// + /// Creates a new portal. + /// + /// Name of the portal to be created + /// Portal Administrator's first name + /// Portal Administrator's last name + /// Portal Administrator's username + /// Portal Administrator's password + /// Portal Administrator's email + /// Description for the new portal + /// KeyWords for the new portal + /// Path where the templates are stored + /// Template file + /// Home Directory + /// Portal Alias String + /// The Path to the root of the Application + /// The Path to the Child Portal Folder + /// True if this is a child portal + /// PortalId of the new portal if there are no errors, -1 otherwise. + /// + /// After the selected portal template is parsed the admin template ("admin.template") will be + /// also processed. The admin template should only contain the "Admin" menu since it's the same + /// on all portals. The selected portal template can contain a node to specify portal + /// properties and a node to define the roles that will be created on the portal by default. + /// + /// + /// [cnurse] 11/08/2004 created (most of this code was moved from SignUp.ascx.vb) + /// + /// ----------------------------------------------------------------------------- + int CreatePortal(string portalName, string firstName, string lastName, string username, string password, string email, string description, string keyWords, string templatePath, + string templateFile, string homeDirectory, string portalAlias, string serverPath, string childPath, bool isChildPortal); + + /// + /// Creates the portal. + /// + /// Name of the portal. + /// The obj admin user. + /// The description. + /// The key words. + /// + /// The home directory. + /// The portal alias. + /// The server path. + /// The child path. + /// if set to true means the portal is child portal. + /// Portal id. + int CreatePortal(string portalName, UserInfo adminUser, string description, string keyWords, + PortalController.PortalTemplateInfo template, + string homeDirectory, string portalAlias, string serverPath, string childPath, + bool isChildPortal); + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a portal permanently + /// + /// PortalId of the portal to be deleted + /// + /// + /// + /// [VMasanas] 03/09/2004 Created + /// [VMasanas] 26/10/2004 Remove dependent data (skins, modules) + /// [cnurse] 24/11/2006 Removal of Modules moved to sproc + /// + /// ----------------------------------------------------------------------------- + void DeletePortalInfo(int portalId); + + + + /// ----------------------------------------------------------------------------- + /// + /// Gets information of a portal + /// + /// Id of the portal + /// PortalInfo object with portal definition + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + PortalInfo GetPortal(int portalId); + + PortalInfo GetPortal(int portalId, string cultureCode); + + List GetPortalList(string cultureCode); + + /// ----------------------------------------------------------------------------- + /// + /// Gets information from all portals + /// + /// ArrayList of PortalInfo objects + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + ArrayList GetPortals(); + + /// + /// Gets the portal. + /// + /// The unique id. + /// Portal info. + PortalInfo GetPortal(Guid uniqueId); + + /// ----------------------------------------------------------------------------- + /// + /// Gets the space used at the host level + /// + /// Space used in bytes + /// + /// + /// + /// [VMasanas] 19/04/2006 Created + /// + /// ----------------------------------------------------------------------------- + long GetPortalSpaceUsedBytes(); + + /// + /// Gets the portal space used bytes. + /// + /// The portal id. + /// Space used in bytes + long GetPortalSpaceUsedBytes(int portalId); + + /// ----------------------------------------------------------------------------- + /// + /// Verifies if there's enough space to upload a new file on the given portal + /// + /// Id of the portal + /// Size of the file being uploaded + /// True if there's enough space available to upload the file + /// + /// + /// + /// [VMasanas] 19/04/2006 Created + /// + /// ----------------------------------------------------------------------------- + bool HasSpaceAvailable(int portalId, long fileSizeBytes); + + /// + /// Remaps the Special Pages such as Home, Profile, Search + /// to their localized versions + /// + /// + /// + void MapLocalizedSpecialPages(int portalId, string cultureCode); + + /// ----------------------------------------------------------------------------- + /// + /// Processess a template file for the new portal. This method will be called twice: for the portal template and for the admin template + /// + /// PortalId of the new portal + /// Path for the folder where templates are stored + /// Template file to process + /// UserId for the portal administrator. This is used to assign roles to this user + /// Flag to determine whether Module content is merged. + /// Flag to determine is the template is applied to an existing portal or a new one. + /// + /// The roles and settings nodes will only be processed on the portal template file. + /// + /// + /// [VMasanas] 27/08/2004 Created + /// + /// ----------------------------------------------------------------------------- + void ParseTemplate(int portalId, string templatePath, string templateFile, int administratorId, PortalTemplateModuleAction mergeTabs, bool isNewPortal); + + /// ----------------------------------------------------------------------------- + /// + /// Processes the resource file for the template file selected + /// + /// New portal's folder + /// Selected template file + /// + /// The resource file is a zip file with the same name as the selected template file and with + /// an extension of .resources (to unable this file being downloaded). + /// For example: for template file "portal.template" a resource file "portal.template.resources" can be defined. + /// + /// + /// [VMasanas] 10/09/2004 Created + /// [cnurse] 11/08/2004 Moved from SignUp to PortalController + /// [cnurse] 03/04/2005 made Public + /// [cnurse] 05/20/2005 moved most of processing to new method in FileSystemUtils + /// + /// ----------------------------------------------------------------------------- + void ProcessResourceFile(string portalPath, string templateFile); + + /// + /// Updates the portal expiry. + /// + /// The portal id. + void UpdatePortalExpiry(int portalId); + + /// + /// Updates the portal expiry. + /// + /// The portal id. + /// The culture code. + void UpdatePortalExpiry(int portalId, string cultureCode); + + /// ----------------------------------------------------------------------------- + /// + /// Updates basic portal information + /// + /// + /// + /// + /// + /// [cnurse] 10/13/2004 created + /// + /// ----------------------------------------------------------------------------- + void UpdatePortalInfo(PortalInfo portal); + + /// + /// Gets the current portal settings. + /// + /// portal settings. + PortalSettings GetCurrentPortalSettings(); + + /// + /// Get all the available portal templates grouped by culture + /// + /// List of PortalTemplateInfo objects + IList GetAvailablePortalTemplates(); + + /// + /// Load info for a portal template + /// + /// The file name of the portal template + /// the culture code if any for the localization of the portal template + /// A portal template + PortalController.PortalTemplateInfo GetPortalTemplate(string templateFileName, string cultureCode); + } +} + + diff --git a/DNN Platform/Library/Entities/Portals/IPortalGroupController.cs b/DNN Platform/Library/Entities/Portals/IPortalGroupController.cs new file mode 100644 index 00000000000..6a0d3569fe7 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/IPortalGroupController.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + public interface IPortalGroupController + { + int AddPortalGroup(PortalGroupInfo portalGroup); + + void AddPortalToGroup(PortalInfo portal, PortalGroupInfo portalGroup, UserCopiedCallback callback); + + void DeletePortalGroup(PortalGroupInfo portalGroup); + + IEnumerable GetPortalGroups(); + + IEnumerable GetPortalsByGroup(int portalGroupId); + + void RemovePortalFromGroup(PortalInfo portal, PortalGroupInfo portalGroup, bool copyUsers, UserCopiedCallback callback); + + void UpdatePortalGroup(PortalGroupInfo portalGroup); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/IPortalSettings.cs b/DNN Platform/Library/Entities/Portals/IPortalSettings.cs new file mode 100644 index 00000000000..8a3d775e6ac --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/IPortalSettings.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Portals.Internal +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IPortalSettings + { + string AdministratorRoleName { get; } + } +} diff --git a/DNN Platform/Library/Entities/Portals/Internal/IPortalAliasController.cs b/DNN Platform/Library/Entities/Portals/Internal/IPortalAliasController.cs new file mode 100644 index 00000000000..aa8fac4b6ed --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/IPortalAliasController.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Portals.Internal +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IPortalAliasController + { + /// + /// Add a new Portal Alias + /// + /// The portal alias to add + /// The Id of the newly added portal alias + int AddPortalAlias(PortalAliasInfo portalAlias); + + /// + /// Delete a Portal Alias + /// + /// The portal alias to remove + void DeletePortalAlias(PortalAliasInfo portalAlias); + + /// + /// Gets the portal alias info. + /// + /// The portal alias. + /// Portal alias info + PortalAliasInfo GetPortalAlias(string alias); + + /// + /// Gets the portal alias by portal ID. + /// + /// The portal ID. + /// Portal alias collection. + IEnumerable GetPortalAliasesByPortalId(int portalId); + + /// + /// Gets all the portal aliases defined + /// + /// A dictionary keyed by the HTTP Alias + IDictionary GetPortalAliases(); + + /// + /// Updates the portal alias info. + /// + /// The obj portal alias info. + void UpdatePortalAlias(PortalAliasInfo portalAlias); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/IPortalTemplateIO.cs b/DNN Platform/Library/Entities/Portals/Internal/IPortalTemplateIO.cs new file mode 100644 index 00000000000..ad76154d805 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/IPortalTemplateIO.cs @@ -0,0 +1,36 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.IO; + +namespace DotNetNuke.Entities.Portals.Internal +{ + public interface IPortalTemplateIO + { + IEnumerable EnumerateTemplates(); + IEnumerable EnumerateLanguageFiles(); + string GetResourceFilePath(string templateFilePath); + string GetLanguageFilePath(string templateFilePath, string cultureCode); + TextReader OpenTextReader(string filePath); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/PortalAliasControllerImpl.cs b/DNN Platform/Library/Entities/Portals/Internal/PortalAliasControllerImpl.cs new file mode 100644 index 00000000000..7cfbc0495e2 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/PortalAliasControllerImpl.cs @@ -0,0 +1,140 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +namespace DotNetNuke.Entities.Portals.Internal +{ + internal class PortalAliasControllerImpl : IPortalAliasController + { + private readonly DataProvider _dataProvider = DataProvider.Instance(); + + #region Private Methods + + private static void ClearCache(bool refreshServiceRoutes) + { + DataCache.RemoveCache(DataCache.PortalAliasCacheKey); + CacheController.FlushPageIndexFromCache(); + if (refreshServiceRoutes) + { + ServicesRoutingManager.ReRegisterServiceRoutesWhileSiteIsRunning(); + } + } + + private static CacheItemArgs GetCacheArgs() + { + return new CacheItemArgs(DataCache.PortalAliasCacheKey, DataCache.PortalAliasCacheTimeOut, DataCache.PortalAliasCachePriority); + } + + private static object GetPortalAliasesCallBack(CacheItemArgs cacheItemArgs) + { + var dic = CBO.FillDictionary("HTTPAlias", DataProvider.Instance().GetPortalAliasByPortalID(-1)); + return dic.Keys.ToDictionary(key => key.ToLowerInvariant(), key => dic[key]); + } + + private static void LogEvent(PortalAliasInfo portalAlias, EventLogController.EventLogType logType) + { + int userId = UserController.GetCurrentUserInfo().UserID; + var eventLogController = new EventLogController(); + eventLogController.AddLog(portalAlias, PortalController.GetCurrentPortalSettings(), userId, "", logType); + } + + #endregion + + #region IPortalAliasController Implementation + + public int AddPortalAlias(PortalAliasInfo portalAlias) + { + //Add Alias + int Id = _dataProvider.AddPortalAlias(portalAlias.PortalID, + portalAlias.HTTPAlias.ToLower().Trim('/'), + portalAlias.CultureCode, + portalAlias.Skin, + portalAlias.BrowserType.ToString(), + portalAlias.IsPrimary, + UserController.GetCurrentUserInfo().UserID); + + //Log Event + LogEvent(portalAlias, EventLogController.EventLogType.PORTALALIAS_CREATED); + + //clear portal alias cache + ClearCache(true); + + return Id; + } + + public void DeletePortalAlias(PortalAliasInfo portalAlias) + { + //Delete Alias + DataProvider.Instance().DeletePortalAlias(portalAlias.PortalAliasID); + + //Log Event + LogEvent(portalAlias, EventLogController.EventLogType.PORTALALIAS_DELETED); + + //clear portal alias cache + ClearCache(false); + } + + public IEnumerable GetPortalAliasesByPortalId(int portalId) + { + return GetPortalAliases().Values.Where(alias => alias.PortalID == portalId).ToList(); + } + + public IDictionary GetPortalAliases() + { + return CBO.GetCachedObject>(GetCacheArgs(), GetPortalAliasesCallBack, true); + } + + public PortalAliasInfo GetPortalAlias(string alias) + { + return PortalAliasController.GetPortalAliasInfo(alias); + } + + public void UpdatePortalAlias(PortalAliasInfo portalAlias) + { + //Update Alias + DataProvider.Instance().UpdatePortalAliasInfo(portalAlias.PortalAliasID, + portalAlias.PortalID, + portalAlias.HTTPAlias.ToLower().Trim('/'), + portalAlias.CultureCode, + portalAlias.Skin, + portalAlias.BrowserType.ToString(), + portalAlias.IsPrimary, + UserController.GetCurrentUserInfo().UserID); + //Log Event + LogEvent(portalAlias, EventLogController.EventLogType.PORTALALIAS_UPDATED); + + //clear portal alias cache + ClearCache(false); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIO.cs b/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIO.cs new file mode 100644 index 00000000000..a774e663564 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIO.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Entities.Portals.Internal +{ + public class PortalTemplateIO : ServiceLocator + { + protected override Func GetFactory() + { + return () => new PortalTemplateIOImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIOImpl.cs b/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIOImpl.cs new file mode 100644 index 00000000000..e2adc481c33 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/PortalTemplateIOImpl.cs @@ -0,0 +1,87 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using DotNetNuke.Common; + +namespace DotNetNuke.Entities.Portals.Internal +{ + //It seems that resx files are not loaded into the DNN filemanager + //so we are stuck with direct disk IO + public class PortalTemplateIOImpl : IPortalTemplateIO + { + #region IPortalTemplateIO Members + + public IEnumerable EnumerateTemplates() + { + string path = Globals.HostMapPath; + if (Directory.Exists(path)) + { + return Directory.GetFiles(path, "*.template").Where(x => Path.GetFileNameWithoutExtension(x) != "admin"); + } + + return new string[0]; + } + + public IEnumerable EnumerateLanguageFiles() + { + string path = Globals.HostMapPath; + if (Directory.Exists(path)) + { + return Directory.GetFiles(path, "*.template.??-??.resx"); + } + + return new string[0]; + } + + public string GetResourceFilePath(string templateFilePath) + { + return CheckFilePath(templateFilePath + ".resources"); + } + + public string GetLanguageFilePath(string templateFilePath, string cultureCode) + { + return CheckFilePath(string.Format("{0}.{1}.resx", templateFilePath, cultureCode)); + } + + public TextReader OpenTextReader(string filePath) + { + return new StreamReader(File.Open(filePath, FileMode.Open)); + } + + private static string CheckFilePath(string path) + { + if (File.Exists(path)) + { + return path; + } + + return ""; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/TestablePortalAliasController.cs b/DNN Platform/Library/Entities/Portals/Internal/TestablePortalAliasController.cs new file mode 100644 index 00000000000..4d1d7630ea4 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/TestablePortalAliasController.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Entities.Portals.Internal +{ + public class TestablePortalAliasController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new PortalAliasControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/Internal/TestablePortalController.cs b/DNN Platform/Library/Entities/Portals/Internal/TestablePortalController.cs new file mode 100644 index 00000000000..038b955706f --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/Internal/TestablePortalController.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Entities.Portals.Internal +{ + public class TestablePortalController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new PortalController(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalAliasCollection.cs b/DNN Platform/Library/Entities/Portals/PortalAliasCollection.cs new file mode 100644 index 00000000000..fa86c18d24c --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalAliasCollection.cs @@ -0,0 +1,89 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + [Serializable] + [Obsolete("Deprecated in DNN 7.1. Use Dictionary")] + public class PortalAliasCollection : DictionaryBase + { + /// + /// Gets or sets the value associated with the specified key. + /// + public PortalAliasInfo this[string key] + { + get + { + return (PortalAliasInfo) Dictionary[key]; + } + set + { + Dictionary[key] = value; + } + } + + /// + /// Gets a value indicating if the collection contains keys that are not null. + /// + public Boolean HasKeys + { + get + { + return Dictionary.Keys.Count > 0; + } + } + + public ICollection Keys + { + get + { + return Dictionary.Keys; + } + } + + public ICollection Values + { + get + { + return Dictionary.Values; + } + } + + public bool Contains(String key) + { + return Dictionary.Contains(key); + } + + /// + /// Adds an entry to the collection. + /// + public void Add(String key, PortalAliasInfo value) + { + Dictionary.Add(key, value); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalAliasController.cs b/DNN Platform/Library/Entities/Portals/PortalAliasController.cs new file mode 100644 index 00000000000..16273802344 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalAliasController.cs @@ -0,0 +1,419 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + /// + /// PortalAliasController provides method to manage portal alias. + /// + /// + /// For DotNetNuke to know what site a request should load, it uses a system of portal aliases. + /// When a request is recieved by DotNetNuke from IIS, it extracts the domain name portion and does a comparison against + /// the list of portal aliases and then redirects to the relevant portal to load the approriate page. + /// + public class PortalAliasController + { + #region Private Methods + + private static object GetPortalAliasLookupCallBack(CacheItemArgs cacheItemArgs) + { +#pragma warning disable 612,618 + return new PortalAliasController().GetPortalAliases(); +#pragma warning restore 612,618 + } + + private static bool ValidateAlias(string portalAlias, bool ischild, bool isDomain) + { + bool isValid = true; + + string validChars = "abcdefghijklmnopqrstuvwxyz0123456789-/"; + if (!ischild) + { + validChars += ".:"; + } + + if (!isDomain) + { + validChars += "_"; + } + + foreach (char c in portalAlias) + { + if (!validChars.Contains(c.ToString())) + { + isValid = false; + break; + } + } + + return isValid; + } + + #endregion + + #region Public Methods + + /// + /// Gets the portal alias. + /// + /// The portal alias. + /// The portal ID. + /// Portal Alias Info. + public PortalAliasInfo GetPortalAlias(string PortalAlias, int PortalID) + { + return (PortalAliasInfo)CBO.FillObject(DataProvider.Instance().GetPortalAlias(PortalAlias, PortalID), typeof(PortalAliasInfo)); + } + + /// + /// Gets the portal alias by portal alias ID. + /// + /// The portal alias ID. + /// Portal alias info. + public PortalAliasInfo GetPortalAliasByPortalAliasID(int PortalAliasID) + { + return (PortalAliasInfo)CBO.FillObject((DataProvider.Instance().GetPortalAliasByPortalAliasID(PortalAliasID)), typeof(PortalAliasInfo)); + } + + /// + /// Gets the portal by portal alias ID. + /// + /// The portal alias id. + /// Portal info. + public PortalInfo GetPortalByPortalAliasID(int PortalAliasId) + { + return (PortalInfo)CBO.FillObject(DataProvider.Instance().GetPortalByPortalAliasID(PortalAliasId), typeof(PortalInfo)); + } + + #endregion + + #region Public Static Methods + + /// + /// Gets the portal alias by portal. + /// + /// The portal id. + /// The portal alias. + /// Portal alias. + public static string GetPortalAliasByPortal(int portalId, string portalAlias) + { + string retValue = ""; + + //get the portal alias collection from the cache + var portalAliasCollection = TestablePortalAliasController.Instance.GetPortalAliases(); + string httpAlias; + bool foundAlias = false; + + //Do a specified PortalAlias check first + PortalAliasInfo portalAliasInfo; + if (portalAliasCollection.ContainsKey(portalAlias)) + { + portalAliasInfo = portalAliasCollection[portalAlias.ToLower()]; + if (portalAliasInfo != null) + { + if (portalAliasInfo.PortalID == portalId) + { + //set the alias + retValue = portalAliasInfo.HTTPAlias; + foundAlias = true; + } + } + } + + + if (!foundAlias) + { + //searching from longest to shortest alias ensures that the most specific portal is matched first + //In some cases this method has been called with "portalaliases" that were not exactly the real portal alias + //the startswith behaviour is preserved here to support those non-specific uses + IEnumerable aliases = portalAliasCollection.Keys.Cast().OrderByDescending(k => k.Length); + foreach (var currentAlias in aliases) + { + // check if the alias key starts with the portal alias value passed in - we use + // StartsWith because child portals are redirected to the parent portal domain name + // eg. child = 'www.domain.com/child' and parent is 'www.domain.com' + // this allows the parent domain name to resolve to the child alias ( the tabid still identifies the child portalid ) + if (portalAliasCollection.ContainsKey(currentAlias)) + { + portalAliasInfo = portalAliasCollection[currentAlias]; + httpAlias = portalAliasInfo.HTTPAlias.ToLower(); + if (httpAlias.StartsWith(portalAlias.ToLower()) && portalAliasInfo.PortalID == portalId) + { + retValue = portalAliasInfo.HTTPAlias; + break; + } + httpAlias = httpAlias.StartsWith("www.") ? httpAlias.Replace("www.", "") : string.Concat("www.", httpAlias); + if (httpAlias.StartsWith(portalAlias.ToLower()) && portalAliasInfo.PortalID == portalId) + { + retValue = portalAliasInfo.HTTPAlias; + break; + } + } + } + } + return retValue; + } + + /// + /// Gets the portal alias by tab. + /// + /// The tab ID. + /// The portal alias. + /// Portal alias. + public static string GetPortalAliasByTab(int TabID, string PortalAlias) + { + string retValue = Null.NullString; + int intPortalId = -2; + + //get the tab + var objTabs = new TabController(); + TabInfo objTab = objTabs.GetTab(TabID, Null.NullInteger, false); + if (objTab != null) + { + //ignore deleted tabs + if (!objTab.IsDeleted) + { + intPortalId = objTab.PortalID; + } + } + switch (intPortalId) + { + case -2: //tab does not exist + break; + case -1: //host tab + //host tabs are not verified to determine if they belong to the portal alias + retValue = PortalAlias; + break; + default: //portal tab + retValue = GetPortalAliasByPortal(intPortalId, PortalAlias); + break; + } + return retValue; + } + + /// + /// Gets the portal alias info. + /// + /// The portal alias. + /// Portal alias info + public static PortalAliasInfo GetPortalAliasInfo(string httpAlias) + { + string strPortalAlias; + + //try the specified alias first + PortalAliasInfo portalAlias = GetPortalAliasLookup(httpAlias.ToLower()); + + //domain.com and www.domain.com should be synonymous + if (portalAlias == null) + { + if (httpAlias.ToLower().StartsWith("www.")) + { + //try alias without the "www." prefix + strPortalAlias = httpAlias.Replace("www.", ""); + } + else //try the alias with the "www." prefix + { + strPortalAlias = string.Concat("www.", httpAlias); + } + //perform the lookup + portalAlias = GetPortalAliasLookup(strPortalAlias.ToLower()); + } + //allow domain wildcards + if (portalAlias == null) + { + //remove the domain prefix ( ie. anything.domain.com = domain.com ) + if (httpAlias.IndexOf(".", StringComparison.Ordinal) != -1) + { + strPortalAlias = httpAlias.Substring(httpAlias.IndexOf(".", StringComparison.Ordinal) + 1); + } + else //be sure we have a clean string (without leftovers from preceding 'if' block) + { + strPortalAlias = httpAlias; + } + //try an explicit lookup using the wildcard entry ( ie. *.domain.com ) + portalAlias = GetPortalAliasLookup("*." + strPortalAlias.ToLower()) ?? + GetPortalAliasLookup(strPortalAlias.ToLower()); + + if (portalAlias == null) + { + //try a lookup using "www." + raw domain + portalAlias = GetPortalAliasLookup("www." + strPortalAlias.ToLower()); + } + } + if (portalAlias == null) + { + //check if this is a fresh install ( no alias values in collection ) + var portalAliases = TestablePortalAliasController.Instance.GetPortalAliases(); + if (portalAliases.Keys.Count == 0 || (portalAliases.Count == 1 && portalAliases.ContainsKey("_default"))) + { + //relate the PortalAlias to the default portal on a fresh database installation + DataProvider.Instance().UpdatePortalAlias(httpAlias.ToLower().Trim('/'), UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalAlias", + httpAlias, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALALIAS_UPDATED); + + //clear the cachekey "GetPortalByAlias" otherwise portalalias "_default" stays in cache after first install + DataCache.RemoveCache("GetPortalByAlias"); + //try again + portalAlias = GetPortalAliasLookup(httpAlias.ToLower()); + } + } + return portalAlias; + } + + /// + /// Gets the portal alias lookup. + /// + /// The alias. + /// Porta lAlias Info + public static PortalAliasInfo GetPortalAliasLookup(string httpAlias) + { + PortalAliasInfo alias = null; + var aliases = TestablePortalAliasController.Instance.GetPortalAliases(); + if (aliases.ContainsKey(httpAlias)) + { + alias = TestablePortalAliasController.Instance.GetPortalAliases()[httpAlias]; + } + return alias; + } + + /// + /// Validates the alias. + /// + /// The portal alias. + /// if set to true [ischild]. + /// true if the alias is a valid url format; otherwise return false. + public static bool ValidateAlias(string portalAlias, bool ischild) + { + if (ischild) + { + return ValidateAlias(portalAlias, true, false); + } + //validate the domain + Uri result; + if (Uri.TryCreate(Globals.AddHTTP(portalAlias), UriKind.Absolute, out result)) + { + return ValidateAlias(result.Host, false, true) && ValidateAlias(portalAlias, false, false); + } + return false; + } + + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.AddPortalAlias")] + public int AddPortalAlias(PortalAliasInfo portalAlias) + { + return TestablePortalAliasController.Instance.AddPortalAlias(portalAlias); + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.DeletePortalAlias")] + public void DeletePortalAlias(int portalAliasId) + { + + DataProvider.Instance().DeletePortalAlias(portalAliasId); + + var eventLogController = new EventLogController(); + eventLogController.AddLog("PortalAliasID", + portalAliasId.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTALALIAS_DELETED); + + DataCache.RemoveCache(DataCache.PortalAliasCacheKey); + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.GetPortalAliasesByPortalId")] + public ArrayList GetPortalAliasArrayByPortalID(int PortalID) + { + return new ArrayList(TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(PortalID).ToArray()); + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.GetPortalAliasesByPortalId")] + public PortalAliasCollection GetPortalAliasByPortalID(int PortalID) + { + var portalAliasCollection = new PortalAliasCollection(); + + foreach (PortalAliasInfo alias in GetPortalAliasLookup().Values.Cast().Where(alias => alias.PortalID == PortalID)) + { + portalAliasCollection.Add(alias.HTTPAlias, alias); + } + + return portalAliasCollection; + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.GetPortalAliases")] + public PortalAliasCollection GetPortalAliases() + { + var portalAliasCollection = new PortalAliasCollection(); + foreach (var kvp in TestablePortalAliasController.Instance.GetPortalAliases()) + { + portalAliasCollection.Add(kvp.Key, kvp.Value); + } + + return portalAliasCollection; + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.GetPortalAliases")] + public static PortalAliasCollection GetPortalAliasLookup() + { + var portalAliasCollection = new PortalAliasCollection(); + foreach (var kvp in TestablePortalAliasController.Instance.GetPortalAliases()) + { + portalAliasCollection.Add(kvp.Key, kvp.Value); + } + + return portalAliasCollection; + } + + [Obsolete("Deprecated in version 7.1. Replaced by TestablePortalAliasController.Instance.UpdatePortalAlias")] + public void UpdatePortalAliasInfo(PortalAliasInfo portalAlias) + { + TestablePortalAliasController.Instance.UpdatePortalAlias(portalAlias); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Portals/PortalAliasExtensions.cs b/DNN Platform/Library/Entities/Portals/PortalAliasExtensions.cs new file mode 100644 index 00000000000..e1f65e40ea2 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalAliasExtensions.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; + +using DotNetNuke.Entities.Urls; + +namespace DotNetNuke.Entities.Portals +{ + public static class PortalAliasExtensions + { + public static bool ContainsAlias(this IEnumerable aliases, int portalId, string httpAlias) + { + return aliases.Where(alias => alias.PortalID == portalId || portalId == -1) + .Any(alias => String.Compare(alias.HTTPAlias, httpAlias, StringComparison.OrdinalIgnoreCase) == 0); + } + + public static bool ContainsSpecificSkins(this IEnumerable aliases) + { + return aliases.Any(alias => !String.IsNullOrEmpty(alias.Skin)); + } + + public static Dictionary GetAliasesAndCulturesForPortalId(this IEnumerable aliases, int portalId) + { + var aliasCultures = new Dictionary(); + foreach (var cpa in aliases) + { + if (aliasCultures.ContainsKey(cpa.HTTPAlias) == false) + { + aliasCultures.Add(cpa.HTTPAlias.ToLowerInvariant(), cpa.CultureCode); + } + } + return aliasCultures; + } + + /// + /// Returns the chosen portal alias for a specific portal Id and culture Code + /// + /// + /// + /// + /// Detects the current browser type if possible. If can't be deteced 'normal' is used. If a specific browser type is required, use overload with browser type. + /// + public static PortalAliasInfo GetAliasByPortalIdAndSettings(this IEnumerable aliases, int portalId, UrlAction result, string cultureCode, FriendlyUrlSettings settings) + { + var browserType = BrowserTypes.Normal; + //if required, and possible, detect browser type + if (HttpContext.Current != null && settings != null) + { + HttpRequest request = HttpContext.Current.Request; + HttpResponse response = HttpContext.Current.Response; + browserType = FriendlyUrlController.GetBrowserType(request, response, settings); + } + + return GetAliasByPortalIdAndSettings(aliases, portalId, result, cultureCode, browserType); + } + + public static PortalAliasInfo GetAliasByPortalIdAndSettings(this IEnumerable aliases, UrlAction result) + { + return GetAliasByPortalIdAndSettings(aliases, result.PortalId, result, result.CultureCode, result.BrowserType); + } + + /// + /// Returns a ChosenPortalAlias object where the portalId, culture code and isMobile matches + /// + /// + /// + /// + /// + /// + /// A ChosenPOrtalAlias + /// Note will return a best-match by portal if no specific culture Code match found + public static PortalAliasInfo GetAliasByPortalIdAndSettings(this IEnumerable aliases, int portalId, UrlAction result, string cultureCode, BrowserTypes browserType) + { + var aliasList = aliases.ToList(); + + var defaultAlias = aliasList.ToList().Where(a => a.PortalID == portalId) + .OrderByDescending(a => a.IsPrimary) + .FirstOrDefault(); + + //27138 : Redirect loop caused by duplicate primary aliases. Changed to only check by browserType/Culture code which makes a primary alias + var foundAlias = aliasList.Where(a => a.BrowserType == browserType + && (String.Compare(a.CultureCode, cultureCode, StringComparison.OrdinalIgnoreCase) == 0 || String.IsNullOrEmpty(a.CultureCode)) + && a.PortalID == portalId) + .OrderByDescending(a => a.IsPrimary) + .ThenByDescending(a => a.CultureCode) + .FirstOrDefault(); + + if (foundAlias != null) + { + if(result !=null && result.PortalAlias != null) + { + if (foundAlias.BrowserType != result.PortalAlias.BrowserType) + { + result.Reason = foundAlias.CultureCode != result.PortalAlias.CultureCode + ? RedirectReason.Wrong_Portal_Alias_For_Culture_And_Browser + : RedirectReason.Wrong_Portal_Alias_For_Browser_Type; + } + else + { + if (foundAlias.CultureCode != result.PortalAlias.CultureCode) + { + result.Reason = RedirectReason.Wrong_Portal_Alias_For_Culture; + } + } + } + } + else + { + foundAlias = defaultAlias; + } + + //if we didn't find a specific match, return the default, which is the closest match + return foundAlias; + } + + public static List GetAliasesForPortalId(this IEnumerable aliases, int portalId) + { + var httpAliases = new List(); + foreach (var cpa in aliases.Where(cpa => httpAliases.Contains(cpa.HTTPAlias) == false)) + { + httpAliases.Add(cpa.HTTPAlias.ToLowerInvariant()); + } + return httpAliases; + } + + public static string GetCultureByPortalIdAndAlias(this IEnumerable aliases, int portalId, string alias) + { + return (from cpa in aliases + where cpa.PortalID == portalId && String.Compare(alias, cpa.HTTPAlias, StringComparison.OrdinalIgnoreCase) == 0 + select cpa.CultureCode) + .FirstOrDefault(); + } + + public static void GetSettingsByPortalIdAndAlias(this IEnumerable aliases, int portalId, string alias, out string culture, out BrowserTypes browserType, out string skin) + { + culture = null; + browserType = BrowserTypes.Normal; + skin = ""; + foreach (var cpa in aliases) + { + if (cpa.PortalID == portalId && String.Compare(alias, cpa.HTTPAlias, StringComparison.OrdinalIgnoreCase) == 0) + { + //this is a match + culture = cpa.CultureCode; + browserType = cpa.BrowserType; + //852 : add skin per portal alias + skin = cpa.Skin; + break; + } + } + } + + + } +} diff --git a/DNN Platform/Library/Entities/Portals/PortalAliasInfo.cs b/DNN Platform/Library/Entities/Portals/PortalAliasInfo.cs new file mode 100644 index 00000000000..142a04a8620 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalAliasInfo.cs @@ -0,0 +1,163 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Data; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Urls; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + [Serializable] + public class PortalAliasInfo : BaseEntityInfo, IHydratable, IXmlSerializable + { + public PortalAliasInfo() {} + + public PortalAliasInfo(PortalAliasInfo alias) + { + HTTPAlias = alias.HTTPAlias; + PortalAliasID = alias.PortalAliasID; + PortalID = alias.PortalID; + IsPrimary = alias.IsPrimary; + Redirect = alias.Redirect; + BrowserType = alias.BrowserType; + CultureCode = alias.CultureCode; + Skin = alias.Skin; + } + + #region Auto-Properties + + public string HTTPAlias { get; set; } + public int PortalAliasID { get; set; } + public int PortalID { get; set; } + public bool IsPrimary { get; set; } + public bool Redirect { get; set; } + + public BrowserTypes BrowserType { get; set; } + public string CultureCode { get; set; } + public string Skin { get; set; } + + #endregion + + #region IHydratable Members + + public int KeyID + { + get { return PortalAliasID; } + set { PortalAliasID = value; } + } + + public void Fill(IDataReader dr) + { + base.FillInternal(dr); + + PortalAliasID = Null.SetNullInteger(dr["PortalAliasID"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + HTTPAlias = Null.SetNullString(dr["HTTPAlias"]); + IsPrimary = Null.SetNullBoolean(dr["IsPrimary"]); + var browserType = Null.SetNullString(dr["BrowserType"]); + BrowserType = String.IsNullOrEmpty(browserType) || browserType.ToLowerInvariant() == "normal" + ? BrowserTypes.Normal + : BrowserTypes.Mobile; + CultureCode = Null.SetNullString(dr["CultureCode"]); + Skin = Null.SetNullString(dr["Skin"]); + } + + #endregion + + #region IXmlSerializable Members + + public XmlSchema GetSchema() + { + return null; + } + + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + switch (reader.Name) + { + case "portalID": + PortalID = reader.ReadElementContentAsInt(); + break; + case "portalAliasID": + PortalAliasID = reader.ReadElementContentAsInt(); + break; + case "HTTPAlias": + HTTPAlias = reader.ReadElementContentAsString(); + break; + case "skin": + Skin = reader.ReadElementContentAsString(); + break; + case "cultureCode": + CultureCode = reader.ReadElementContentAsString(); + break; + case "browserType": + string type = reader.ReadElementContentAsString(); + BrowserType = type.ToLowerInvariant() == "mobile" ? BrowserTypes.Mobile : BrowserTypes.Normal; + break; + case "primary": + IsPrimary = reader.ReadElementContentAsBoolean(); + break; + } + } + } + + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("portalAlias"); + + //write out properties + writer.WriteElementString("portalID", PortalID.ToString()); + writer.WriteElementString("portalAliasID", PortalAliasID.ToString()); + writer.WriteElementString("HTTPAlias", HTTPAlias); + writer.WriteElementString("skin", Skin); + writer.WriteElementString("cultureCode", CultureCode); + writer.WriteElementString("browserType", BrowserType.ToString().ToLowerInvariant()); + writer.WriteElementString("primary", IsPrimary.ToString().ToLowerInvariant()); + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalController.cs b/DNN Platform/Library/Entities/Portals/PortalController.cs new file mode 100644 index 00000000000..72ae8b9e14f --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalController.cs @@ -0,0 +1,3521 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Web; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content.Workflow; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Membership; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Installer; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Web.Client; + +using ICSharpCode.SharpZipLib.Zip; + +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + /// + /// PoralController provides business layer of poatal. + /// + /// + /// DotNetNuke supports the concept of virtualised sites in a single install. This means that multiple sites, + /// each potentially with multiple unique URL's, can exist in one instance of DotNetNuke i.e. one set of files and one database. + /// + public class PortalController : IPortalController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (PortalController)); + + #region const values + + public const string HtmlText_TimeToAutoSave = "HtmlText_TimeToAutoSave"; + public const string HtmlText_AutoSaveEnabled = "HtmlText_AutoSaveEnabled"; + + #endregion + + #region Private Methods + + private void AddFolderPermissions(int portalId, int folderId) + { + var objPortal = GetPortal(portalId); + FolderPermissionInfo objFolderPermission; + var folderManager = FolderManager.Instance; + var folder = folderManager.GetFolder(folderId); + var objPermissionController = new PermissionController(); + foreach (PermissionInfo objpermission in objPermissionController.GetPermissionByCodeAndKey("SYSTEM_FOLDER", "")) + { + objFolderPermission = new FolderPermissionInfo(objpermission) + { + FolderID = folder.FolderID, + RoleID = objPortal.AdministratorRoleId, + AllowAccess = true + }; + + folder.FolderPermissions.Add(objFolderPermission); + if (objpermission.PermissionKey == "READ") + { + //add READ permissions to the All Users Role + folderManager.AddAllUserReadPermission(folder, objpermission); + } + } + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + private static void CreateDefaultPortalRoles(int portalId, int administratorId, ref int administratorRoleId, ref int registeredRoleId, ref int subscriberRoleId, int unverifiedRoleId) + { + var controller = new RoleController(); + + //create required roles if not already created + if (administratorRoleId == -1) + { + administratorRoleId = CreateRole(portalId, "Administrators", "Administrators of this Website", 0, 0, "M", 0, 0, "N", false, false); + } + if (registeredRoleId == -1) + { + registeredRoleId = CreateRole(portalId, "Registered Users", "Registered Users", 0, 0, "M", 0, 0, "N", false, true); + } + if (subscriberRoleId == -1) + { + subscriberRoleId = CreateRole(portalId, "Subscribers", "A public role for site subscriptions", 0, 0, "M", 0, 0, "N", true, true); + } + if (unverifiedRoleId == -1) + { + CreateRole(portalId, "Unverified Users", "Unverified Users", 0, 0, "M", 0, 0, "N", false, false); + } + controller.AddUserRole(portalId, administratorId, administratorRoleId, Null.NullDate, Null.NullDate); + controller.AddUserRole(portalId, administratorId, registeredRoleId, Null.NullDate, Null.NullDate); + controller.AddUserRole(portalId, administratorId, subscriberRoleId, Null.NullDate, Null.NullDate); + } + + private static string CreateProfileDefinitions(int portalId, string templateFilePath) + { + string strMessage = Null.NullString; + try + { + //add profile definitions + XmlDocument xmlDoc = new XmlDocument(); + XmlNode node; + //open the XML template file + try + { + xmlDoc.Load(templateFilePath); + } + catch (Exception ex) + { + Logger.Error(ex); + } + //parse profile definitions if available + node = xmlDoc.SelectSingleNode("//portal/profiledefinitions"); + if (node != null) + { + ParseProfileDefinitions(node, portalId); + } + else //template does not contain profile definitions ( ie. was created prior to DNN 3.3.0 ) + { + ProfileController.AddDefaultDefinitions(portalId); + } + } + catch (Exception ex) + { + strMessage = Localization.GetString("CreateProfileDefinitions.Error"); + Exceptions.LogException(ex); + } + return strMessage; + } + + private static int CreatePortal(string portalName, string homeDirectory) + { + //add portal + int PortalId = -1; + try + { + //Use host settings as default values for these parameters + //This can be overwritten on the portal template + DateTime datExpiryDate; + if (Host.Host.DemoPeriod > Null.NullInteger) + { + datExpiryDate = Convert.ToDateTime(Globals.GetMediumDate(DateTime.Now.AddDays(Host.Host.DemoPeriod).ToString())); + } + else + { + datExpiryDate = Null.NullDate; + } + PortalId = DataProvider.Instance().CreatePortal(portalName, + Host.Host.HostCurrency, + datExpiryDate, + Host.Host.HostFee, + Host.Host.HostSpace, + Host.Host.PageQuota, + Host.Host.UserQuota, + Host.Host.SiteLogHistory, + homeDirectory, + UserController.GetCurrentUserInfo().UserID); + + //clear portal cache + DataCache.ClearHostCache(true); + + EventLogController objEventLog = new EventLogController(); + objEventLog.AddLog("PortalName", portalName, GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTAL_CREATED); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + return PortalId; + } + + private static int CreateRole(RoleInfo role) + { + RoleInfo objRoleInfo; + int roleId = Null.NullInteger; + + //First check if the role exists + objRoleInfo = TestableRoleController.Instance.GetRole(role.PortalID, r => r.RoleName == role.RoleName); + if (objRoleInfo == null) + { + roleId = TestableRoleController.Instance.AddRole(role); + } + else + { + roleId = objRoleInfo.RoleID; + } + return roleId; + } + + private static int CreateRole(int portalId, string roleName, string description, float serviceFee, int billingPeriod, string billingFrequency, float trialFee, int trialPeriod, string trialFrequency, + bool isPublic, bool isAuto) + { + RoleInfo objRoleInfo = new RoleInfo(); + objRoleInfo.PortalID = portalId; + objRoleInfo.RoleName = roleName; + objRoleInfo.RoleGroupID = Null.NullInteger; + objRoleInfo.Description = description; + objRoleInfo.ServiceFee = Convert.ToSingle(serviceFee < 0 ? 0 : serviceFee); + objRoleInfo.BillingPeriod = billingPeriod; + objRoleInfo.BillingFrequency = billingFrequency; + objRoleInfo.TrialFee = Convert.ToSingle(trialFee < 0 ? 0 : trialFee); + objRoleInfo.TrialPeriod = trialPeriod; + objRoleInfo.TrialFrequency = trialFrequency; + objRoleInfo.IsPublic = isPublic; + objRoleInfo.AutoAssignment = isAuto; + return CreateRole(objRoleInfo); + } + + private static void CreateRoleGroup(RoleGroupInfo roleGroup) + { + RoleGroupInfo objRoleGroupInfo; + RoleController objRoleController = new RoleController(); + int roleGroupId = Null.NullInteger; + + //First check if the role exists + objRoleGroupInfo = RoleController.GetRoleGroupByName(roleGroup.PortalID, roleGroup.RoleGroupName); + + if (objRoleGroupInfo == null) + { + roleGroup.RoleGroupID = RoleController.AddRoleGroup(roleGroup); + } + else + { + roleGroup.RoleGroupID = objRoleGroupInfo.RoleGroupID; + } + } + + private static PortalInfo GetPortalInternal(int portalID, string cultureCode) + { + var controller = new PortalController(); + return controller.GetPortalList(cultureCode).SingleOrDefault(p => p.PortalID == portalID); + } + + private static object GetPortalDefaultLanguageCallBack(CacheItemArgs cacheItemArgs) + { + int portalID = (int)cacheItemArgs.ParamList[0]; + return DataProvider.Instance().GetPortalDefaultLanguage(portalID); + } + + private static object GetPortalDictionaryCallback(CacheItemArgs cacheItemArgs) + { + var portalDic = new Dictionary(); + if (Host.Host.PerformanceSetting != Globals.PerformanceSettings.NoCaching) + { + //get all tabs + int intField = 0; + IDataReader dr = DataProvider.Instance().GetTabPaths(Null.NullInteger, Null.NullString); + try + { + while (dr.Read()) + { + //add to dictionary + portalDic[Convert.ToInt32(Null.SetNull(dr["TabID"], intField))] = Convert.ToInt32(Null.SetNull(dr["PortalID"], intField)); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + } + return portalDic; + } + + private object GetPortalsCallBack(CacheItemArgs cacheItemArgs) + { + var cultureCode = (string)cacheItemArgs.ParamList[0]; + string cacheKey = String.Format(DataCache.PortalCacheKey, Null.NullInteger, cultureCode); + List portals = CBO.FillCollection(DataProvider.Instance().GetPortals(cultureCode)); + DataCache.SetCache(cacheKey, portals); + return portals; + } + + private static object GetPortalSettingsDictionaryCallback(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + var cultureCode = Convert.ToString(cacheItemArgs.ParamList[1]); + if (string.IsNullOrEmpty(cultureCode)) + { + cultureCode = GetActivePortalLanguage(portalId); + } + + var dicSettings = new Dictionary(); + IDataReader dr = DataProvider.Instance().GetPortalSettings(portalId, cultureCode); + try + { + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + dicSettings.Add(dr.GetString(0), dr.GetString(1)); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return dicSettings; + } + + private static void ParseFiles(XmlNodeList nodeFiles, int portalId, FolderInfo objFolder) + { + var fileManager = FileManager.Instance; + + foreach (XmlNode node in nodeFiles) + { + var fileName = XmlUtils.GetNodeValue(node.CreateNavigator(), "filename"); + + //First check if the file exists + var objInfo = fileManager.GetFile(objFolder, fileName); + + if (objInfo != null) continue; + + objInfo = new FileInfo + { + PortalId = portalId, + FileName = fileName, + Extension = XmlUtils.GetNodeValue(node.CreateNavigator(), "extension"), + Size = XmlUtils.GetNodeValueInt(node, "size"), + Width = XmlUtils.GetNodeValueInt(node, "width"), + Height = XmlUtils.GetNodeValueInt(node, "height"), + ContentType = XmlUtils.GetNodeValue(node.CreateNavigator(), "contenttype"), + SHA1Hash = XmlUtils.GetNodeValue(node.CreateNavigator(), "sha1hash"), + FolderId = objFolder.FolderID, + Folder = objFolder.FolderPath, + Title = "", + StartDate = DateTime.Now, + EndDate = Null.NullDate, + EnablePublishPeriod = false, + ContentItemID = Null.NullInteger + }; + + //Save new File + try + { + using (var fileContent = fileManager.GetFileContent(objInfo)) + { + objInfo.FileId = fileManager.AddFile(objFolder, fileName, fileContent, false).FileId; + } + + fileManager.UpdateFile(objInfo); + } + catch (InvalidFileExtensionException ex) //when the file is not allowed, we should not break parse process, but just log the error. + { + Logger.Error(ex.Message); + } + } + } + + private static void ParseFolderPermissions(XmlNodeList nodeFolderPermissions, int portalId, FolderInfo folder) + { + PermissionController permissionController = new PermissionController(); + int permissionId = 0; + + //Clear the current folder permissions + folder.FolderPermissions.Clear(); + foreach (XmlNode xmlFolderPermission in nodeFolderPermissions) + { + string permissionKey = XmlUtils.GetNodeValue(xmlFolderPermission.CreateNavigator(), "permissionkey"); + string permissionCode = XmlUtils.GetNodeValue(xmlFolderPermission.CreateNavigator(), "permissioncode"); + string roleName = XmlUtils.GetNodeValue(xmlFolderPermission.CreateNavigator(), "rolename"); + bool allowAccess = XmlUtils.GetNodeValueBoolean(xmlFolderPermission, "allowaccess"); + foreach (PermissionInfo permission in permissionController.GetPermissionByCodeAndKey(permissionCode, permissionKey)) + { + permissionId = permission.PermissionID; + } + int roleId = int.MinValue; + switch (roleName) + { + case Globals.glbRoleAllUsersName: + roleId = Convert.ToInt32(Globals.glbRoleAllUsers); + break; + case Globals.glbRoleUnauthUserName: + roleId = Convert.ToInt32(Globals.glbRoleUnauthUser); + break; + default: + RoleInfo objRole = TestableRoleController.Instance.GetRole(portalId, r => r.RoleName == roleName); + if (objRole != null) + { + roleId = objRole.RoleID; + } + break; + } + + //if role was found add, otherwise ignore + if (roleId != int.MinValue) + { + var folderPermission = new FolderPermissionInfo + { + FolderID = folder.FolderID, + PermissionID = permissionId, + RoleID = roleId, + UserID = Null.NullInteger, + AllowAccess = allowAccess + }; + + bool canAdd = !folder.FolderPermissions.Cast() + .Any(fp => fp.FolderID == folderPermission.FolderID + && fp.PermissionID == folderPermission.PermissionID + && fp.RoleID == folderPermission.RoleID + && fp.UserID == folderPermission.UserID); + if (canAdd) + { + folder.FolderPermissions.Add(folderPermission); + } + } + } + FolderPermissionController.SaveFolderPermissions(folder); + } + + private void ParseFolders(XmlNode nodeFolders, int PortalId) + { + IFolderInfo objInfo; + string folderPath; + int storageLocation; + bool isProtected = false; + var folderManager = FolderManager.Instance; + var folderMappingController = FolderMappingController.Instance; + FolderMappingInfo folderMapping = null; + + foreach (XmlNode node in nodeFolders.SelectNodes("//folder")) + { + folderPath = XmlUtils.GetNodeValue(node.CreateNavigator(), "folderpath"); + + //First check if the folder exists + objInfo = folderManager.GetFolder(PortalId, folderPath); + + if (objInfo == null) + { + isProtected = PathUtils.Instance.IsDefaultProtectedPath(folderPath); + + if (isProtected) + { + //protected folders must use insecure storage + folderMapping = folderMappingController.GetDefaultFolderMapping(PortalId); + } + else + { + storageLocation = Convert.ToInt32(XmlUtils.GetNodeValue(node, "storagelocation", "0")); + + switch (storageLocation) + { + case (int)FolderController.StorageLocationTypes.InsecureFileSystem: + folderMapping = folderMappingController.GetDefaultFolderMapping(PortalId); + break; + case (int)FolderController.StorageLocationTypes.SecureFileSystem: + folderMapping = folderMappingController.GetFolderMapping(PortalId, "Secure"); + break; + case (int)FolderController.StorageLocationTypes.DatabaseSecure: + folderMapping = folderMappingController.GetFolderMapping(PortalId, "Database"); + break; + default: + break; + } + + isProtected = XmlUtils.GetNodeValueBoolean(node, "isprotected"); + } + //Save new folder + objInfo = folderManager.AddFolder(folderMapping, folderPath); + objInfo.IsProtected = isProtected; + + folderManager.UpdateFolder(objInfo); + } + + var nodeFolderPermissions = node.SelectNodes("folderpermissions/permission"); + ParseFolderPermissions(nodeFolderPermissions, PortalId, (FolderInfo)objInfo); + + var nodeFiles = node.SelectNodes("files/file"); + + if (!String.IsNullOrEmpty(folderPath)) + { + folderPath += "/"; + } + + ParseFiles(nodeFiles, PortalId, (FolderInfo)objInfo); + } + } + + private static void ParsePortalDesktopModules(XPathNavigator nav, int portalID) + { + string friendlyName = Null.NullString; + DesktopModuleInfo desktopModule = null; + foreach (XPathNavigator desktopModuleNav in nav.Select("portalDesktopModule")) + { + friendlyName = XmlUtils.GetNodeValue(desktopModuleNav, "friendlyname"); + if (!string.IsNullOrEmpty(friendlyName)) + { + desktopModule = DesktopModuleController.GetDesktopModuleByFriendlyName(friendlyName); + if (desktopModule != null) + { + //Parse the permissions + DesktopModulePermissionCollection permissions = new DesktopModulePermissionCollection(); + foreach (XPathNavigator permissionNav in + desktopModuleNav.Select("portalDesktopModulePermissions/portalDesktopModulePermission")) + { + string code = XmlUtils.GetNodeValue(permissionNav, "permissioncode"); + string key = XmlUtils.GetNodeValue(permissionNav, "permissionkey"); + DesktopModulePermissionInfo desktopModulePermission = null; + ArrayList arrPermissions = new PermissionController().GetPermissionByCodeAndKey(code, key); + if (arrPermissions.Count > 0) + { + PermissionInfo permission = arrPermissions[0] as PermissionInfo; + if (permission != null) + { + desktopModulePermission = new DesktopModulePermissionInfo(permission); + } + } + desktopModulePermission.AllowAccess = bool.Parse(XmlUtils.GetNodeValue(permissionNav, "allowaccess")); + string rolename = XmlUtils.GetNodeValue(permissionNav, "rolename"); + if (!string.IsNullOrEmpty(rolename)) + { + RoleInfo role = TestableRoleController.Instance.GetRole(portalID, r => r.RoleName == rolename); + if (role != null) + { + desktopModulePermission.RoleID = role.RoleID; + } + } + permissions.Add(desktopModulePermission); + } + DesktopModuleController.AddDesktopModuleToPortal(portalID, desktopModule, permissions, false); + } + } + } + } + + private void ParsePortalSettings(XmlNode nodeSettings, int PortalId) + { + PortalInfo objPortal; + objPortal = GetPortal(PortalId); + objPortal.LogoFile = Globals.ImportFile(PortalId, XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "logofile")); + objPortal.FooterText = XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "footertext"); + if (nodeSettings.SelectSingleNode("expirydate") != null) + { + objPortal.ExpiryDate = XmlUtils.GetNodeValueDate(nodeSettings, "expirydate", Null.NullDate); + } + objPortal.UserRegistration = XmlUtils.GetNodeValueInt(nodeSettings, "userregistration"); + objPortal.BannerAdvertising = XmlUtils.GetNodeValueInt(nodeSettings, "banneradvertising"); + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "currency"))) + { + objPortal.Currency = XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "currency"); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "hostfee"))) + { + objPortal.HostFee = XmlUtils.GetNodeValueSingle(nodeSettings, "hostfee"); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "hostspace"))) + { + objPortal.HostSpace = XmlUtils.GetNodeValueInt(nodeSettings, "hostspace"); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "pagequota"))) + { + objPortal.PageQuota = XmlUtils.GetNodeValueInt(nodeSettings, "pagequota"); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "userquota"))) + { + objPortal.UserQuota = XmlUtils.GetNodeValueInt(nodeSettings, "userquota"); + } + objPortal.BackgroundFile = XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "backgroundfile"); + objPortal.PaymentProcessor = XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "paymentprocessor"); + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings.CreateNavigator(), "siteloghistory"))) + { + objPortal.SiteLogHistory = XmlUtils.GetNodeValueInt(nodeSettings, "siteloghistory"); + } + objPortal.DefaultLanguage = XmlUtils.GetNodeValue(nodeSettings, "defaultlanguage", "en-US"); + UpdatePortalInfo(objPortal); + + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "skinsrc", ""))) + { + UpdatePortalSetting(PortalId, "DefaultPortalSkin", XmlUtils.GetNodeValue(nodeSettings, "skinsrc", "")); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "skinsrcadmin", ""))) + { + UpdatePortalSetting(PortalId, "DefaultAdminSkin", XmlUtils.GetNodeValue(nodeSettings, "skinsrcadmin", "")); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "containersrc", ""))) + { + UpdatePortalSetting(PortalId, "DefaultPortalContainer", XmlUtils.GetNodeValue(nodeSettings, "containersrc", "")); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "containersrcadmin", ""))) + { + UpdatePortalSetting(PortalId, "DefaultAdminContainer", XmlUtils.GetNodeValue(nodeSettings, "containersrcadmin", "")); + } + + //Enable Skin Widgets Setting + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "enableskinwidgets", ""))) + { + UpdatePortalSetting(PortalId, "EnableSkinWidgets", XmlUtils.GetNodeValue(nodeSettings, "enableskinwidgets", "")); + } + + //Enable AutoSAve feature + //Enable Skin Widgets Setting + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "enableautosave", ""))) + { + UpdatePortalSetting(PortalId, HtmlText_AutoSaveEnabled, XmlUtils.GetNodeValue(nodeSettings, "enableautosave", "")); + //Time to autosave, only if enableautosave exists + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "timetoautosave", ""))) + { + UpdatePortalSetting(PortalId, HtmlText_TimeToAutoSave, XmlUtils.GetNodeValue(nodeSettings, "timetoautosave", "")); + } + } + + //Set Auto alias mapping + + if (!string.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "portalaliasmapping", "CANONICALURL"))) + { + UpdatePortalSetting(PortalId, "PortalAliasMapping", XmlUtils.GetNodeValue(nodeSettings, "portalaliasmapping", "CANONICALURL").ToUpperInvariant()); + } + //Set Time Zone maping + if (!string.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "timezone", Localization.SystemTimeZone))) + { + UpdatePortalSetting(PortalId, "TimeZone", XmlUtils.GetNodeValue(nodeSettings, "timezone", Localization.SystemTimeZone)); + } + + if (!string.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeSettings, "contentlocalizationenabled"))) + { + UpdatePortalSetting(PortalId, "ContentLocalizationEnabled", XmlUtils.GetNodeValue(nodeSettings, "contentlocalizationenabled")); + } + } + + private static LocaleCollection ParseEnabledLocales(XmlNode nodeEnabledLocales, int PortalId) + { + var defaultLocale = LocaleController.Instance.GetDefaultLocale(PortalId); + var returnCollection = new LocaleCollection { { defaultLocale.Code, defaultLocale } }; + var clearCache = false; + foreach (XmlNode node in nodeEnabledLocales.SelectNodes("//locale")) + { + var cultureCode = node.InnerText; + var locale = LocaleController.Instance.GetLocale(cultureCode); + if (locale == null) + { + // if language does not exist in the installation, create it + locale = new Locale {Code = cultureCode, Fallback = Localization.SystemLocale, Text = CultureInfo.CreateSpecificCulture(cultureCode).NativeName}; + Localization.SaveLanguage(locale,false); + clearCache = true; + } + + if (locale.Code != defaultLocale.Code) + { + returnCollection.Add(locale.Code, locale); + } + } + if (clearCache) + { + DataCache.ClearHostCache(true); + } + return returnCollection; + } + + private static void ParseProfileDefinitions(XmlNode nodeProfileDefinitions, int PortalId) + { + var listController = new ListController(); + Dictionary colDataTypes = listController.GetListEntryInfoDictionary("DataType"); + + int orderCounter = -1; + ProfilePropertyDefinition objProfileDefinition; + bool preferredTimeZoneFound = false; + foreach (XmlNode node in nodeProfileDefinitions.SelectNodes("//profiledefinition")) + { + orderCounter += 2; + ListEntryInfo typeInfo; + if (!colDataTypes.TryGetValue("DataType:" + XmlUtils.GetNodeValue(node.CreateNavigator(), "datatype"), out typeInfo)) + { + typeInfo = colDataTypes["DataType:Unknown"]; + } + objProfileDefinition = new ProfilePropertyDefinition(PortalId); + objProfileDefinition.DataType = typeInfo.EntryID; + objProfileDefinition.DefaultValue = ""; + objProfileDefinition.ModuleDefId = Null.NullInteger; + objProfileDefinition.PropertyCategory = XmlUtils.GetNodeValue(node.CreateNavigator(), "propertycategory"); + objProfileDefinition.PropertyName = XmlUtils.GetNodeValue(node.CreateNavigator(), "propertyname"); + objProfileDefinition.Required = false; + objProfileDefinition.Visible = true; + objProfileDefinition.ViewOrder = orderCounter; + objProfileDefinition.Length = XmlUtils.GetNodeValueInt(node, "length"); + + switch (XmlUtils.GetNodeValueInt(node, "defaultvisibility", 2)) + { + case 0: + objProfileDefinition.DefaultVisibility = UserVisibilityMode.AllUsers; + break; + case 1: + objProfileDefinition.DefaultVisibility = UserVisibilityMode.MembersOnly; + break; + case 2: + objProfileDefinition.DefaultVisibility = UserVisibilityMode.AdminOnly; + break; + } + + if (objProfileDefinition.PropertyName == "PreferredTimeZone") + { + preferredTimeZoneFound = true; + } + + ProfileController.AddPropertyDefinition(objProfileDefinition); + } + + //6.0 requires the old TimeZone property to be marked as Deleted + ProfilePropertyDefinition pdf = ProfileController.GetPropertyDefinitionByName(PortalId, "TimeZone"); + if (pdf != null) + { + ProfileController.DeletePropertyDefinition(pdf); + } + + // 6.0 introduced a new property called as PreferredTimeZone. If this property is not present in template + // it should be added. Situation will mostly happen while using an older template file. + if (!preferredTimeZoneFound) + { + orderCounter += 2; + + ListEntryInfo typeInfo = colDataTypes["DataType:TimeZoneInfo"]; + if (typeInfo == null) + { + typeInfo = colDataTypes["DataType:Unknown"]; + } + + objProfileDefinition = new ProfilePropertyDefinition(PortalId); + objProfileDefinition.DataType = typeInfo.EntryID; + objProfileDefinition.DefaultValue = ""; + objProfileDefinition.ModuleDefId = Null.NullInteger; + objProfileDefinition.PropertyCategory = "Preferences"; + objProfileDefinition.PropertyName = "PreferredTimeZone"; + objProfileDefinition.Required = false; + objProfileDefinition.Visible = true; + objProfileDefinition.ViewOrder = orderCounter; + objProfileDefinition.Length = 0; + objProfileDefinition.DefaultVisibility = UserVisibilityMode.AdminOnly; + ProfileController.AddPropertyDefinition(objProfileDefinition); + } + } + + private void ParseRoleGroups(XPathNavigator nav, int portalID, int administratorId) + { + var administratorRoleId = -1; + var registeredRoleId = -1; + var subscriberRoleId = -1; + var unverifiedRoleId = -1; + + foreach (XPathNavigator roleGroupNav in nav.Select("rolegroup")) + { + var roleGroup = CBO.DeserializeObject(new StringReader(roleGroupNav.OuterXml)); + if (roleGroup.RoleGroupName != "GlobalRoles") + { + roleGroup.PortalID = portalID; + CreateRoleGroup(roleGroup); + } + foreach (var role in roleGroup.Roles.Values) + { + role.PortalID = portalID; + role.RoleGroupID = roleGroup.RoleGroupID; + role.Status = RoleStatus.Approved; + switch (role.RoleType) + { + case RoleType.Administrator: + administratorRoleId = CreateRole(role); + break; + case RoleType.RegisteredUser: + registeredRoleId = CreateRole(role); + break; + case RoleType.Subscriber: + subscriberRoleId = CreateRole(role); + break; + case RoleType.None: + CreateRole(role); + break; + case RoleType.UnverifiedUser: + unverifiedRoleId = CreateRole(role); + break; + } + } + } + CreateDefaultPortalRoles(portalID, administratorId, ref administratorRoleId, ref registeredRoleId, ref subscriberRoleId, unverifiedRoleId); + + //update portal setup + var objportal = GetPortal(portalID); + UpdatePortalSetup(portalID, + administratorId, + administratorRoleId, + registeredRoleId, + objportal.SplashTabId, + objportal.HomeTabId, + objportal.LoginTabId, + objportal.RegisterTabId, + objportal.UserTabId, + objportal.SearchTabId, + objportal.AdminTabId, + GetActivePortalLanguage(portalID)); + } + + private void ParseRoles(XPathNavigator nav, int portalID, int administratorId) + { + var administratorRoleId = -1; + var registeredRoleId = -1; + var subscriberRoleId = -1; + var unverifiedRoleId = -1; + + foreach (XPathNavigator roleNav in nav.Select("role")) + { + var role = CBO.DeserializeObject(new StringReader(roleNav.OuterXml)); + role.PortalID = portalID; + role.RoleGroupID = Null.NullInteger; + switch (role.RoleType) + { + case RoleType.Administrator: + administratorRoleId = CreateRole(role); + break; + case RoleType.RegisteredUser: + registeredRoleId = CreateRole(role); + break; + case RoleType.Subscriber: + subscriberRoleId = CreateRole(role); + break; + case RoleType.None: + CreateRole(role); + break; + case RoleType.UnverifiedUser: + unverifiedRoleId = CreateRole(role); + break; + } + } + + //create required roles if not already created + CreateDefaultPortalRoles(portalID, administratorId, ref administratorRoleId, ref registeredRoleId, ref subscriberRoleId, unverifiedRoleId); + + //update portal setup + var objportal = GetPortal(portalID); + UpdatePortalSetup(portalID, + administratorId, + administratorRoleId, + registeredRoleId, + objportal.SplashTabId, + objportal.HomeTabId, + objportal.LoginTabId, + objportal.RegisterTabId, + objportal.UserTabId, + objportal.SearchTabId, + objportal.AdminTabId, + GetActivePortalLanguage(portalID)); + } + + private void ParseTab(XmlNode nodeTab, int PortalId, bool IsAdminTemplate, PortalTemplateModuleAction mergeTabs, ref Hashtable hModules, ref Hashtable hTabs, bool isNewPortal) + { + TabInfo tab = null; + var tabController = new TabController(); + string strName = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "name"); + var portal = GetPortal(PortalId); + if (!String.IsNullOrEmpty(strName)) + { + if (!isNewPortal) //running from wizard: try to find the tab by path + { + string parenttabname = ""; + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent"))) + { + parenttabname = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent") + "/"; + } + if (hTabs[parenttabname + strName] != null) + { + tab = tabController.GetTab(Convert.ToInt32(hTabs[parenttabname + strName]), PortalId, false); + } + } + if (tab == null || isNewPortal) + { + tab = TabController.DeserializeTab(nodeTab, null, hTabs, PortalId, IsAdminTemplate, mergeTabs, hModules); + } + var eventLogController = new EventLogController(); + + //when processing the template we should try and identify the Admin tab + if (tab.TabName == "Admin") + { + portal.AdminTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("AdminTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + } + //when processing the template we can find: hometab, usertab, logintab + switch (XmlUtils.GetNodeValue(nodeTab, "tabtype", "")) + { + case "splashtab": + portal.SplashTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("SplashTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + break; + case "hometab": + portal.HomeTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("HomeTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + break; + case "logintab": + portal.LoginTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("LoginTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + break; + case "usertab": + portal.UserTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("UserTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + break; + case "searchtab": + portal.SearchTabId = tab.TabID; + UpdatePortalSetup(PortalId, + portal.AdministratorId, + portal.AdministratorRoleId, + portal.RegisteredRoleId, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.AdminTabId, + GetActivePortalLanguage(PortalId)); + eventLogController.AddLog("SearchTab", + tab.TabID.ToString(), + GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + break; + case "gettingStartedTab": + UpdatePortalSetting(PortalId, "GettingStartedTabId", tab.TabID.ToString()); + break; + case "404Tab": + UpdatePortalSetting(PortalId, "AUM_ErrorPage404", tab.TabID.ToString()); + break; + case "500Tab": + UpdatePortalSetting(PortalId, "AUM_ErrorPage500", tab.TabID.ToString()); + break; + } + } + } + + private void ParseTabs(XmlNode nodeTabs, int PortalId, bool IsAdminTemplate, PortalTemplateModuleAction mergeTabs, bool IsNewPortal) + { + //used to control if modules are true modules or instances + //will hold module ID from template / new module ID so new instances can reference right moduleid + //only first one from the template will be create as a true module, + //others will be moduleinstances (tabmodules) + Hashtable hModules = new Hashtable(); + Hashtable hTabs = new Hashtable(); + + //if running from wizard we need to pre populate htabs with existing tabs so ParseTab + //can find all existing ones + string tabname; + if (!IsNewPortal) + { + Hashtable hTabNames = new Hashtable(); + TabController objTabs = new TabController(); + foreach (KeyValuePair tabPair in objTabs.GetTabsByPortal(PortalId)) + { + TabInfo objTab = tabPair.Value; + if (!objTab.IsDeleted) + { + tabname = objTab.TabName; + if (!Null.IsNull(objTab.ParentId)) + { + tabname = Convert.ToString(hTabNames[objTab.ParentId]) + "/" + objTab.TabName; + } + hTabNames.Add(objTab.TabID, tabname); + } + } + + //when parsing tabs we will need tabid given tabname + foreach (int i in hTabNames.Keys) + { + if (hTabs[hTabNames[i]] == null) + { + hTabs.Add(hTabNames[i], i); + } + } + hTabNames = null; + } + foreach (XmlNode nodeTab in nodeTabs.SelectNodes("//tab")) + { + ParseTab(nodeTab, PortalId, IsAdminTemplate, mergeTabs, ref hModules, ref hTabs, IsNewPortal); + } + + //Process tabs that are linked to tabs + foreach (XmlNode nodeTab in nodeTabs.SelectNodes("//tab[url/@type = 'Tab']")) + { + int tabId = XmlUtils.GetNodeValueInt(nodeTab, "tabid", Null.NullInteger); + string tabPath = XmlUtils.GetNodeValue(nodeTab, "url", Null.NullString); + if (tabId > Null.NullInteger) + { + TabController controller = new TabController(); + TabInfo objTab = controller.GetTab(tabId, PortalId, false); + objTab.Url = TabController.GetTabByTabPath(PortalId, tabPath, Null.NullString).ToString(); + controller.UpdateTab(objTab); + } + } + var folderManager = FolderManager.Instance; + var fileManager = FileManager.Instance; + //Process tabs that are linked to files + foreach (XmlNode nodeTab in nodeTabs.SelectNodes("//tab[url/@type = 'File']")) + { + var tabId = XmlUtils.GetNodeValueInt(nodeTab, "tabid", Null.NullInteger); + var filePath = XmlUtils.GetNodeValue(nodeTab, "url", Null.NullString); + if (tabId > Null.NullInteger) + { + var controller = new TabController(); + var objTab = controller.GetTab(tabId, PortalId, false); + + var fileName = Path.GetFileName(filePath); + + var folderPath = filePath.Substring(0, filePath.LastIndexOf(fileName)); + var folder = folderManager.GetFolder(PortalId, folderPath); + + var file = fileManager.GetFile(folder, fileName); + + objTab.Url = "FileID=" + file.FileId; + controller.UpdateTab(objTab); + } + } + } + + private void UpdatePortalSetup(int PortalId, int AdministratorId, int AdministratorRoleId, int RegisteredRoleId, int SplashTabId, int HomeTabId, int LoginTabId, int RegisterTabId, + int UserTabId, int SearchTabId, int AdminTabId, string CultureCode) + { + DataProvider.Instance().UpdatePortalSetup(PortalId, + AdministratorId, + AdministratorRoleId, + RegisteredRoleId, + SplashTabId, + HomeTabId, + LoginTabId, + RegisterTabId, + UserTabId, + SearchTabId, + AdminTabId, + CultureCode); + EventLogController objEventLog = new EventLogController(); + objEventLog.AddLog("PortalId", PortalId.ToString(), GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTALINFO_UPDATED); + DataCache.ClearHostCache(true); + } + + private void PrepareLocalizedPortalTemplate(PortalTemplateInfo template, out string templatePath, out string templateFile) + { + if (string.IsNullOrEmpty(template.LanguageFilePath)) + { + //no language to merge + templatePath = Path.GetDirectoryName(template.TemplateFilePath) + @"\"; + templateFile = Path.GetFileName(template.TemplateFilePath); + return; + } + + templatePath = Path.Combine(TestableGlobals.Instance.HostMapPath, "MergedTemplate"); + Directory.CreateDirectory(templatePath); + + var buffer = new StringBuilder(File.ReadAllText(template.TemplateFilePath)); + + XDocument languageDoc; + using (var reader = PortalTemplateIO.Instance.OpenTextReader(template.LanguageFilePath)) + { + languageDoc = XDocument.Load(reader); + } + + var localizedData = languageDoc.Descendants("data"); + + foreach (var item in localizedData) + { + var nameAttribute = item.Attribute("name"); + if (nameAttribute != null) + { + string name = nameAttribute.Value; + var valueElement = item.Descendants("value").FirstOrDefault(); + if (valueElement != null) + { + string value = valueElement.Value; + + buffer = buffer.Replace(string.Format("[{0}]", name), value); + } + } + } + + templateFile = string.Format("Merged-{0}-{1}", template.CultureCode, Path.GetFileName(template.TemplateFilePath)); + + File.WriteAllText(Path.Combine(templatePath, templateFile), buffer.ToString()); + } + + private string GetTemplateName(string languageFileName) + { + //e.g. "default template.template.en-US.resx" + return languageFileName.Substring(0, languageFileName.Length - ".xx-XX.resx".Length); + } + + private string GetCultureCode(string languageFileName) + { + //e.g. "default template.template.en-US.resx" + return languageFileName.Substring(1 + languageFileName.Length - ".xx-XX.resx".Length, "xx-XX".Length); + } + + private static Dictionary GetPortalSettingsDictionary(int portalId, string cultureCode) + { + string cacheKey = string.Format(DataCache.PortalSettingsCacheKey, portalId); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.PortalSettingsCacheTimeOut, DataCache.PortalSettingsCachePriority, portalId, cultureCode), + GetPortalSettingsDictionaryCallback, + true); + } + + private static bool EnableBrowserLanguageInDefault(int portalId) + { + bool retValue = Null.NullBoolean; + try + { + var setting = Null.NullString; + GetPortalSettingsDictionary(portalId, Localization.SystemLocale).TryGetValue("EnableBrowserLanguage", out setting); + if (string.IsNullOrEmpty(setting)) + { + retValue = Host.Host.EnableBrowserLanguage; + } + else + { + retValue = (setting.StartsWith("Y", StringComparison.InvariantCultureIgnoreCase) || setting.ToUpperInvariant() == "TRUE"); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + return retValue; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Creates a new portal alias + /// + /// Id of the portal + /// Portal Alias to be created + /// + /// + /// + /// [cnurse] 01/11/2005 created + /// + /// ----------------------------------------------------------------------------- + public void AddPortalAlias(int portalId, string portalAlias) + { + var portalAliasController = new PortalAliasController(); + + //Check if the Alias exists + PortalAliasInfo portalAliasInfo = portalAliasController.GetPortalAlias(portalAlias, portalId); + + //If alias does not exist add new + if (portalAliasInfo == null) + { + portalAliasInfo = new PortalAliasInfo {PortalID = portalId, HTTPAlias = portalAlias, IsPrimary = true}; + TestablePortalAliasController.Instance.AddPortalAlias(portalAliasInfo); + } + } + + /// + /// Copies the page template. + /// + /// The template file. + /// The mapped home directory. + public void CopyPageTemplate(string templateFile, string mappedHomeDirectory) + { + string hostTemplateFile = string.Format("{0}Templates\\{1}", Globals.HostMapPath, templateFile); + if (File.Exists(hostTemplateFile)) + { + string portalTemplateFolder = string.Format("{0}Templates\\", mappedHomeDirectory); + if (!Directory.Exists(portalTemplateFolder)) + { + //Create Portal Templates folder + Directory.CreateDirectory(portalTemplateFolder); + } + string portalTemplateFile = portalTemplateFolder + templateFile; + if (!File.Exists(portalTemplateFile)) + { + File.Copy(hostTemplateFile, portalTemplateFile); + } + } + } + + /// + /// Creates the portal. + /// + /// Name of the portal. + /// The obj admin user. + /// The description. + /// The key words. + /// The template path. + /// The template file. + /// The home directory. + /// The portal alias. + /// The server path. + /// The child path. + /// if set to true means the portal is child portal. + /// Portal id. + public int CreatePortal(string portalName, UserInfo adminUser, string description, string keyWords, string templatePath, + string templateFile, string homeDirectory, string portalAlias, + string serverPath, string childPath, bool isChildPortal) + { + var template = TestablePortalController.Instance.GetPortalTemplate(Path.Combine(templatePath, templateFile), null); + + return CreatePortal(portalName, adminUser, description, keyWords, template, homeDirectory, portalAlias, + serverPath, childPath, isChildPortal); + } + + /// + /// Creates the portal. + /// + /// Name of the portal. + /// The obj admin user. + /// The description. + /// The key words. + /// + /// The home directory. + /// The portal alias. + /// The server path. + /// The child path. + /// if set to true means the portal is child portal. + /// Portal id. + public int CreatePortal(string portalName, int adminUserId, string description, string keyWords, PortalTemplateInfo template, + string homeDirectory, string portalAlias, string serverPath, string childPath, bool isChildPortal) + { + string message = Null.NullString; + int administratorId = adminUserId; + UserInfo adminUser=new UserInfo(); + + //Attempt to create a new portal + int portalId = CreatePortal(portalName, homeDirectory); + + string templatePath, templateFile; + PrepareLocalizedPortalTemplate(template, out templatePath, out templateFile); + string mergedTemplatePath = Path.Combine(templatePath, templateFile); + + if (portalId != -1) + { + //add userportal record + UserController.AddUserPortal(portalId,administratorId); + + if (String.IsNullOrEmpty(homeDirectory)) + { + homeDirectory = "Portals/" + portalId; + } + string mappedHomeDirectory = String.Format(Globals.ApplicationMapPath + "\\" + homeDirectory + "\\").Replace("/", "\\"); + message += CreateProfileDefinitions(portalId, mergedTemplatePath); + if (message == Null.NullString) + { + //retrieve existing administrator + try + { + adminUser = UserController.GetUserById(portalId, administratorId); + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + } + else + { + throw new Exception(message); + } + if (String.IsNullOrEmpty(message) && administratorId > 0) + { + try + { + //the upload directory may already exist if this is a new DB working with a previously installed application + if (Directory.Exists(mappedHomeDirectory)) + { + Globals.DeleteFolderRecursive(mappedHomeDirectory); + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("DeleteUploadFolder.Error") + Exc.Message + Exc.StackTrace; + } + + //Set up Child Portal + if (message == Null.NullString) + { + if (isChildPortal) + { + message = CreateChildPortalFolder(childPath); + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + try + { + //create the upload directory for the new portal + Directory.CreateDirectory(mappedHomeDirectory); + //ensure that the Templates folder exists + string templateFolder = String.Format("{0}Templates", mappedHomeDirectory); + if (!Directory.Exists(templateFolder)) + { + Directory.CreateDirectory(templateFolder); + } + + //ensure that the Users folder exists + string usersFolder = String.Format("{0}Users", mappedHomeDirectory); + if (!Directory.Exists(usersFolder)) + { + Directory.CreateDirectory(usersFolder); + } + + //copy the default page template + CopyPageTemplate("Default.page.template", mappedHomeDirectory); + + // process zip resource file if present + if (File.Exists(template.ResourceFilePath)) + { + ProcessResourceFileExplicit(mappedHomeDirectory, template.ResourceFilePath); + } + + //copy getting started css into portal's folder. + var hostGettingStartedFile = string.Format("{0}GettingStarted.css", Globals.HostMapPath); + if (File.Exists(hostGettingStartedFile)) + { + var portalFile = mappedHomeDirectory + "GettingStarted.css"; + if (!File.Exists(portalFile)) + { + File.Copy(hostGettingStartedFile, portalFile); + } + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("ChildPortal.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + try + { + FolderMappingController.Instance.AddDefaultFolderTypes(portalId); + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("DefaultFolderMappings.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + + LocaleCollection newPortalLocales = null; + if (message == Null.NullString) + { + try + { + ParseTemplate(portalId, templatePath, templateFile, administratorId, PortalTemplateModuleAction.Replace, true, out newPortalLocales); + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("PortalTemplate.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + + var portal = GetPortal(portalId); + portal.Description = description; + portal.KeyWords = keyWords; + portal.UserTabId = TabController.GetTabByTabPath(portal.PortalID, "//UserProfile", portal.CultureCode); + if (portal.UserTabId == -1) + { + portal.UserTabId = TabController.GetTabByTabPath(portal.PortalID, "//ActivityFeed", portal.CultureCode); + } + portal.SearchTabId = TabController.GetTabByTabPath(portal.PortalID, "//SearchResults", portal.CultureCode); + UpdatePortalInfo(portal); + adminUser.Profile.PreferredLocale = portal.DefaultLanguage; + var portalSettings = new PortalSettings(portal); + adminUser.Profile.PreferredTimeZone = portalSettings.TimeZone; + UserController.UpdateUser(portal.PortalID, adminUser); + DesktopModuleController.AddDesktopModulesToPortal(portalId); + AddPortalAlias(portalId, portalAlias); + UpdatePortalSetting(portalId, "DefaultPortalAlias", portalAlias, false); + DataCache.ClearPortalCache(portalId,true); + + if (newPortalLocales != null) + { + foreach (Locale newPortalLocale in newPortalLocales.AllValues) + { + Localization.AddLanguageToPortal(portalId, newPortalLocale.LanguageId, false); + } + } + + try + { + RelationshipController.Instance.CreateDefaultRelationshipsForPortal(portalId); + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + //add profanity list to new portal + try + { + const string listName = "ProfanityFilter"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + entry.PortalID = portalId; + entry.SystemList = false; + entry.ListName = listName + "-" + portalId; + listController.AddListEntry(entry); + + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + //add banned password list to new portal + try + { + const string listName = "BannedPasswords"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + entry.PortalID = portalId; + entry.SystemList = false; + entry.ListName = listName + "-" + portalId; + listController.AddListEntry(entry); + + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + // Add default workflows + try + { + ContentWorkflowController.Instance.CreateDefaultWorkflows(portalId); + } + catch (Exception ex) + { + Logger.Error(ex); + } + + ServicesRoutingManager.ReRegisterServiceRoutesWhileSiteIsRunning(); + + try + { + var objEventLogInfo = new LogInfo(); + objEventLogInfo.BypassBuffering = true; + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Install Portal:", portalName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("FirstName:", adminUser.FirstName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("LastName:", adminUser.LastName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Username:", adminUser.Username)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Email:", adminUser.Email)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Description:", description)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Keywords:", keyWords)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Template:", template.TemplateFilePath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("TemplateCulture:", template.CultureCode)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("HomeDirectory:", homeDirectory)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("PortalAlias:", portalAlias)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("ServerPath:", serverPath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("ChildPath:", childPath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("IsChildPortal:", isChildPortal.ToString())); + var eventLog = new EventLogController(); + eventLog.AddLog(objEventLogInfo); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + else + { + throw new Exception(message); + } + } + else + { + DeletePortalInfo(portalId); + portalId = -1; + throw new Exception(message); + } + } + else + { + message += Localization.GetString("CreatePortal.Error"); + throw new Exception(message); + } + return portalId; + } + /// + /// Creates the portal. + /// + /// Name of the portal. + /// The obj admin user. + /// The description. + /// The key words. + /// + /// The home directory. + /// The portal alias. + /// The server path. + /// The child path. + /// if set to true means the portal is child portal. + /// Portal id. + public int CreatePortal(string portalName, UserInfo adminUser, string description, string keyWords, PortalTemplateInfo template, + string homeDirectory, string portalAlias, string serverPath, string childPath, bool isChildPortal) + { + string message = Null.NullString; + int administratorId = Null.NullInteger; + + //Attempt to create a new portal + int portalId = CreatePortal(portalName, homeDirectory); + + string templatePath, templateFile; + PrepareLocalizedPortalTemplate(template, out templatePath, out templateFile); + string mergedTemplatePath = Path.Combine(templatePath, templateFile); + + if (portalId != -1) + { + if (String.IsNullOrEmpty(homeDirectory)) + { + homeDirectory = "Portals/" + portalId; + } + string mappedHomeDirectory = String.Format(Globals.ApplicationMapPath + "\\" + homeDirectory + "\\").Replace("/", "\\"); + message += CreateProfileDefinitions(portalId, mergedTemplatePath); + if (message == Null.NullString) + { + //add administrator + try + { + adminUser.PortalID = portalId; + UserCreateStatus createStatus = UserController.CreateUser(ref adminUser); + if (createStatus == UserCreateStatus.Success) + { + administratorId = adminUser.UserID; + //reload the UserInfo as when it was first created, it had no portal id and therefore + //used host profile definitions + adminUser = UserController.GetUserById(adminUser.PortalID, adminUser.UserID); + } + else + { + message += UserController.GetUserCreateStatus(createStatus); + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("CreateAdminUser.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + if (String.IsNullOrEmpty(message) && administratorId > 0) + { + try + { + //the upload directory may already exist if this is a new DB working with a previously installed application + if (Directory.Exists(mappedHomeDirectory)) + { + Globals.DeleteFolderRecursive(mappedHomeDirectory); + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("DeleteUploadFolder.Error") + Exc.Message + Exc.StackTrace; + } + + //Set up Child Portal + if (message == Null.NullString) + { + if (isChildPortal) + { + message = CreateChildPortalFolder(childPath); + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + try + { + //create the upload directory for the new portal + Directory.CreateDirectory(mappedHomeDirectory); + //ensure that the Templates folder exists + string templateFolder = String.Format("{0}Templates", mappedHomeDirectory); + if (!Directory.Exists(templateFolder)) + { + Directory.CreateDirectory(templateFolder); + } + + //ensure that the Users folder exists + string usersFolder = String.Format("{0}Users", mappedHomeDirectory); + if (!Directory.Exists(usersFolder)) + { + Directory.CreateDirectory(usersFolder); + } + + //copy the default page template + CopyPageTemplate("Default.page.template", mappedHomeDirectory); + + // process zip resource file if present + if (File.Exists(template.ResourceFilePath)) + { + ProcessResourceFileExplicit(mappedHomeDirectory, template.ResourceFilePath); + } + + //copy getting started css into portal's folder. + var hostGettingStartedFile = string.Format("{0}GettingStarted.css", Globals.HostMapPath); + if (File.Exists(hostGettingStartedFile)) + { + var portalFile = mappedHomeDirectory + "GettingStarted.css"; + if (!File.Exists(portalFile)) + { + File.Copy(hostGettingStartedFile, portalFile); + } + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("ChildPortal.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + try + { + FolderMappingController.Instance.AddDefaultFolderTypes(portalId); + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("DefaultFolderMappings.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + + LocaleCollection newPortalLocales = null; + if (message == Null.NullString) + { + try + { + ParseTemplate(portalId, templatePath, templateFile, administratorId, PortalTemplateModuleAction.Replace, true, out newPortalLocales); + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("PortalTemplate.Error") + Exc.Message + Exc.StackTrace; + } + } + else + { + throw new Exception(message); + } + if (message == Null.NullString) + { + var portal = GetPortal(portalId); + portal.Description = description; + portal.KeyWords = keyWords; + portal.UserTabId = TabController.GetTabByTabPath(portal.PortalID, "//UserProfile", portal.CultureCode); + if (portal.UserTabId == -1) + { + portal.UserTabId = TabController.GetTabByTabPath(portal.PortalID, "//ActivityFeed", portal.CultureCode); + } + portal.SearchTabId = TabController.GetTabByTabPath(portal.PortalID, "//SearchResults", portal.CultureCode); + UpdatePortalInfo(portal); + adminUser.Profile.PreferredLocale = portal.DefaultLanguage; + var portalSettings = new PortalSettings(portal); + adminUser.Profile.PreferredTimeZone = portalSettings.TimeZone; + UserController.UpdateUser(portal.PortalID, adminUser); + DesktopModuleController.AddDesktopModulesToPortal(portalId); + AddPortalAlias(portalId, portalAlias); + + if (newPortalLocales != null) + { + foreach (Locale newPortalLocale in newPortalLocales.AllValues) + { + Localization.AddLanguageToPortal(portalId, newPortalLocale.LanguageId, false); + } + } + + try + { + RelationshipController.Instance.CreateDefaultRelationshipsForPortal(portalId); + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + //add profanity list to new portal + try + { + const string listName = "ProfanityFilter"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + entry.PortalID = portalId; + entry.SystemList = false; + entry.ListName = listName + "-" + portalId; + listController.AddListEntry(entry); + + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + //add banned password list to new portal + try + { + const string listName = "BannedPasswords"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + entry.PortalID = portalId; + entry.SystemList = false; + entry.ListName = listName + "-" + portalId; + listController.AddListEntry(entry); + + } + catch (Exception Exc) + { + Logger.Error(Exc); + } + + // Add default workflows + try + { + ContentWorkflowController.Instance.CreateDefaultWorkflows(portalId); + } + catch (Exception ex) + { + Logger.Error(ex); + } + + ServicesRoutingManager.ReRegisterServiceRoutesWhileSiteIsRunning(); + + try + { + var objEventLogInfo = new LogInfo(); + objEventLogInfo.BypassBuffering = true; + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Install Portal:", portalName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("FirstName:", adminUser.FirstName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("LastName:", adminUser.LastName)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Username:", adminUser.Username)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Email:", adminUser.Email)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Description:", description)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Keywords:", keyWords)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Template:", template.TemplateFilePath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("TemplateCulture:", template.CultureCode)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("HomeDirectory:", homeDirectory)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("PortalAlias:", portalAlias)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("ServerPath:", serverPath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("ChildPath:", childPath)); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("IsChildPortal:", isChildPortal.ToString())); + var eventLog = new EventLogController(); + eventLog.AddLog(objEventLogInfo); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + else + { + throw new Exception(message); + } + } + else + { + DeletePortalInfo(portalId); + portalId = -1; + throw new Exception(message); + } + } + else + { + message += Localization.GetString("CreatePortal.Error"); + throw new Exception(message); + } + return portalId; + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates a new portal. + /// + /// Name of the portal to be created + /// Portal Administrator's first name + /// Portal Administrator's last name + /// Portal Administrator's username + /// Portal Administrator's password + /// Portal Administrator's email + /// Description for the new portal + /// KeyWords for the new portal + /// Path where the templates are stored + /// Template file + /// Home Directory + /// Portal Alias String + /// The Path to the root of the Application + /// The Path to the Child Portal Folder + /// True if this is a child portal + /// PortalId of the new portal if there are no errors, -1 otherwise. + /// + /// After the selected portal template is parsed the admin template ("admin.template") will be + /// also processed. The admin template should only contain the "Admin" menu since it's the same + /// on all portals. The selected portal template can contain a node to specify portal + /// properties and a node to define the roles that will be created on the portal by default. + /// + /// + /// [cnurse] 11/08/2004 created (most of this code was moved from SignUp.ascx.vb) + /// + /// ----------------------------------------------------------------------------- + public int CreatePortal(string portalName, string firstName, string lastName, string username, string password, string email, + string description, string keyWords, string templatePath, string templateFile, string homeDirectory, + string portalAlias, string serverPath, string childPath, bool isChildPortal) + { + UserInfo adminUser = new UserInfo(); + adminUser.FirstName = firstName; + adminUser.LastName = lastName; + adminUser.Username = username; + adminUser.DisplayName = firstName + " " + lastName; + adminUser.Membership.Password = password; + adminUser.Email = email; + adminUser.IsSuperUser = false; + adminUser.Membership.Approved = true; + adminUser.Profile.FirstName = firstName; + adminUser.Profile.LastName = lastName; + return CreatePortal(portalName, adminUser, description, keyWords, templatePath, templateFile, homeDirectory, portalAlias, serverPath, childPath, isChildPortal); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a portal permanently + /// + /// PortalId of the portal to be deleted + /// + /// + /// + /// [VMasanas] 03/09/2004 Created + /// [VMasanas] 26/10/2004 Remove dependent data (skins, modules) + /// [cnurse] 24/11/2006 Removal of Modules moved to sproc + /// + /// ----------------------------------------------------------------------------- + public void DeletePortalInfo(int portalId) + { + UserController.DeleteUsers(portalId, false, true); + DataProvider.Instance().DeletePortalInfo(portalId); + EventLogController eventLogController = new EventLogController(); + eventLogController.AddLog("PortalId", portalId.ToString(), GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTALINFO_DELETED); + DataCache.ClearHostCache(true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets information of a portal + /// + /// Id of the portal + /// PortalInfo object with portal definition + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public PortalInfo GetPortal(int portalId) + { + string defaultLanguage = GetActivePortalLanguage(portalId); + PortalInfo portal = GetPortal(portalId, defaultLanguage); + if (portal == null) + { + //Active language may not be valid, so fallback to default language + defaultLanguage = GetPortalDefaultLanguage(portalId); + portal = GetPortal(portalId, defaultLanguage); + } + return portal; + } + + public PortalInfo GetPortal(int portalId, string cultureCode) + { + PortalInfo portal = GetPortalInternal(portalId, cultureCode); + + if (Localization.ActiveLanguagesByPortalID(portalId) > 1) + { + if (portal == null) + { + //Get Fallback language + string fallbackLanguage = string.Empty; + + if (string.IsNullOrEmpty(cultureCode)) cultureCode = Localization.SystemLocale; + + Locale userLocale = LocaleController.Instance.GetLocale(cultureCode); + if (userLocale != null && !string.IsNullOrEmpty(userLocale.Fallback)) + { + fallbackLanguage = userLocale.Fallback; + } + portal = GetPortalInternal(portalId, fallbackLanguage); + //if we cannot find any fallback, it mean's it's a non portal default langauge + if (portal == null) + { + DataProvider.Instance().EnsureLocalizationExists(portalId, GetActivePortalLanguage(portalId)); + DataCache.ClearHostCache(true); + portal = GetPortalInternal(portalId, GetActivePortalLanguage(portalId)); + } + } + } + return portal; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets information from all portals + /// + /// ArrayList of PortalInfo objects + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetPortals() + { + string cultureCode = Localization.SystemLocale; + string cacheKey = String.Format(DataCache.PortalCacheKey, Null.NullInteger, cultureCode); + var portals = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.PortalCacheTimeOut, DataCache.PortalCachePriority, cultureCode), + GetPortalsCallBack); + return new ArrayList(portals); + } + + public List GetPortalList(string cultureCode) + { + string cacheKey = String.Format(DataCache.PortalCacheKey, Null.NullInteger, cultureCode); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.PortalCacheTimeOut, DataCache.PortalCachePriority, cultureCode), + GetPortalsCallBack); + } + + /// + /// Gets the portal. + /// + /// The unique id. + /// Portal info. + public PortalInfo GetPortal(Guid uniqueId) + { + ArrayList portals = GetPortals(); + PortalInfo targetPortal = null; + + foreach (PortalInfo currentPortal in portals) + { + if (currentPortal.GUID == uniqueId) + { + targetPortal = currentPortal; + break; + } + } + return targetPortal; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the space used at the host level + /// + /// Space used in bytes + /// + /// + /// + /// [VMasanas] 19/04/2006 Created + /// + /// ----------------------------------------------------------------------------- + public long GetPortalSpaceUsedBytes() + { + return GetPortalSpaceUsedBytes(-1); + } + + /// + /// Gets the portal space used bytes. + /// + /// The portal id. + /// Space used in bytes + public long GetPortalSpaceUsedBytes(int portalId) + { + long size = 0; + IDataReader dr = null; + dr = DataProvider.Instance().GetPortalSpaceUsed(portalId); + try + { + if (dr.Read()) + { + if (dr["SpaceUsed"] != DBNull.Value) + { + size = Convert.ToInt64(dr["SpaceUsed"]); + } + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return size; + } + + /// ----------------------------------------------------------------------------- + /// + /// Verifies if there's enough space to upload a new file on the given portal + /// + /// Id of the portal + /// Size of the file being uploaded + /// True if there's enough space available to upload the file + /// + /// + /// + /// [VMasanas] 19/04/2006 Created + /// + /// ----------------------------------------------------------------------------- + public bool HasSpaceAvailable(int portalId, long fileSizeBytes) + { + int hostSpace; + if (portalId == -1) + { + hostSpace = 0; + } + else + { + PortalSettings ps = GetCurrentPortalSettings(); + if (ps != null && ps.PortalId == portalId) + { + hostSpace = ps.HostSpace; + } + else + { + PortalInfo portal = GetPortal(portalId); + hostSpace = portal.HostSpace; + } + } + return (((GetPortalSpaceUsedBytes(portalId) + fileSizeBytes) / Math.Pow(1024, 2)) <= hostSpace) || hostSpace == 0; + } + + /// + /// Remaps the Special Pages such as Home, Profile, Search + /// to their localized versions + /// + /// + /// + public void MapLocalizedSpecialPages(int portalId, string cultureCode) + { + TabController tabCont = new TabController(); + + DataCache.ClearHostCache(true); + DataProvider.Instance().EnsureLocalizationExists(portalId, cultureCode); + + PortalInfo defaultPortal = GetPortal(portalId, GetPortalDefaultLanguage(portalId)); + PortalInfo targetPortal = GetPortal(portalId, cultureCode); + + Locale targetLocale = LocaleController.Instance.GetLocale(cultureCode); + TabInfo tempTab; + if ((defaultPortal.HomeTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.HomeTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.HomeTabId = tempTab.TabID; + } + } + if ((defaultPortal.LoginTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.LoginTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.LoginTabId = tempTab.TabID; + } + } + if ((defaultPortal.RegisterTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.RegisterTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.RegisterTabId = tempTab.TabID; + } + } + if ((defaultPortal.SplashTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.SplashTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.SplashTabId = tempTab.TabID; + } + } + if ((defaultPortal.UserTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.UserTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.UserTabId = tempTab.TabID; + } + } + if ((defaultPortal.SearchTabId != Null.NullInteger)) + { + tempTab = tabCont.GetTabByCulture(defaultPortal.SearchTabId, portalId, targetLocale); + if (tempTab != null) + { + targetPortal.SearchTabId = tempTab.TabID; + } + } + + UpdatePortalInfo(targetPortal, false); + } + /// + /// Removes the related PortalLocalization record from the database + /// + /// + /// + public void RemovePortalLocalization(int portalId, string cultureCode) + { + RemovePortalLocalization(portalId, cultureCode, true); + } + /// + /// Removes the related PortalLocalization record from the database, adds optional clear cache + /// + /// + /// + /// + public void RemovePortalLocalization(int portalId, string cultureCode, bool clearCache) + { + DataProvider.Instance().RemovePortalLocalization(portalId, cultureCode); + if (clearCache) + { + DataCache.ClearPortalCache(portalId, false); + } + } + + /// + /// Processess a template file for the new portal. + /// + /// PortalId of the new portal + /// The template + /// UserId for the portal administrator. This is used to assign roles to this user + /// Flag to determine whether Module content is merged. + /// Flag to determine is the template is applied to an existing portal or a new one. + /// + /// The roles and settings nodes will only be processed on the portal template file. + /// + public void ParseTemplate(int portalId, PortalTemplateInfo template, int administratorId, PortalTemplateModuleAction mergeTabs, bool isNewPortal) + { + string templatePath, templateFile; + PrepareLocalizedPortalTemplate(template, out templatePath, out templateFile); + + ParseTemplate(portalId, templatePath, templateFile, administratorId, mergeTabs, isNewPortal); + } + + /// ----------------------------------------------------------------------------- + /// + /// Processess a template file for the new portal. This method will be called twice: for the portal template and for the admin template + /// + /// PortalId of the new portal + /// Path for the folder where templates are stored + /// Template file to process + /// UserId for the portal administrator. This is used to assign roles to this user + /// Flag to determine whether Module content is merged. + /// Flag to determine is the template is applied to an existing portal or a new one. + /// + /// The roles and settings nodes will only be processed on the portal template file. + /// + /// + /// [VMasanas] 27/08/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void ParseTemplate(int PortalId, string TemplatePath, string TemplateFile, int AdministratorId, PortalTemplateModuleAction mergeTabs, bool IsNewPortal) + { + LocaleCollection localeCollection; + ParseTemplate(PortalId, TemplatePath, TemplateFile, AdministratorId, mergeTabs, IsNewPortal, out localeCollection); + } + + public void ParseTemplate(int PortalId, string TemplatePath, string TemplateFile, int AdministratorId, PortalTemplateModuleAction mergeTabs, bool IsNewPortal, out LocaleCollection localeCollection) + { + XmlDocument xmlPortal = new XmlDocument(); + IFolderInfo objFolder; + XmlNode node; + try + { + xmlPortal.Load(Path.Combine(TemplatePath, TemplateFile)); + } + catch(Exception ex) + { + Logger.Error(ex); + } + node = xmlPortal.SelectSingleNode("//portal/settings"); + if (node != null && IsNewPortal) + { + ParsePortalSettings(node, PortalId); + } + node = xmlPortal.SelectSingleNode("//locales"); + if (node != null && IsNewPortal) + { + localeCollection = ParseEnabledLocales(node, PortalId); + } + else + { + var portalInfo = new PortalController().GetPortal(PortalId); + var defaultLocale = LocaleController.Instance.GetLocale(portalInfo.DefaultLanguage); + if (defaultLocale == null) + { + defaultLocale = new Locale { Code = portalInfo.DefaultLanguage, Fallback = Localization.SystemLocale, Text = CultureInfo.CreateSpecificCulture(portalInfo.DefaultLanguage).NativeName }; + Localization.SaveLanguage(defaultLocale, false); + } + localeCollection = new LocaleCollection { { defaultLocale.Code, defaultLocale } }; + } + node = xmlPortal.SelectSingleNode("//portal/rolegroups"); + if (node != null) + { + ParseRoleGroups(node.CreateNavigator(), PortalId, AdministratorId); + } + node = xmlPortal.SelectSingleNode("//portal/roles"); + if (node != null) + { + ParseRoles(node.CreateNavigator(), PortalId, AdministratorId); + } + node = xmlPortal.SelectSingleNode("//portal/portalDesktopModules"); + if (node != null) + { + ParsePortalDesktopModules(node.CreateNavigator(), PortalId); + } + node = xmlPortal.SelectSingleNode("//portal/folders"); + if (node != null) + { + ParseFolders(node, PortalId); + } + + var defaultFolderMapping = FolderMappingController.Instance.GetDefaultFolderMapping(PortalId); + + if (FolderManager.Instance.GetFolder(PortalId, "") == null) + { + objFolder = FolderManager.Instance.AddFolder(defaultFolderMapping, ""); + objFolder.IsProtected = true; + FolderManager.Instance.UpdateFolder(objFolder); + + AddFolderPermissions(PortalId, objFolder.FolderID); + } + + if (FolderManager.Instance.GetFolder(PortalId, "Templates/") == null) + { + objFolder = FolderManager.Instance.AddFolder(defaultFolderMapping, "Templates/"); + objFolder.IsProtected = true; + FolderManager.Instance.UpdateFolder(objFolder); + + //AddFolderPermissions(PortalId, objFolder.FolderID); + } + + // force creation of users folder if not present on template + if (FolderManager.Instance.GetFolder(PortalId, "Users/") == null) + { + objFolder = FolderManager.Instance.AddFolder(defaultFolderMapping, "Users/"); + objFolder.IsProtected = true; + FolderManager.Instance.UpdateFolder(objFolder); + + //AddFolderPermissions(PortalId, objFolder.FolderID); + } + + if (mergeTabs == PortalTemplateModuleAction.Replace) + { + TabController objTabs = new TabController(); + TabInfo objTab; + foreach (KeyValuePair tabPair in objTabs.GetTabsByPortal(PortalId)) + { + objTab = tabPair.Value; + objTab.TabName = objTab.TabName + "_old"; + objTab.TabPath = Globals.GenerateTabPath(objTab.ParentId, objTab.TabName); + objTab.IsDeleted = true; + objTabs.UpdateTab(objTab); + ModuleController objModules = new ModuleController(); + ModuleInfo objModule; + foreach (KeyValuePair modulePair in objModules.GetTabModules(objTab.TabID)) + { + objModule = modulePair.Value; + objModules.DeleteTabModule(objModule.TabID, objModule.ModuleID, false); + } + } + } + node = xmlPortal.SelectSingleNode("//portal/tabs"); + if (node != null) + { + string version = xmlPortal.DocumentElement.GetAttribute("version"); + if (version != "5.0") + { + XmlDocument xmlAdmin = new XmlDocument(); + try + { + string path = Path.Combine(TemplatePath, "admin.template"); + if(!File.Exists(path)) + { + //if the template is a merged copy of a localized templte the + //admin.template may be one director up + path = Path.Combine(TemplatePath, "..\admin.template"); + } + + xmlAdmin.Load(path); + + XmlNode adminNode = xmlAdmin.SelectSingleNode("//portal/tabs"); + foreach (XmlNode adminTabNode in adminNode.ChildNodes) + { + node.AppendChild(xmlPortal.ImportNode(adminTabNode, true)); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + ParseTabs(node, PortalId, false, mergeTabs, IsNewPortal); + } + } + + /// + /// Processes the resource file for the template file selected + /// + /// New portal's folder + /// Selected template file + /// + /// The resource file is a zip file with the same name as the selected template file and with + /// an extension of .resources (to disable this file being downloaded). + /// For example: for template file "portal.template" a resource file "portal.template.resources" can be defined. + /// + [Obsolete("Deprecated in DNN 6.2.0 use ProcessResourceFileExplicit instead")] + public void ProcessResourceFile(string portalPath, string TemplateFile) + { + ProcessResourceFileExplicit(portalPath, TemplateFile + ".resources"); + } + + /// + /// Processes the resource file for the template file selected + /// + /// New portal's folder + /// full path to the resource file + /// + /// The resource file is a zip file with the same name as the selected template file and with + /// an extension of .resources (to disable this file being downloaded). + /// For example: for template file "portal.template" a resource file "portal.template.resources" can be defined. + /// + public void ProcessResourceFileExplicit(string portalPath, string resoureceFile) + { + try + { + var zipStream = new ZipInputStream(new FileStream(resoureceFile, FileMode.Open, FileAccess.Read)); + FileSystemUtils.UnzipResources(zipStream, portalPath); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + /// + /// Updates the portal expiry. + /// + /// The portal id. + public void UpdatePortalExpiry(int PortalId) + { + UpdatePortalExpiry(PortalId, GetActivePortalLanguage(PortalId)); + } + + /// + /// Updates the portal expiry. + /// + /// The portal id. + /// The culture code. + public void UpdatePortalExpiry(int PortalId, string CultureCode) + { + var portal = GetPortal(PortalId, CultureCode); + + if (portal.ExpiryDate == Null.NullDate) + { + portal.ExpiryDate = DateTime.Now; + } + portal.ExpiryDate = portal.ExpiryDate.AddMonths(1); + + UpdatePortalInfo(portal); + } + + /// + /// Updates basic portal information + /// + /// + public void UpdatePortalInfo(PortalInfo portal) + { + UpdatePortalInfo(portal, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates basic portal information + /// + /// + /// + /// + /// + /// [cnurse] 10/13/2004 created + /// + /// ----------------------------------------------------------------------------- + public void UpdatePortalInfo(PortalInfo portal, bool clearCache) + { + DataProvider.Instance().UpdatePortalInfo(portal.PortalID, + portal.PortalGroupID, + portal.PortalName, + portal.LogoFile, + portal.FooterText, + portal.ExpiryDate, + portal.UserRegistration, + portal.BannerAdvertising, + portal.Currency, + portal.AdministratorId, + portal.HostFee, + portal.HostSpace, + portal.PageQuota, + portal.UserQuota, + portal.PaymentProcessor, + portal.ProcessorUserId, + portal.ProcessorPassword, + portal.Description, + portal.KeyWords, + portal.BackgroundFile, + portal.SiteLogHistory, + portal.SplashTabId, + portal.HomeTabId, + portal.LoginTabId, + portal.RegisterTabId, + portal.UserTabId, + portal.SearchTabId, + portal.DefaultLanguage, + portal.HomeDirectory, + UserController.GetCurrentUserInfo().UserID, + portal.CultureCode); + + var eventLogController = new EventLogController(); + eventLogController.AddLog("PortalId", portal.PortalID.ToString(), GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTALINFO_UPDATED); + + //ensure a localization item exists (in case a new default language has been set) + DataProvider.Instance().EnsureLocalizationExists(portal.PortalID, portal.DefaultLanguage); + + //clear portal cache + if (clearCache) + DataCache.ClearHostCache(true); + } + + public class PortalTemplateInfo + { + private string _resourceFilePath; + + public PortalTemplateInfo(string templateFilePath, string cultureCode) + { + TemplateFilePath = templateFilePath; + + InitLocalizationFields(cultureCode); + InitNameAndDescription(); + } + + private void InitNameAndDescription() + { + if(!String.IsNullOrEmpty(LanguageFilePath)) + { + LoadNameAndDescriptionFromLanguageFile(); + } + + if(String.IsNullOrEmpty(Name)) + { + Name = Path.GetFileNameWithoutExtension(TemplateFilePath); + } + + if(String.IsNullOrEmpty(Description)) + { + LoadDescriptionFromTemplateFile(); + } + } + + private void LoadDescriptionFromTemplateFile() + { + try + { + XDocument xmlDoc; + using (var reader = PortalTemplateIO.Instance.OpenTextReader(TemplateFilePath)) + { + xmlDoc = XDocument.Load(reader); + } + + Description = xmlDoc.Elements("portal").Elements("description").SingleOrDefault().Value; + } + catch (Exception e) + { + Logger.Error("Error while parsing: " + TemplateFilePath, e); + } + } + + private void LoadNameAndDescriptionFromLanguageFile() + { + try + { + using (var reader = PortalTemplateIO.Instance.OpenTextReader(LanguageFilePath)) + { + var xmlDoc = XDocument.Load(reader); + + Name = ReadLanguageFileValue(xmlDoc, "LocalizedTemplateName.Text"); + Description = ReadLanguageFileValue(xmlDoc, "PortalDescription.Text"); + } + } + catch (Exception e) + { + Logger.Error("Error while parsing: " + TemplateFilePath, e); + } + } + + static string ReadLanguageFileValue(XDocument xmlDoc, string name) + { + return (from f in xmlDoc.Descendants("data") + where (string)f.Attribute("name") == name + select (string)f.Element("value")).SingleOrDefault(); + } + + private void InitLocalizationFields(string cultureCode) + { + LanguageFilePath = PortalTemplateIO.Instance.GetLanguageFilePath(TemplateFilePath, cultureCode); + if(!String.IsNullOrEmpty(LanguageFilePath)) + { + CultureCode = cultureCode; + } + else + { + CultureCode = ""; + } + } + + public string Name { get; private set; } + public string CultureCode { get; private set; } + public string TemplateFilePath { get; private set; } + public string LanguageFilePath { get; private set; } + public string Description { get; private set; } + + public string ResourceFilePath + { + get + { + if(_resourceFilePath == null) + { + _resourceFilePath = PortalTemplateIO.Instance.GetResourceFilePath(TemplateFilePath); + } + + return _resourceFilePath; + } + } + } + + /// + /// Get all the available portal templates grouped by culture + /// + /// List of PortalTemplateInfo objects + public IList GetAvailablePortalTemplates() + { + var list = new List(); + + var templateFilePaths = PortalTemplateIO.Instance.EnumerateTemplates(); + var languageFileNames = PortalTemplateIO.Instance.EnumerateLanguageFiles().Select(x => Path.GetFileName(x)).ToList(); + + foreach (string templateFilePath in templateFilePaths) + { + var currentFileName = Path.GetFileName(templateFilePath); + var langs = languageFileNames.Where(x => GetTemplateName(x).Equals(currentFileName, StringComparison.InvariantCultureIgnoreCase)).Select(x => GetCultureCode(x)).Distinct().ToList(); + + if(langs.Any()) + { + langs.ForEach(x => list.Add(new PortalTemplateInfo(templateFilePath, x))); + } + else + { + list.Add(new PortalTemplateInfo(templateFilePath, "")); + } + } + + return list; + } + + /// + /// Load info for a portal template + /// + /// Full path to the portal template + /// the culture code if any for the localization of the portal template + /// A portal template + public PortalTemplateInfo GetPortalTemplate(string templatePath, string cultureCode) + { + var template = new PortalTemplateInfo(templatePath, cultureCode); + + if(!string.IsNullOrEmpty(cultureCode) && template.CultureCode != cultureCode) + { + return null; + } + + return template; + } + + #endregion + + #region Interface Implementation + + /// + /// Gets the current portal settings. + /// + /// portal settings. + PortalSettings IPortalController.GetCurrentPortalSettings() + { + return GetCurrentPortalSettings(); + } + + #endregion + + #region Public Static Methods + + /// + /// Adds the portal dictionary. + /// + /// The portal id. + /// The tab id. + public static void AddPortalDictionary(int portalId, int tabId) + { + var portalDic = GetPortalDictionary(); + portalDic[tabId] = portalId; + DataCache.SetCache(DataCache.PortalDictionaryCacheKey, portalDic); + } + + /// + /// Creates the root folder for a child portal. + /// + /// + /// If call this method, it will create the specific folder if the folder doesn't exist; + /// and will copy subhost.aspx to the folder if there is no 'Default.aspx'; + /// + /// The child path. + /// + /// If the method executed successful, it will return NullString, otherwise return error message. + /// + /// + /// + /// string childPhysicalPath = Server.MapPath(childPath); + /// message = PortalController.CreateChildPortalFolder(childPhysicalPath); + /// + /// + public static string CreateChildPortalFolder(string ChildPath) + { + string message = Null.NullString; + + //Set up Child Portal + try + { + // create the subdirectory for the new portal + if (!Directory.Exists(ChildPath)) + { + Directory.CreateDirectory(ChildPath); + } + + // create the subhost default.aspx file + if (!File.Exists(ChildPath + "\\" + Globals.glbDefaultPage)) + { + File.Copy(Globals.HostMapPath + "subhost.aspx", ChildPath + "\\" + Globals.glbDefaultPage); + } + } + catch (Exception Exc) + { + Logger.Error(Exc); + message += Localization.GetString("ChildPortal.Error") + Exc.Message + Exc.StackTrace; + } + + return message; + } + + /// + /// Deletes all expired portals. + /// + /// The server path. + public static void DeleteExpiredPortals(string serverPath) + { + foreach (PortalInfo portal in GetExpiredPortals()) + { + DeletePortal(portal, serverPath); + } + } + + /// + /// Deletes the portal. + /// + /// The portal. + /// The server path. + /// If the method executed successful, it will return NullString, otherwise return error message. + public static string DeletePortal(PortalInfo portal, string serverPath) + { + var portalController = new PortalController(); + string message = string.Empty; + + //check if this is the last portal + int portalCount = portalController.GetPortals().Count; + if (portalCount > 1) + { + if (portal != null) + { + //delete custom resource files + Globals.DeleteFilesRecursive(serverPath, ".Portal-" + portal.PortalID + ".resx"); + + //If child portal delete child folder + var arr = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portal.PortalID).ToList(); + if (arr.Count > 0) + { + var portalAliasInfo = (PortalAliasInfo)arr[0]; + string portalName = Globals.GetPortalDomainName(portalAliasInfo.HTTPAlias, null, true); + if (portalAliasInfo.HTTPAlias.IndexOf("/", StringComparison.Ordinal) > -1) + { + portalName = GetPortalFolder(portalAliasInfo.HTTPAlias); + } + if (!String.IsNullOrEmpty(portalName) && Directory.Exists(serverPath + portalName)) + { + DeletePortalFolder(serverPath, portalName); + } + } + //delete upload directory + Globals.DeleteFolderRecursive(serverPath + "Portals\\" + portal.PortalID); + if (!string.IsNullOrEmpty(portal.HomeDirectory)) + { + string HomeDirectory = portal.HomeDirectoryMapPath; + if (Directory.Exists(HomeDirectory)) + { + Globals.DeleteFolderRecursive(HomeDirectory); + } + } + //remove database references + portalController.DeletePortalInfo(portal.PortalID); + } + } + else + { + message = Localization.GetString("LastPortal"); + } + return message; + } + + /// + /// Get the portal folder froma child portal alias. + /// + /// portal alias. + /// folder path of the child portal. + public static string GetPortalFolder(string alias) + { + alias = alias.ToLowerInvariant().Replace("http://", string.Empty).Replace("https://", string.Empty); + var appPath = Globals.ApplicationPath + "/"; + if (string.IsNullOrEmpty(Globals.ApplicationPath) || alias.IndexOf(appPath, StringComparison.InvariantCultureIgnoreCase) == Null.NullInteger) + { + return alias.Contains("/") ? alias.Substring(alias.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) + 1) : string.Empty; + } + + return alias.Substring(alias.IndexOf(appPath, StringComparison.InvariantCultureIgnoreCase) + appPath.Length); + } + + /// + /// Delete the child portal folder and try to remove its parent when parent folder is empty. + /// + /// the server path. + /// the child folder path. + /// + public static void DeletePortalFolder(string serverPath, string portalFolder) + { + var physicalPath = serverPath + portalFolder; + Globals.DeleteFolderRecursive(physicalPath); + //remove parent folder if its empty. + var parentFolder = Directory.GetParent(physicalPath); + while (parentFolder != null && !parentFolder.FullName.Equals(serverPath.TrimEnd('\\'), StringComparison.InvariantCultureIgnoreCase)) + { + if (parentFolder.GetDirectories().Length + parentFolder.GetFiles().Length == 0) + { + parentFolder.Delete(); + parentFolder = parentFolder.Parent; + } + else + { + break; + } + } + } + + /// + /// Gets the portal dictionary. + /// + /// portal dictionary. the dictionary's Key -> Value is: TabId -> PortalId. + public static Dictionary GetPortalDictionary() + { + string cacheKey = string.Format(DataCache.PortalDictionaryCacheKey); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.PortalDictionaryTimeOut, DataCache.PortalDictionaryCachePriority), GetPortalDictionaryCallback); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetPortalsByName gets all the portals whose name matches a provided filter expression + /// + /// + /// + /// The email address to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of PortalInfo objects. + /// + /// [cnurse] 11/17/2006 created + /// + /// ----------------------------------------------------------------------------- + public static ArrayList GetPortalsByName(string nameToMatch, int pageIndex, int pageSize, ref int totalRecords) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + Type type = typeof(PortalInfo); + return CBO.FillCollection(DataProvider.Instance().GetPortalsByName(nameToMatch, pageIndex, pageSize), ref type, ref totalRecords); + } + + public static ArrayList GetPortalsByUser(int userId) + { + Type type = typeof(PortalInfo); + return CBO.FillCollection(DataProvider.Instance().GetPortalsByUser(userId), type); + } + + /// + /// Gets the current portal settings. + /// + /// portal settings. + public static PortalSettings GetCurrentPortalSettings() + { + PortalSettings objPortalSettings = null; + if (HttpContext.Current != null) + { + objPortalSettings = (PortalSettings)HttpContext.Current.Items["PortalSettings"]; + } + return objPortalSettings; + } + + public static int GetEffectivePortalId(int portalId) + { + if (portalId > Null.NullInteger && Globals.Status != Globals.UpgradeStatus.Upgrade) + { + //var portalController = new PortalController(); + var portalController = TestablePortalController.Instance; + var portal = portalController.GetPortal(portalId); + var portalGroup = (from p in PortalGroupController.Instance.GetPortalGroups() + where p.PortalGroupId == portal.PortalGroupID + select p) + .SingleOrDefault(); + + if (portalGroup != null) + { + portalId = portalGroup.MasterPortalId; + } + } + + return portalId; + } + + /// + /// Gets all expired portals. + /// + /// all expired portals as array list. + public static ArrayList GetExpiredPortals() + { + return CBO.FillCollection(DataProvider.Instance().GetExpiredPortals(), typeof(PortalInfo)); + } + + /// + /// Determines whether the portal is child portal. + /// + /// The portal. + /// The server path. + /// + /// true if the portal is child portal; otherwise, false. + /// + public static bool IsChildPortal(PortalInfo portal, string serverPath) + { + bool isChild = Null.NullBoolean; + string portalName; + var arr = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portal.PortalID).ToList(); + if (arr.Count > 0) + { + PortalAliasInfo portalAlias = (PortalAliasInfo)arr[0]; + portalName = Globals.GetPortalDomainName(portalAlias.HTTPAlias, null, true); + if (portalAlias.HTTPAlias.IndexOf("/") > -1) + { + portalName = GetPortalFolder(portalAlias.HTTPAlias); + } + if (!String.IsNullOrEmpty(portalName) && Directory.Exists(serverPath + portalName)) + { + isChild = true; + } + } + return isChild; + } + + public static bool IsMemberOfPortalGroup(int portalId) + { + //var portalController = new PortalController(); + var portalController = TestablePortalController.Instance; + var portal = portalController.GetPortal(portalId); + + return portal != null && portal.PortalGroupID > Null.NullInteger; + } + + /// + /// Deletes the portal setting. + /// + /// The portal ID. + /// Name of the setting. + public static void DeletePortalSetting(int portalID, string settingName) + { + DeletePortalSetting(portalID, settingName, GetActivePortalLanguage(portalID)); + } + + /// + /// Deletes the portal setting. + /// + /// The portal ID. + /// Name of the setting. + /// The culture code. + public static void DeletePortalSetting(int portalID, string settingName, string CultureCode) + { + DataProvider.Instance().DeletePortalSetting(portalID, settingName, CultureCode.ToLower()); + EventLogController objEventLog = new EventLogController(); + objEventLog.AddLog("SettingName", settingName, GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTAL_SETTING_DELETED); + DataCache.ClearHostCache(true); + } + + /// + /// Deletes all portal settings by portal id. + /// + /// The portal ID. + public static void DeletePortalSettings(int portalID) + { + DataProvider.Instance().DeletePortalSettings(portalID); + EventLogController objEventLog = new EventLogController(); + objEventLog.AddLog("PortalID", portalID.ToString(), GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTAL_SETTING_DELETED); + DataCache.ClearHostCache(true); + } + + /// + /// Gets the portal settings dictionary. + /// + /// The portal ID. + /// portal settings. + public static Dictionary GetPortalSettingsDictionary(int portalID) + { + return GetPortalSettingsDictionary(portalID, string.Empty); + } + + /// + /// Gets the portal setting. + /// + /// Name of the setting. + /// The portal ID. + /// The default value. + /// Returns setting's value if portal contains the specific setting, otherwise return defaultValue. + public static string GetPortalSetting(string settingName, int portalID, string defaultValue) + { + var retValue = Null.NullString; + try + { + string setting; + GetPortalSettingsDictionary(portalID).TryGetValue(settingName, out setting); + retValue = string.IsNullOrEmpty(setting) ? defaultValue : setting; + } + catch (Exception exc) + { + Logger.Error(exc); + } + return retValue; + } + + /// + /// Gets the portal setting as boolean. + /// + /// The key. + /// The portal ID. + /// default value. + /// Returns setting's value if portal contains the specific setting, otherwise return defaultValue. + public static bool GetPortalSettingAsBoolean(string key, int portalID, bool defaultValue) + { + bool retValue = Null.NullBoolean; + try + { + string setting = Null.NullString; + GetPortalSettingsDictionary(portalID).TryGetValue(key, out setting); + if (string.IsNullOrEmpty(setting)) + { + retValue = defaultValue; + } + else + { + retValue = (setting.StartsWith("Y", StringComparison.InvariantCultureIgnoreCase) || setting.ToUpperInvariant() == "TRUE"); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + return retValue; + } + + /// + /// Gets the portal setting as integer. + /// + /// The key. + /// The portal ID. + /// The default value. + /// Returns setting's value if portal contains the specific setting, otherwise return defaultValue. + public static int GetPortalSettingAsInteger(string key, int portalID, int defaultValue) + { + int retValue = Null.NullInteger; + try + { + string setting = Null.NullString; + GetPortalSettingsDictionary(portalID).TryGetValue(key, out setting); + if (string.IsNullOrEmpty(setting)) + { + retValue = defaultValue; + } + else + { + retValue = Convert.ToInt32(setting); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + return retValue; + } + + /// + /// Updates the portal setting. + /// + /// The portal ID. + /// Name of the setting. + /// The setting value. + public static void UpdatePortalSetting(int portalID, string settingName, string settingValue) + { + UpdatePortalSetting(portalID, settingName, settingValue, true); + } + + /// + /// Updates the portal setting. + /// + /// The portal ID. + /// Name of the setting. + /// The setting value. + /// if set to true [clear cache]. + public static void UpdatePortalSetting(int portalID, string settingName, string settingValue, bool clearCache) + { + string culture = Thread.CurrentThread.CurrentCulture.ToString().ToLower(); + if ((string.IsNullOrEmpty(culture))) + { + culture = GetPortalSetting("DefaultLanguage", portalID, "".ToLower()); + } + if ((string.IsNullOrEmpty(culture))) + { + culture = Localization.SystemLocale.ToLower(); + } + UpdatePortalSetting(portalID, settingName, settingValue, clearCache, culture); + } + + /// + /// Updates the portal setting. + /// + /// The portal ID. + /// Name of the setting. + /// The setting value. + /// if set to true [clear cache]. + /// The culturecode. + public static void UpdatePortalSetting(int portalID, string settingName, string settingValue, bool clearCache, string culturecode) + { + string currentSetting = GetPortalSetting(settingName, portalID, String.Empty); + + if (currentSetting != settingValue) + { + DataProvider.Instance().UpdatePortalSetting(portalID, settingName, settingValue, UserController.GetCurrentUserInfo().UserID, culturecode); + var objEventLog = new EventLogController(); + objEventLog.AddLog(settingName, settingValue, GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.PORTAL_SETTING_UPDATED); + if (clearCache) + { + DataCache.ClearPortalCache(portalID, false); + DataCache.RemoveCache(DataCache.PortalDictionaryCacheKey); + } + } + } + + /// + /// Checks the desktop modules whether is installed. + /// + /// The nav. + /// Empty string if the module hasn't been installed, otherwise return the frind name. + public static string CheckDesktopModulesInstalled(XPathNavigator nav) + { + string friendlyName = Null.NullString; + DesktopModuleInfo desktopModule = null; + StringBuilder modulesNotInstalled = new StringBuilder(); + + foreach (XPathNavigator desktopModuleNav in nav.Select("portalDesktopModule")) + { + friendlyName = XmlUtils.GetNodeValue(desktopModuleNav, "friendlyname"); + + if (!string.IsNullOrEmpty(friendlyName)) + { + desktopModule = DesktopModuleController.GetDesktopModuleByFriendlyName(friendlyName); + if (desktopModule == null) + { + //PE and EE templates have HTML as friendly name so check to make sure + //there is really no HTML module installed + if (friendlyName == "HTML") + { + desktopModule = DesktopModuleController.GetDesktopModuleByFriendlyName("HTML Pro"); + if (desktopModule == null) + { + modulesNotInstalled.Append(friendlyName); + modulesNotInstalled.Append("
"); + } + } + else + { + modulesNotInstalled.Append(friendlyName); + modulesNotInstalled.Append("
"); + } + } + } + } + return modulesNotInstalled.ToString(); + } + + /// + /// function provides the language for portalinfo requests + /// in case where language has not been installed yet, will return the core install default of en-us + /// + /// + /// + /// + /// + public static string GetActivePortalLanguage(int portalID) + { + // get Language + string Language = Localization.SystemLocale; + string tmpLanguage = GetPortalDefaultLanguage(portalID); + var isDefaultLanguage = false; + if (!String.IsNullOrEmpty(tmpLanguage)) + { + Language = tmpLanguage; + isDefaultLanguage = true; + } + //handles case where portalcontroller methods invoked before a language is installed + if (portalID > Null.NullInteger && Globals.Status == Globals.UpgradeStatus.None && Localization.ActiveLanguagesByPortalID(portalID) == 1) + { + return Language; + } + if (HttpContext.Current != null && Globals.Status == Globals.UpgradeStatus.None) + { + if ((HttpContext.Current.Request.QueryString["language"] != null)) + { + Language = HttpContext.Current.Request.QueryString["language"]; + isDefaultLanguage = false; + } + else + { + PortalSettings _PortalSettings = GetCurrentPortalSettings(); + if (_PortalSettings != null && _PortalSettings.ActiveTab != null && !String.IsNullOrEmpty(_PortalSettings.ActiveTab.CultureCode)) + { + Language = _PortalSettings.ActiveTab.CultureCode; + isDefaultLanguage = false; + } + else + { + //PortalSettings IS Nothing - probably means we haven't set it yet (in Begin Request) + //so try detecting the user's cookie + if (HttpContext.Current.Request["language"] != null) + { + Language = HttpContext.Current.Request["language"]; + isDefaultLanguage = false; + } + + //if no cookie - try detecting browser + if ((String.IsNullOrEmpty(Language) || isDefaultLanguage) && EnableBrowserLanguageInDefault(portalID)) + { + CultureInfo Culture = Localization.GetBrowserCulture(portalID); + + if (Culture != null) + { + Language = Culture.Name; + } + } + } + } + } + + return Language; + } + + /// + /// return the current DefaultLanguage value from the Portals table for the requested Portalid + /// + /// + /// + /// + /// + public static string GetPortalDefaultLanguage(int portalID) + { + //Return DataProvider.Instance().GetPortalDefaultLanguage(portalID) + string cacheKey = String.Format("PortalDefaultLanguage_{0}", portalID); + return CBO.GetCachedObject(new CacheItemArgs(cacheKey, DataCache.PortalCacheTimeOut, DataCache.PortalCachePriority, portalID), GetPortalDefaultLanguageCallBack); + } + + /// + /// set the required DefaultLanguage in the Portals table for a particular portal + /// saves having to update an entire PortalInfo object + /// + /// + /// + /// + /// + public static void UpdatePortalDefaultLanguage(int portalID, string CultureCode) + { + DataProvider.Instance().UpdatePortalDefaultLanguage(portalID, CultureCode); + //ensure localization record exists as new portal default language may be relying on fallback chain + //of which it is now the final part + DataProvider.Instance().EnsureLocalizationExists(portalID, CultureCode); + } + + public static void IncrementCrmVersion(int portalID) + { + int currentVersion; + var versionSetting = GetPortalSetting(ClientResourceSettings.VersionKey, portalID, "1"); + if (int.TryParse(versionSetting, out currentVersion)) + { + var newVersion = currentVersion + 1; + UpdatePortalSetting(portalID, ClientResourceSettings.VersionKey, newVersion.ToString(CultureInfo.InvariantCulture), true); + } + } + + public static void IncrementOverridingPortalsCrmVersion() + { + foreach (PortalInfo portal in new PortalController().GetPortals()) + { + string setting = GetPortalSetting(ClientResourceSettings.OverrideDefaultSettingsKey, portal.PortalID, "False"); + bool overriden; + + // if this portal is overriding the host level... + if (bool.TryParse(setting, out overriden) && overriden) + { + // increment its version + IncrementCrmVersion(portal.PortalID); + } + } + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetPortalSpaceUsedBytes")] + public int GetPortalSpaceUsed(int portalId) + { + int size = 0; + try + { + size = Convert.ToInt32(GetPortalSpaceUsedBytes(portalId)); + } + catch (Exception exc) + { + Logger.Error(exc); + + size = int.MaxValue; + } + + return size; + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by TabController.DeserializePanes")] + public void ParsePanes(XmlNode nodePanes, int portalId, int TabId, PortalTemplateModuleAction mergeTabs, Hashtable hModules) + { + TabController.DeserializePanes(nodePanes, portalId, TabId, mergeTabs, hModules); + } + + [Obsolete("Deprecated in DotNetNuke 6.1. Replaced by UpdatePortalInfo(PortalInfo)")] + public void UpdatePortalInfo(int portalId, string portalName, string logoFile, string footerText, DateTime expiryDate, int userRegistration, int bannerAdvertising, string currency, + int administratorId, double hostFee, double hostSpace, int pageQuota, int userQuota, string paymentProcessor, string processorUserId, string processorPassword, + string description, string KeyWords, string backgroundFile, int siteLogHistory, int splashTabId, int homeTabId, int loginTabId, int registerTabId, int userTabId, + int searchTabId, string defaultLanguage, string homeDirectory) + { + var portal = new PortalInfo() + { + PortalID = portalId, + PortalName = portalName, + LogoFile = logoFile, + FooterText = footerText, + ExpiryDate = expiryDate, + UserRegistration = userRegistration, + BannerAdvertising = bannerAdvertising, + Currency = currency, + AdministratorId = administratorId, + HostFee = (float)hostFee, + HostSpace = (int)hostSpace, + PageQuota = pageQuota, + UserQuota = userQuota, + PaymentProcessor = paymentProcessor, + ProcessorUserId = processorUserId, + ProcessorPassword = processorPassword, + Description = description, + KeyWords = KeyWords, + BackgroundFile = backgroundFile, + SiteLogHistory = siteLogHistory, + SplashTabId = splashTabId, + HomeTabId = homeTabId, + LoginTabId = loginTabId, + RegisterTabId = registerTabId, + UserTabId = userTabId, + SearchTabId = searchTabId, + DefaultLanguage = defaultLanguage, + HomeDirectory = homeDirectory, + CultureCode = PortalController.GetActivePortalLanguage(portalId) + }; + + UpdatePortalInfo(portal); + } + + + [Obsolete("Deprecated in DotNetNuke 6.1. Replaced by UpdatePortalInfo(PortalInfo)")] + public void UpdatePortalInfo(int portalId, string portalName, string logoFile, string footerText, DateTime expiryDate, int userRegistration, int bannerAdvertising, string currency, + int administratorId, double hostFee, double hostSpace, int pageQuota, int userQuota, string paymentProcessor, string processorUserId, string processorPassword, + string description, string keyWords, string backgroundFile, int siteLogHistory, int splashTabId, int homeTabId, int loginTabId, int registerTabId, int userTabId, + int searchTabId, string defaultLanguage, string homeDirectory, string cultureCode) +{ + var portal = new PortalInfo() + { + PortalID = portalId, + PortalName = portalName, + LogoFile = logoFile, + FooterText = footerText, + ExpiryDate = expiryDate, + UserRegistration = userRegistration, + BannerAdvertising = bannerAdvertising, + Currency = currency, + AdministratorId = administratorId, + HostFee = (float)hostFee, + HostSpace = (int)hostSpace, + PageQuota = pageQuota, + UserQuota = userQuota, + PaymentProcessor = paymentProcessor, + ProcessorUserId = processorUserId, + ProcessorPassword = processorPassword, + Description = description, + KeyWords = keyWords, + BackgroundFile = backgroundFile, + SiteLogHistory = siteLogHistory, + SplashTabId = splashTabId, + HomeTabId = homeTabId, + LoginTabId = loginTabId, + RegisterTabId = registerTabId, + UserTabId = userTabId, + SearchTabId = searchTabId, + DefaultLanguage = defaultLanguage, + HomeDirectory = homeDirectory, + CultureCode = cultureCode + }; + UpdatePortalInfo(portal); + } + + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalGroupController.cs b/DNN Platform/Library/Entities/Portals/PortalGroupController.cs new file mode 100644 index 00000000000..31ceddef684 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalGroupController.cs @@ -0,0 +1,320 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals.Data; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + public class PortalGroupController : ComponentBase, IPortalGroupController + { + private readonly IDataService _dataService; + private readonly IPortalController _portalController; + + #region Constructors + + public PortalGroupController() : this(DataService.Instance, new PortalController()) + { + } + + public PortalGroupController(IDataService dataService, IPortalController portalController) + { + //Argument Contract + Requires.NotNull("dataService", dataService); + Requires.NotNull("portalController", portalController); + + _dataService = dataService; + _portalController = portalController; + } + + #endregion + + #region Private Methods + + private object GetPortalGroupsCallback(CacheItemArgs cacheItemArgs) + { + return CBO.FillCollection(_dataService.GetPortalGroups()); + } + + private static void ClearCache() + { + DataCache.RemoveCache(DataCache.PortalGroupsCacheKey); + } + + #endregion + + #region IPortalGroupController Members + + public void AddPortalToGroup(PortalInfo portal, PortalGroupInfo portalGroup, UserCopiedCallback callback) + { + //Argument Contract + Requires.NotNull("portal", portal); + Requires.PropertyNotNegative("portal", "PortalId", portal.PortalID); + Requires.NotNull("portalGroup", portalGroup); + Requires.PropertyNotNegative("portalGroup", "PortalGroupId", portalGroup.PortalGroupId); + Requires.PropertyNotNegative("portalGroup", "MasterPortalId", portalGroup.MasterPortalId); + + //Callback to update progress bar + var args = new UserCopiedEventArgs + { + TotalUsers = 0, + UserNo = 0, + UserName = "", + PortalName = portal.PortalName, + Stage = "starting" + }; + callback(args); + + var masterPortal = _portalController.GetPortal(portalGroup.MasterPortalId); + var autoAssignRoles = TestableRoleController.Instance.GetRoles(portal.PortalID, role => role.AutoAssignment && role.Status == RoleStatus.Approved); + var roleController = new RoleController(); + + + var users = UserController.GetUsers(portal.PortalID); + var userNo = 0; + foreach (UserInfo user in users) + { + userNo += 1; + + //move user to master portal + UserController.CopyUserToPortal(user, masterPortal, true, true); + + //add user to auto assign roles + foreach (var autoAssignRole in autoAssignRoles) + { + roleController.AddUserRole(masterPortal.PortalID, user.UserID, autoAssignRole.RoleID, Null.NullDate, Null.NullDate); + } + + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = users.Count, + UserNo = userNo, + UserName = user.Username, + PortalName = portal.PortalName + }; + callback(args); + } + + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = users.Count, + UserNo = userNo, + UserName = "", + PortalName = portal.PortalName, + Stage = "finalizing" + }; + callback(args); + + //Remove Profile Definitions + foreach(ProfilePropertyDefinition definition in ProfileController.GetPropertyDefinitionsByPortal(portal.PortalID)) + { + ProfileController.DeletePropertyDefinition(definition); + } + + //Add portal to group + portal.PortalGroupID = portalGroup.PortalGroupId; + _portalController.UpdatePortalInfo(portal); + + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = users.Count, + UserNo = userNo, + UserName = "", + PortalName = portal.PortalName, + Stage = "finished", + PortalGroupId = portalGroup.PortalGroupId + }; + callback(args); + + } + + public int AddPortalGroup(PortalGroupInfo portalGroup) + { + //Argument Contract + Requires.NotNull("portalGroup", portalGroup); + + portalGroup.PortalGroupId = _dataService.AddPortalGroup(portalGroup, UserController.GetCurrentUserInfo().UserID); + + //Update portal + var portal = _portalController.GetPortal(portalGroup.MasterPortalId); + if (portal != null) + { + portal.PortalGroupID = portalGroup.PortalGroupId; + _portalController.UpdatePortalInfo(portal); + } + + ClearCache(); + + return portalGroup.PortalGroupId; + } + + public void DeletePortalGroup(PortalGroupInfo portalGroup) + { + //Argument Contract + Requires.NotNull("portalGroup", portalGroup); + Requires.PropertyNotNegative("portalGroup", "PortalGroupId", portalGroup.PortalGroupId); + + //Update portal + var portal = _portalController.GetPortal(portalGroup.MasterPortalId); + if (portal != null) + { + portal.PortalGroupID = -1; + _portalController.UpdatePortalInfo(portal); + } + + _dataService.DeletePortalGroup(portalGroup); + + ClearCache(); + } + + public IEnumerable GetPortalGroups() + { + return CBO.GetCachedObject>(new CacheItemArgs(DataCache.PortalGroupsCacheKey, + DataCache.PortalGroupsCacheTimeOut, + DataCache.PortalGroupsCachePriority), + GetPortalGroupsCallback); + } + + public IEnumerable GetPortalsByGroup(int portalGroupId) + { + var controller = new PortalController(); + var portals = controller.GetPortals(); + + return portals.Cast() + .Where(portal => portal.PortalGroupID == portalGroupId) + .ToList(); + } + + public void RemovePortalFromGroup(PortalInfo portal, PortalGroupInfo portalGroup, bool copyUsers, UserCopiedCallback callback) + { + //Argument Contract + Requires.NotNull("portal", portal); + Requires.PropertyNotNegative("portal", "PortalId", portal.PortalID); + Requires.NotNull("portalGroup", portalGroup); + Requires.PropertyNotNegative("portalGroup", "PortalGroupId", portalGroup.PortalGroupId); + Requires.PropertyNotNegative("portalGroup", "MasterPortalId", portalGroup.MasterPortalId); + + //Callback to update progress bar + var args = new UserCopiedEventArgs + { + TotalUsers = 0, + UserNo = 0, + UserName = "", + PortalName = portal.PortalName, + Stage = "startingremove" + }; + callback(args); + + //Remove portal from group + portal.PortalGroupID = -1; + _portalController.UpdatePortalInfo(portal); + + var userNo = 0; + if (copyUsers) + { + var users = UserController.GetUsers(portalGroup.MasterPortalId); + foreach (UserInfo masterUser in users) + { + userNo += 1; + + //Copy user to portal + UserController.CopyUserToPortal(masterUser, portal, false, false); + + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = users.Count, + UserNo = userNo, + UserName = masterUser.Username, + PortalName = portal.PortalName + }; + + callback(args); + } + } + else + { + //Get admin users + var roleController = new RoleController(); + var adminUsers = roleController.GetUsersByRoleName(Null.NullInteger, portal.AdministratorRoleName) + .Cast() + .Where(u => roleController.GetUserRole(portal.PortalID, u.UserID, portal.AdministratorRoleId) != null); + + foreach (var user in adminUsers) + { + //Copy Administrator to portal + UserController.CopyUserToPortal(user, portal, false, false); + + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = 1, + UserNo = ++userNo, + UserName = user.Username, + PortalName = portal.PortalName + }; + + callback(args); + } + } + //Callback to update progress bar + args = new UserCopiedEventArgs + { + TotalUsers = 1, + UserNo = userNo, + UserName = "", + PortalName = portal.PortalName, + Stage = "finishedremove", + PortalGroupId = portalGroup.PortalGroupId + }; + callback(args); + } + + public void UpdatePortalGroup(PortalGroupInfo portalGroup) + { + //Argument Contract + Requires.NotNull("portalGroup", portalGroup); + Requires.PropertyNotNegative("portalGroup", "PortalGroupId", portalGroup.PortalGroupId); + + _dataService.UpdatePortalGroup(portalGroup, UserController.GetCurrentUserInfo().UserID); + + ClearCache(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Portals/PortalGroupInfo.cs b/DNN Platform/Library/Entities/Portals/PortalGroupInfo.cs new file mode 100644 index 00000000000..baf834904ed --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalGroupInfo.cs @@ -0,0 +1,95 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel.DataAnnotations; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + [Serializable] + public class PortalGroupInfo : BaseEntityInfo, IHydratable + { + + public int PortalGroupId { get; set; } + + public string AuthenticationDomain { get; set; } + + public int MasterPortalId { get; set; } + + public string MasterPortalName + { + get + { + string portalName = String.Empty; + if (MasterPortalId > -1) + { + var portalController = new PortalController(); + var portal = portalController.GetPortal(MasterPortalId); + if (portal != null) + { + portalName = portal.PortalName; + } + } + return portalName; + } + } + + [Required()] + public string PortalGroupDescription { get; set; } + + [Required()] + public string PortalGroupName { get; set; } + + #region IHydratable Members + + public int KeyID + { + get + { + return PortalGroupId; + } + set + { + PortalGroupId = value; + } + } + + public void Fill(IDataReader dr) + { + FillInternal(dr); + + PortalGroupId = Null.SetNullInteger(dr["PortalGroupID"]); + PortalGroupName = Null.SetNullString(dr["PortalGroupName"]); + PortalGroupDescription = Null.SetNullString(dr["PortalGroupDescription"]); + MasterPortalId = Null.SetNullInteger(dr["MasterPortalID"]); + AuthenticationDomain = Null.SetNullString(dr["AuthenticationDomain"]); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalInfo.cs b/DNN Platform/Library/Entities/Portals/PortalInfo.cs new file mode 100644 index 00000000000..7f4091f3af8 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalInfo.cs @@ -0,0 +1,828 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + /// + /// PortalInfo provides a base class for Portal information + /// This class inherites from the BaseEntityInfo and is Hydratable + /// + /// + /// This example shows how the PortalInfo class is used to get physical file names + /// + /// Public ReadOnly Property PhysicalPath() As String + /// Get + /// Dim _PhysicalPath As String + /// Dim PortalSettings As PortalSettings = Nothing + /// If Not HttpContext.Current Is Nothing Then + /// PortalSettings = PortalController.GetCurrentPortalSettings() + /// End If + /// If PortalId = Null.NullInteger Then + /// _PhysicalPath = DotNetNuke.Common.Globals.HostMapPath + RelativePath + /// Else + /// If PortalSettings Is Nothing OrElse PortalSettings.PortalId <> PortalId Then + /// ' Get the PortalInfo based on the Portalid + /// Dim objPortals As New PortalController() + /// Dim objPortal As PortalInfo = objPortals.GetPortal(PortalId) + /// _PhysicalPath = objPortal.HomeDirectoryMapPath + RelativePath + /// Else + /// _PhysicalPath = PortalSettings.HomeDirectoryMapPath + RelativePath + /// End If + /// End If + /// Return _PhysicalPath.Replace("/", "\") + /// End Get + /// End Property + /// + /// + /// + [XmlRoot("settings", IsNullable = false)] + [Serializable] + public class PortalInfo : BaseEntityInfo, IHydratable + { + #region "Private Members" + + private string _administratorRoleName; + private int _pages = Null.NullInteger; + private string _registeredRoleName; + + #endregion + + #region Constructors + + /// + /// Create new Portalinfo instance + /// + /// + /// This example illustrates the creation of a new PortalInfo object + /// + /// For Each portal As PortalInfo In New PortalController().GetPortals + /// Dim portalID As Integer = portal.PortalID + /// ... + /// Next + /// + /// + /// + public PortalInfo() + { + Users = Null.NullInteger; + } + + #endregion + + #region Auto_Properties + + /// + /// UserID of the user who is the admininistrator of the portal + /// + /// UserId of the user who is the portal admin + /// UserId of the user who is the portal admin + /// This show the usage of the AdministratorId + /// + /// Dim Arr As ArrayList = objRoleController.GetUserRolesByRoleName(intPortalId, objPortal.AdministratorRoleName) + /// Dim i As Integer + /// For i = 0 To Arr.Count - 1 + /// Dim objUser As UserRoleInfo = CType(Arr(i), UserRoleInfo) + /// cboAdministratorId.Items.Add(New ListItem(objUser.FullName, objUser.UserID.ToString)) + /// Next + /// If Not cboAdministratorId.Items.FindByValue(objPortal.AdministratorId.ToString) Is Nothing Then + /// cboAdministratorId.Items.FindByValue(objPortal.AdministratorId.ToString).Selected = True + /// End If + /// + [XmlElement("administratorid")] + public int AdministratorId { get; set; } + + /// + /// The RoleId of the Security Role of the Administrators group of the portal + /// + /// RoleId of de Administrators Security Role + /// RoleId of de Administrators Security Role + /// This shows the usage of the AdministratoprRoleId + /// + /// Dim objPortal As PortalInfo = New PortalController().GetPortal(PortalID) + /// If RoleID = objPortal.AdministratorRoleId Then + /// _RoleType = Roles.RoleType.Administrator + /// ElseIf RoleID = objPortal.RegisteredRoleId Then + /// _RoleType = Roles.RoleType.RegisteredUser + /// ElseIf RoleName = "Subscribers" Then + /// _RoleType = Roles.RoleType.Subscriber + /// End If + /// + /// + /// + [XmlElement("administratorroleid")] + public int AdministratorRoleId { get; set; } + + /// + /// TabId at which admin tasks start + /// + /// TabID of admin tasks + /// TabID of admin tasks + /// + [XmlElement("admintabid")] + public int AdminTabId { get; set; } + + /// + /// Image (bitmap) file that is used as background for the portal + /// + /// Name of the file that is used as background + /// Name of the file that is used as background + /// + [XmlElement("backgroundfile")] + public string BackgroundFile { get; set; } + + /// + /// Setting for the type of banner advertising in the portal + /// + /// Type of banner advertising + /// Type of banner advertising + /// This show the usage of BannerAdvertising setting + /// + /// optBanners.SelectedIndex = objPortal.BannerAdvertising + /// + [XmlElement("banneradvertising")] + public int BannerAdvertising { get; set; } + + [XmlElement("cultureCode")] + public string CultureCode { get; set; } + + /// + /// Curreny format that is used in the portal + /// + /// Currency of the portal + /// Currency of the portal + /// This exampels show the usage of the Currentcy property + /// + /// cboCurrency.DataSource = colList + /// cboCurrency.DataBind() + /// If Null.IsNull(objPortal.Currency) Or cboCurrency.Items.FindByValue(objPortal.Currency) Is Nothing Then + /// cboCurrency.Items.FindByValue("USD").Selected = True + /// Else + /// cboCurrency.Items.FindByValue(objPortal.Currency).Selected = True + /// End If + /// + [XmlElement("currency")] + public string Currency { get; set; } + + /// + /// Default language for the portal + /// + /// Default language of the portal + /// Default language of the portal + /// + [XmlElement("defaultlanguage")] + public string DefaultLanguage { get; set; } + + /// + /// Description of the portal + /// + /// Description of the portal + /// Description of the portal + /// This show the usage of the Description property + /// + /// Dim objPortalController As New PortalController + /// Dim objPortal As PortalInfo = objPortalController.GetPortal(PortalID) + /// txtPortalName.Text = objPortal.PortalName + /// txtDescription.Text = objPortal.Description + /// txtKeyWords.Text = objPortal.KeyWords + /// + [XmlElement("description")] + public string Description { get; set; } + + /// + /// The default e-mail to be used in the porta; + /// + /// E-mail of the portal + /// E-mail of the portal + /// + [XmlElement("email")] + public string Email { get; set; } + + /// + /// Date at which the portal expires + /// + /// Date of expiration of the portal + /// Date of expiration of the portal + /// This show the Portal expiration date usage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("expirydate")] + public DateTime ExpiryDate { get; set; } + + /// + /// The footer text as specified in the Portal settings + /// + /// Footer text of the portal + /// Returns the the footer text of the portal + /// + /// This show the usage of the FooterText property + /// + /// txtFooterText.Text = objPortal.FooterText + /// + /// + /// + [XmlElement("footertext")] + public string FooterText { get; set; } + + /// + /// GUID of the portal info object + /// + /// Portal info Object GUID + /// GUD of the portal info object + /// + [XmlIgnore] + public Guid GUID { get; set; } + + /// + /// Home directory of the portal (logical path) + /// + /// Portal home directory + /// Portal home directory + /// + [XmlElement("homedirectory")] + public string HomeDirectory { get; set; } + + /// + /// TabdId of the Home page + /// + /// TabId of the Home page + /// TabId of the Home page + /// + [XmlElement("hometabid")] + public int HomeTabId { get; set; } + + /// + /// Amount of currency that is used as a hosting fee of the portal + /// + /// Currency amount hosting fee + /// Currency amount hosting fee + /// This show the Portal HostFeeusage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("hostfee")] + public float HostFee { get; set; } + + /// + /// Total disk space allowed for the portal (Mb). 0 means not limited + /// + /// Diskspace allowed for the portal + /// Diskspace allowed for the portal + /// This show the Portal HostSpaceusage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("hostspace")] + public int HostSpace { get; set; } + + /// + /// Keywords (separated by ,) for this portal + /// + /// Keywords seperated by , + /// Keywords for this portal + /// This show the usage of the KeyWords property + /// + /// Dim objPortalController As New PortalController + /// Dim objPortal As PortalInfo = objPortalController.GetPortal(PortalID) + /// txtPortalName.Text = objPortal.PortalName + /// txtDescription.Text = objPortal.Description + /// txtKeyWords.Text = objPortal.KeyWords + /// + [XmlElement("keywords")] + public string KeyWords { get; set; } + + /// + /// TabId with the login control, page to login + /// + /// TabId of the Login page + /// TabId of the Login page + /// + [XmlElement("logintabid")] + public int LoginTabId { get; set; } + + /// + /// The portal has a logo (bitmap) associated with the portal. Teh admin can set the logo in the portal settings + /// + /// URL of the logo + /// URL of the Portal logo + /// + /// urlLogo.Url = objPortal.LogoFile + /// urlLogo.FileFilter = glbImageFileTypes + /// + [XmlElement("logofile")] + public string LogoFile { get; set; } + + /// + /// Number of portal pages allowed in the portal. 0 means not limited + /// + /// Number of portal pages allowed + /// Number of portal pages allowed + /// This show the Portal PageQuotausage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("pagequota")] + public int PageQuota { get; set; } + + /// + /// Name of the Payment processor that is used for portal payments, e.g. PayPal + /// + /// Name of the portal payment processor + /// Name of the portal payment processor + /// + [XmlElement("paymentprocessor")] + public string PaymentProcessor { get; set; } + + /// + /// Unique idenitifier of the Portal within the site + /// + /// Portal identifier + /// Portal Identifier + /// + [XmlElement("portalid")] + public int PortalID { get; set; } + + /// + /// Contains the id of the portal group that the portal belongs to + /// Will be null or -1 (null.nullinteger) if the portal does not belong to a portal group + /// + /// Portal Group identifier + /// Portal Group Identifier + /// + public int PortalGroupID { get; set; } + + /// + /// Name of the portal. Can be set at creation time, Admin can change the name in the portal settings + /// + /// Name of the portal + /// Name of the portal + /// This show the usage of the PortalName property + /// + /// Dim objPortalController As New PortalController + /// Dim objPortal As PortalInfo = objPortalController.GetPortal(PortalID) + /// txtPortalName.Text = objPortal.PortalName + /// txtDescription.Text = objPortal.Description + /// txtKeyWords.Text = objPortal.KeyWords + /// + [XmlElement("portalname")] + public string PortalName { get; set; } + + /// + /// Password to use in the payment processor + /// + /// Payment Processor password + /// + /// This shows the usage of the payment processing + /// + /// If objPortal.PaymentProcessor <> "" Then + /// If Not cboProcessor.Items.FindByText(objPortal.PaymentProcessor) Is Nothing Then + /// cboProcessor.Items.FindByText(objPortal.PaymentProcessor).Selected = True + /// Else ' default + /// If Not cboProcessor.Items.FindByText("PayPal") Is Nothing Then + /// cboProcessor.Items.FindByText("PayPal").Selected = True + /// End If + /// End If + /// Else + /// cboProcessor.Items.FindByValue("").Selected = True + /// End If + /// txtUserId.Text = objPortal.ProcessorUserId + /// txtPassword.Attributes.Add("value", objPortal.ProcessorPassword) + /// + [XmlElement("processorpassword")] + public string ProcessorPassword { get; set; } + + /// + /// Payment Processor userId + /// + /// + /// + /// + /// This shows the usage of the payment processing + /// + /// If objPortal.PaymentProcessor <> "" Then + /// If Not cboProcessor.Items.FindByText(objPortal.PaymentProcessor) Is Nothing Then + /// cboProcessor.Items.FindByText(objPortal.PaymentProcessor).Selected = True + /// Else ' default + /// If Not cboProcessor.Items.FindByText("PayPal") Is Nothing Then + /// cboProcessor.Items.FindByText("PayPal").Selected = True + /// End If + /// End If + /// Else + /// cboProcessor.Items.FindByValue("").Selected = True + /// End If + /// txtUserId.Text = objPortal.ProcessorUserId + /// txtPassword.Attributes.Add("value", objPortal.ProcessorPassword) + /// + [XmlElement("processoruserid")] + public string ProcessorUserId { get; set; } + + /// + /// The RoleId of the Registered users group of the portal. + /// + /// RoleId of the Registered users + /// RoleId of the Registered users + /// + [XmlElement("registeredroleid")] + public int RegisteredRoleId { get; set; } + + /// + /// Tabid of the Registration page + /// + /// TabId of the Registration page + /// TabId of the Registration page + /// + /// + [XmlElement("registertabid")] + public int RegisterTabId { get; set; } + + /// + /// Tabid of the Search profile page + /// + /// TabdId of the Search Results page + /// TabdId of the Search Results page + /// + /// + [XmlElement("searchtabid")] + public int SearchTabId { get; set; } + + /// + /// # of days that Site log history should be kept. 0 means unlimited + /// + /// # of days sitelog history + /// # of days sitelog history + /// This show the Portal SiteLogHistoryusage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("siteloghistory")] + public int SiteLogHistory { get; set; } + + /// + /// TabdId of the splash page. If 0, there is no splash page + /// + /// TabdId of the Splash page + /// TabdId of the Splash page + /// + [XmlElement("splashtabid")] + public int SplashTabId { get; set; } + + /// + /// TabId at which Host tasks start + /// + /// TabId of Host tasks + /// TabId of Host tasks + /// + [XmlElement("supertabid")] + public int SuperTabId { get; set; } + + /// + /// Number of registered users allowed in the portal. 0 means not limited + /// + /// Number of registered users allowed + /// Number of registered users allowed + /// This show the Portal userQuota usage + /// + /// If Not Null.IsNull(objPortal.ExpiryDate) Then + /// txtExpiryDate.Text = objPortal.ExpiryDate.ToShortDateString + /// End If + /// txtHostFee.Text = objPortal.HostFee.ToString + /// txtHostSpace.Text = objPortal.HostSpace.ToString + /// txtPageQuota.Text = objPortal.PageQuota.ToString + /// txtUserQuota.Text = objPortal.UserQuota.ToString + /// If Not IsDBNull(objPortal.SiteLogHistory) Then + /// txtSiteLogHistory.Text = objPortal.SiteLogHistory.ToString + /// End If + /// + [XmlElement("userquota")] + public int UserQuota { get; set; } + + /// + /// Type of registration that the portal supports + /// + /// Type of registration + /// Type of registration + /// Registration type + /// + /// optUserRegistration.SelectedIndex = objPortal.UserRegistration + /// + [XmlElement("userregistration")] + public int UserRegistration { get; set; } + + /// + /// Tabid of the User profile page + /// + /// TabdId of the User profile page + /// TabdId of the User profile page + /// + [XmlElement("usertabid")] + public int UserTabId { get; set; } + + private int _users; + + /// + /// Actual number of actual users for this portal + /// + /// Number of users for the portal + /// Number of users for the portal + /// + [XmlElement("users")] + public int Users + { + get + { + if (_users < 0) + { + _users = UserController.GetUserCountByPortal(PortalID); + } + return _users; + } + set { _users = value; } + } + + /// + /// DNN Version # of the portal installation + /// + /// Version # of the portal installation + /// Version # of the portal installation + /// + [XmlElement("version")] + public string Version { get; set; } + + #endregion + + #region Properties + + /// + /// The actual name of the Administrators group of the portal. + /// This name is retrieved from the RoleController object + /// + /// The name of the Administrators group + /// The name of the Administrators group + /// + [XmlElement("administratorrolename")] + public string AdministratorRoleName + { + get + { + if (_administratorRoleName == Null.NullString && AdministratorRoleId > Null.NullInteger) + { + //Get Role Name + RoleInfo adminRole = TestableRoleController.Instance.GetRole(PortalID, r => r.RoleID == AdministratorRoleId); + if (adminRole != null) + { + _administratorRoleName = adminRole.RoleName; + } + } + return _administratorRoleName; + } + set + { + _administratorRoleName = value; + } + } + + /// + /// Fysical path on disk of the home directory of the portal + /// + /// + /// Fully qualified path of the home directory + /// + [XmlIgnore] + public string HomeDirectoryMapPath + { + get + { + return String.Format("{0}\\{1}\\", Globals.ApplicationMapPath, HomeDirectory.Replace("/", "\\")); + } + } + + /// + /// Actual number of pages of the portal + /// + /// Number of pages of the portal + /// Number of pages of the portal + /// + [XmlElement("pages")] + public int Pages + { + get + { + if (_pages < 0) + { + var objTabController = new TabController(); + _pages = objTabController.GetTabCount(PortalID); + } + return _pages; + } + set + { + _pages = value; + } + } + + /// + /// The actual name of the Registerd Users group of the portal. + /// This name is retrieved from the RoleController object + /// + /// The name of the Registerd Users group + /// The name of the Registerd Users group + /// + [XmlElement("registeredrolename")] + public string RegisteredRoleName + { + get + { + if (_registeredRoleName == Null.NullString && RegisteredRoleId > Null.NullInteger) + { + //Get Role Name + RoleInfo regUsersRole = TestableRoleController.Instance.GetRole(PortalID, r => r.RoleID == RegisteredRoleId); + if (regUsersRole != null) + { + _registeredRoleName = regUsersRole.RoleName; + } + } + return _registeredRoleName; + } + set + { + _registeredRoleName = value; + } + } + + #endregion + + [XmlIgnore, Obsolete("Deprecated in DNN 6.0.")] + public int TimeZoneOffset { get; set; } + + #region IHydratable Members + + /// + /// Fills a PortalInfo from a Data Reader + /// + /// The Data Reader to use + /// Standard IHydratable.Fill implementation + /// + public void Fill(IDataReader dr) + { + PortalID = Null.SetNullInteger(dr["PortalID"]); + + try + { + PortalGroupID = Null.SetNullInteger(dr["PortalGroupID"]); + } + catch (IndexOutOfRangeException) + { + if(Globals.Status == Globals.UpgradeStatus.None) + { + //this should not happen outside of an upgrade situation + throw; + } + + //else swallow the error + } + + PortalName = Null.SetNullString(dr["PortalName"]); + LogoFile = Null.SetNullString(dr["LogoFile"]); + FooterText = Null.SetNullString(dr["FooterText"]); + ExpiryDate = Null.SetNullDateTime(dr["ExpiryDate"]); + UserRegistration = Null.SetNullInteger(dr["UserRegistration"]); + BannerAdvertising = Null.SetNullInteger(dr["BannerAdvertising"]); + AdministratorId = Null.SetNullInteger(dr["AdministratorID"]); + Email = Null.SetNullString(dr["Email"]); + Currency = Null.SetNullString(dr["Currency"]); + HostFee = Null.SetNullInteger(dr["HostFee"]); + HostSpace = Null.SetNullInteger(dr["HostSpace"]); + PageQuota = Null.SetNullInteger(dr["PageQuota"]); + UserQuota = Null.SetNullInteger(dr["UserQuota"]); + AdministratorRoleId = Null.SetNullInteger(dr["AdministratorRoleID"]); + RegisteredRoleId = Null.SetNullInteger(dr["RegisteredRoleID"]); + Description = Null.SetNullString(dr["Description"]); + KeyWords = Null.SetNullString(dr["KeyWords"]); + BackgroundFile = Null.SetNullString(dr["BackGroundFile"]); + GUID = new Guid(Null.SetNullString(dr["GUID"])); + PaymentProcessor = Null.SetNullString(dr["PaymentProcessor"]); + ProcessorUserId = Null.SetNullString(dr["ProcessorUserId"]); + ProcessorPassword = Null.SetNullString(dr["ProcessorPassword"]); + SiteLogHistory = Null.SetNullInteger(dr["SiteLogHistory"]); + SplashTabId = Null.SetNullInteger(dr["SplashTabID"]); + HomeTabId = Null.SetNullInteger(dr["HomeTabID"]); + LoginTabId = Null.SetNullInteger(dr["LoginTabID"]); + RegisterTabId = Null.SetNullInteger(dr["RegisterTabID"]); + UserTabId = Null.SetNullInteger(dr["UserTabID"]); + SearchTabId = Null.SetNullInteger(dr["SearchTabID"]); + DefaultLanguage = Null.SetNullString(dr["DefaultLanguage"]); +#pragma warning disable 612,618 //needed for upgrades and backwards compatibility + TimeZoneOffset = Null.SetNullInteger(dr["TimeZoneOffset"]); +#pragma warning restore 612,618 + AdminTabId = Null.SetNullInteger(dr["AdminTabID"]); + HomeDirectory = Null.SetNullString(dr["HomeDirectory"]); + SuperTabId = Null.SetNullInteger(dr["SuperTabId"]); + CultureCode = Null.SetNullString(dr["CultureCode"]); + + FillInternal(dr); + AdministratorRoleName = Null.NullString; + RegisteredRoleName = Null.NullString; + + Users = Null.NullInteger; + Pages = Null.NullInteger; + } + + /// + /// Gets and sets the Key ID + /// + /// KeyId of the IHydratable.Key + /// + public int KeyID + { + get + { + return PortalID; + } + set + { + PortalID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Portals/PortalSettings.cs b/DNN Platform/Library/Entities/Portals/PortalSettings.cs new file mode 100644 index 00000000000..5a828a10ea7 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalSettings.cs @@ -0,0 +1,1517 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Web; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Personalization; +using DotNetNuke.Services.Tokens; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + /// ----------------------------------------------------------------------------- + /// + /// PortalSettings Class + /// + /// This class encapsulates all of the settings for the Portal, as well + /// as the configuration settings required to execute the current tab + /// view within the portal. + /// + /// + /// + /// + /// [cnurse] 10/21/2004 documented + /// [cnurse] 10/21/2004 added GetTabModuleSettings + /// + /// ----------------------------------------------------------------------------- + public class PortalSettings : BaseEntityInfo, IPropertyAccess + { + #region ControlPanelPermission enum + + public enum ControlPanelPermission + { + TabEditor, + ModuleEditor + } + + #endregion + + #region Mode enum + + public enum Mode + { + View, + Edit, + Layout + } + + #endregion + + #region PortalAliasMapping enum + + public enum PortalAliasMapping + { + None, + CanonicalUrl, + Redirect + } + + #endregion + + private string _version; + + #region Constructors + + public PortalSettings() + { + } + + public PortalSettings(int portalID) + : this(Null.NullInteger, portalID) + { + } + + public PortalSettings(int tabID, int portalID) + { + var controller = new PortalController(); + var portal = controller.GetPortal(portalID); + GetPortalSettings(tabID, portal); + } + + /// ----------------------------------------------------------------------------- + /// + /// The PortalSettings Constructor encapsulates all of the logic + /// necessary to obtain configuration settings necessary to render + /// a Portal Tab view for a given request. + /// + /// + /// + /// The current tab + /// The current portal + /// + /// [cnurse] 10/21/2004 documented + /// + /// ----------------------------------------------------------------------------- + public PortalSettings(int tabID, PortalAliasInfo objPortalAliasInfo) + { + ActiveTab = new TabInfo(); + PortalId = objPortalAliasInfo.PortalID; + PortalAlias = objPortalAliasInfo; + var controller = new PortalController(); + var portal = controller.GetPortal(PortalId); + if (portal != null) + { + GetPortalSettings(tabID, portal); + } + } + + public PortalSettings(PortalInfo portal) + { + ActiveTab = new TabInfo(); + GetPortalSettings(Null.NullInteger, portal); + } + + public PortalSettings(int tabID, PortalInfo portal) + { + ActiveTab = new TabInfo(); + GetPortalSettings(tabID, portal); + } + + #endregion + + #region Auto-Properties + + public TabInfo ActiveTab { get; set; } + public int AdministratorId { get; set; } + public int AdministratorRoleId { get; set; } + public string AdministratorRoleName { get; set; } + public int AdminTabId { get; set; } + public string BackgroundFile { get; set; } + public int BannerAdvertising { get; set; } + public string CultureCode { get; set; } + public string Currency { get; set; } + public string DefaultLanguage { get; set; } + public string Description { get; set; } + public string Email { get; set; } + public DateTime ExpiryDate { get; set; } + public string FooterText { get; set; } + public Guid GUID { get; set; } + public string HomeDirectory { get; set; } + public int HomeTabId { get; set; } + public float HostFee { get; set; } + public int HostSpace { get; set; } + public string KeyWords { get; set; } + public int LoginTabId { get; set; } + public string LogoFile { get; set; } + public int PageQuota { get; set; } + public int Pages { get; set; } + public int PortalId { get; set; } + public PortalAliasInfo PortalAlias { get; set; } + public PortalAliasInfo PrimaryAlias { get; set; } + public string PortalName { get; set; } + public int RegisteredRoleId { get; set; } + public string RegisteredRoleName { get; set; } + public int RegisterTabId { get; set; } + public int SearchTabId { get; set; } + public int SiteLogHistory { get; set; } + public int SplashTabId { get; set; } + public int SuperTabId { get; set; } + public int UserQuota { get; set; } + public int UserRegistration { get; set; } + public int Users { get; set; } + public int UserTabId { get; set; } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Allows users to select their own UI culture. + /// When set to false (default) framework will allways same culture for both + /// CurrentCulture (content) and CurrentUICulture (interface) + /// + /// Defaults to False + /// + /// [vmasanas] 03/22/2012 Created + /// + /// ----------------------------------------------------------------------------- + public bool AllowUserUICulture + { + get + { + return PortalController.GetPortalSettingAsBoolean("AllowUserUICulture", PortalId, false); + } + } + + public int CdfVersion + { + get + { + return PortalController.GetPortalSettingAsInteger("CdfVersion", PortalId, Null.NullInteger); + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.fullyCacheable; + } + } + + public bool ContentLocalizationEnabled + { + get + { + return PortalController.GetPortalSettingAsBoolean("ContentLocalizationEnabled", PortalId, false); + } + } + + public ControlPanelPermission ControlPanelSecurity + { + get + { + ControlPanelPermission security = ControlPanelPermission.ModuleEditor; + string setting; + if (PortalController.GetPortalSettingsDictionary(PortalId).TryGetValue("ControlPanelSecurity", out setting)) + { + security = (setting.ToUpperInvariant() == "TAB") ? ControlPanelPermission.TabEditor : ControlPanelPermission.ModuleEditor; + } + return security; + } + } + + public bool ControlPanelVisible + { + get + { + var setting = Convert.ToString(Personalization.GetProfile("Usability", "ControlPanelVisible" + PortalId)); + return String.IsNullOrEmpty(setting) ? DefaultControlPanelVisibility : Convert.ToBoolean(setting); + } + } + + public static PortalSettings Current + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + public string DefaultAdminContainer + { + get + { + return PortalController.GetPortalSetting("DefaultAdminContainer", PortalId, Host.Host.DefaultAdminContainer); + } + } + + public string DefaultAdminSkin + { + get + { + return PortalController.GetPortalSetting("DefaultAdminSkin", PortalId, Host.Host.DefaultAdminSkin); + } + } + + public Mode DefaultControlPanelMode + { + get + { + var mode = Mode.View; + string setting; + if (PortalController.GetPortalSettingsDictionary(PortalId).TryGetValue("ControlPanelMode", out setting)) + { + if (setting.ToUpperInvariant() == "EDIT") + { + mode = Mode.Edit; + } + } + return mode; + } + } + + public bool DefaultControlPanelVisibility + { + get + { + bool isVisible = true; + string setting; + if (PortalController.GetPortalSettingsDictionary(PortalId).TryGetValue("ControlPanelVisibility", out setting)) + { + isVisible = setting.ToUpperInvariant() != "MIN"; + } + return isVisible; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Module Id + /// + /// Defaults to Null.NullInteger + /// + /// [cnurse] 05/02/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int DefaultModuleId + { + get + { + return PortalController.GetPortalSettingAsInteger("defaultmoduleid", PortalId, Null.NullInteger); + } + } + + public string DefaultPortalAlias + { + get + { + foreach (var alias in TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(PortalId).Where(alias => alias.IsPrimary)) + { + return alias.HTTPAlias; + } + return String.Empty; + } + } + + public string DefaultPortalContainer + { + get + { + return PortalController.GetPortalSetting("DefaultPortalContainer", PortalId, Host.Host.DefaultPortalContainer); + } + } + + public string DefaultPortalSkin + { + get + { + return PortalController.GetPortalSetting("DefaultPortalSkin", PortalId, Host.Host.DefaultPortalSkin); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Tab Id + /// + /// Defaults to Null.NullInteger + /// + /// [cnurse] 05/02/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int DefaultTabId + { + get + { + return PortalController.GetPortalSettingAsInteger("defaulttabid", PortalId, Null.NullInteger); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether Browser Language Detection is Enabled + /// + /// Defaults to True + /// + /// [cnurse] 02/19/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool EnableBrowserLanguage + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnableBrowserLanguage", PortalId, Host.Host.EnableBrowserLanguage); + } + } + + public bool EnableCompositeFiles + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnableCompositeFiles", PortalId, false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to use the popup. + /// + /// Defaults to True + /// ----------------------------------------------------------------------------- + public bool EnablePopUps + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnablePopups", PortalId, true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether hide the login link. + /// + /// Defaults to False. + /// ----------------------------------------------------------------------------- + public bool HideLoginControl + { + get + { + return PortalController.GetPortalSettingAsBoolean("HideLoginControl", PortalId, false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Skin Widgets are enabled/supported + /// + /// Defaults to True + /// + /// [cnurse] 07/03/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool EnableSkinWidgets + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnableSkinWidgets", PortalId, true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether enable url language. + /// + /// Defaults to True + /// ----------------------------------------------------------------------------- + public bool EnableUrlLanguage + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnableUrlLanguage", PortalId, Host.Host.EnableUrlLanguage); + } + } + + public int ErrorPage404 + { + get + { + return PortalController.GetPortalSettingAsInteger("AUM_ErrorPage404", PortalId, Null.NullInteger); + } + } + + public int ErrorPage500 + { + get + { + return PortalController.GetPortalSettingAsInteger("AUM_ErrorPage500", PortalId, Null.NullInteger); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether folders which are hidden or whose name begins with underscore + /// are included in folder synchronization. + /// + /// + /// Defaults to True + /// + /// + /// [cnurse] 08/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool HideFoldersEnabled + { + get + { + return PortalController.GetPortalSettingAsBoolean("HideFoldersEnabled", PortalId, true); + } + } + + public string HomeDirectoryMapPath { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Inline Editor is enabled + /// + /// Defaults to True + /// + /// [cnurse] 08/28/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool InlineEditorEnabled + { + get + { + return PortalController.GetPortalSettingAsBoolean("InlineEditorEnabled", PortalId, true); + } + } + + public PortalAliasMapping PortalAliasMappingMode + { + get + { + return GetPortalAliasMappingMode(PortalId); + } + } + + public static PortalAliasMapping GetPortalAliasMappingMode(int portalId) + { + PortalAliasMapping aliasMapping = PortalAliasMapping.None; + string setting; + if (PortalController.GetPortalSettingsDictionary(portalId).TryGetValue("PortalAliasMapping", out setting)) + { + switch (setting.ToUpperInvariant()) + { + case "CANONICALURL": + aliasMapping = PortalAliasMapping.CanonicalUrl; + break; + case "REDIRECT": + aliasMapping = PortalAliasMapping.Redirect; + break; + default: + aliasMapping = PortalAliasMapping.None; + break; + } + } + return aliasMapping; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Common Words in the Search Index + /// + /// Defaults to False + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool SearchIncludeCommon + { + get + { + return PortalController.GetPortalSettingAsBoolean("SearchIncludeCommon", PortalId, Host.Host.SearchIncludeNumeric); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Numbers in the Search Index + /// + /// Defaults to False + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool SearchIncludeNumeric + { + get + { + return PortalController.GetPortalSettingAsBoolean("SearchIncludeNumeric", PortalId, Host.Host.SearchIncludeNumeric); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the filter used for inclusion of tag info + /// + /// + /// Defaults to "" + /// + /// + /// [vnguyen] 09/03/2010 Created + /// + /// ----------------------------------------------------------------------------- + public string SearchIncludedTagInfoFilter + { + get + { + return PortalController.GetPortalSetting("SearchIncludedTagInfoFilter", PortalId, Host.Host.SearchIncludedTagInfoFilter); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the maximum Search Word length to index + /// + /// Defaults to 3 + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int SearchMaxWordlLength + { + get + { + return PortalController.GetPortalSettingAsInteger("MaxSearchWordLength", PortalId, Host.Host.SearchMaxWordlLength); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the minum Search Word length to index + /// + /// Defaults to 3 + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int SearchMinWordlLength + { + get + { + return PortalController.GetPortalSettingAsInteger("MinSearchWordLength", PortalId, Host.Host.SearchMinWordlLength); + } + } + + public bool SSLEnabled + { + get + { + return PortalController.GetPortalSettingAsBoolean("SSLEnabled", PortalId, false); + } + } + + public bool SSLEnforced + { + get + { + return PortalController.GetPortalSettingAsBoolean("SSLEnforced", PortalId, false); + } + } + + public string SSLURL + { + get + { + return PortalController.GetPortalSetting("SSLURL", PortalId, Null.NullString); + } + } + + public string STDURL + { + get + { + return PortalController.GetPortalSetting("STDURL", PortalId, Null.NullString); + } + } + + public TimeZoneInfo TimeZone + { + get + { + //check if there is a PortalSetting + string timeZoneId = PortalController.GetPortalSetting("TimeZone", PortalId, string.Empty); + if (!string.IsNullOrEmpty(timeZoneId)) + { + var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); + if (timeZone != null) + return timeZone; + } + + return TimeZoneInfo.Local; + } + set + { + PortalController.UpdatePortalSetting(PortalId, "TimeZone", value.Id, true); + } + } + + public int UserId + { + get + { + if (HttpContext.Current.Request.IsAuthenticated) + { + return UserInfo.UserID; + } + return Null.NullInteger; + } + } + + public UserInfo UserInfo + { + get + { + return UserController.GetCurrentUserInfo(); + } + } + + public Mode UserMode + { + get + { + Mode mode; + if (HttpContext.Current != null && HttpContext.Current.Request.IsAuthenticated) + { + mode = DefaultControlPanelMode; + string setting = Convert.ToString(Personalization.GetProfile("Usability", "UserMode" + PortalId)); + switch (setting.ToUpper()) + { + case "VIEW": + mode = Mode.View; + break; + case "EDIT": + mode = Mode.Edit; + break; + case "LAYOUT": + mode = Mode.Layout; + break; + } + } + else + { + mode = Mode.View; + } + return mode; + } + } + + /// + /// Website Administrator whether receive the notification email when new user register. + /// + public bool EnableRegisterNotification + { + get + { + return PortalController.GetPortalSettingAsBoolean("EnableRegisterNotification", PortalId, true); + } + } + + #endregion + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound) + { + var outputFormat = string.Empty; + if (format == string.Empty) + { + outputFormat = "g"; + } + var lowerPropertyName = propertyName.ToLower(); + if (accessLevel == Scope.NoSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + propertyNotFound = true; + var result = string.Empty; + var isPublic = true; + switch (lowerPropertyName) + { + case "url": + propertyNotFound = false; + result = PropertyAccess.FormatString(PortalAlias.HTTPAlias, format); + break; + case "portalid": + propertyNotFound = false; + result = (PortalId.ToString(outputFormat, formatProvider)); + break; + case "portalname": + propertyNotFound = false; + result = PropertyAccess.FormatString(PortalName, format); + break; + case "homedirectory": + propertyNotFound = false; + result = PropertyAccess.FormatString(HomeDirectory, format); + break; + case "homedirectorymappath": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(HomeDirectoryMapPath, format); + break; + case "logofile": + propertyNotFound = false; + result = PropertyAccess.FormatString(LogoFile, format); + break; + case "footertext": + propertyNotFound = false; + var footerText = FooterText.Replace("[year]", DateTime.Now.Year.ToString()); + result = PropertyAccess.FormatString(footerText, format); + break; + case "expirydate": + isPublic = false; + propertyNotFound = false; + result = (ExpiryDate.ToString(outputFormat, formatProvider)); + break; + case "userregistration": + isPublic = false; + propertyNotFound = false; + result = (UserRegistration.ToString(outputFormat, formatProvider)); + break; + case "banneradvertising": + isPublic = false; + propertyNotFound = false; + result = (BannerAdvertising.ToString(outputFormat, formatProvider)); + break; + case "currency": + propertyNotFound = false; + result = PropertyAccess.FormatString(Currency, format); + break; + case "administratorid": + isPublic = false; + propertyNotFound = false; + result = (AdministratorId.ToString(outputFormat, formatProvider)); + break; + case "email": + propertyNotFound = false; + result = PropertyAccess.FormatString(Email, format); + break; + case "hostfee": + isPublic = false; + propertyNotFound = false; + result = (HostFee.ToString(outputFormat, formatProvider)); + break; + case "hostspace": + isPublic = false; + propertyNotFound = false; + result = (HostSpace.ToString(outputFormat, formatProvider)); + break; + case "pagequota": + isPublic = false; + propertyNotFound = false; + result = (PageQuota.ToString(outputFormat, formatProvider)); + break; + case "userquota": + isPublic = false; + propertyNotFound = false; + result = (UserQuota.ToString(outputFormat, formatProvider)); + break; + case "administratorroleid": + isPublic = false; + propertyNotFound = false; + result = (AdministratorRoleId.ToString(outputFormat, formatProvider)); + break; + case "administratorrolename": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(AdministratorRoleName, format); + break; + case "registeredroleid": + isPublic = false; + propertyNotFound = false; + result = (RegisteredRoleId.ToString(outputFormat, formatProvider)); + break; + case "registeredrolename": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(RegisteredRoleName, format); + break; + case "description": + propertyNotFound = false; + result = PropertyAccess.FormatString(Description, format); + break; + case "keywords": + propertyNotFound = false; + result = PropertyAccess.FormatString(KeyWords, format); + break; + case "backgroundfile": + propertyNotFound = false; + result = PropertyAccess.FormatString(BackgroundFile, format); + break; + case "siteloghistory": + isPublic = false; + propertyNotFound = false; + result = SiteLogHistory.ToString(outputFormat, formatProvider); + break; + case "admintabid": + isPublic = false; + propertyNotFound = false; + result = AdminTabId.ToString(outputFormat, formatProvider); + break; + case "supertabid": + isPublic = false; + propertyNotFound = false; + result = SuperTabId.ToString(outputFormat, formatProvider); + break; + case "splashtabid": + isPublic = false; + propertyNotFound = false; + result = SplashTabId.ToString(outputFormat, formatProvider); + break; + case "hometabid": + isPublic = false; + propertyNotFound = false; + result = HomeTabId.ToString(outputFormat, formatProvider); + break; + case "logintabid": + isPublic = false; + propertyNotFound = false; + result = LoginTabId.ToString(outputFormat, formatProvider); + break; + case "registertabid": + isPublic = false; + propertyNotFound = false; + result = RegisterTabId.ToString(outputFormat, formatProvider); + break; + case "usertabid": + isPublic = false; + propertyNotFound = false; + result = UserTabId.ToString(outputFormat, formatProvider); + break; + case "defaultlanguage": + propertyNotFound = false; + result = PropertyAccess.FormatString(DefaultLanguage, format); + break; + case "users": + isPublic = false; + propertyNotFound = false; + result = Users.ToString(outputFormat, formatProvider); + break; + case "pages": + isPublic = false; + propertyNotFound = false; + result = Pages.ToString(outputFormat, formatProvider); + break; + case "contentvisible": + isPublic = false; + break; + case "controlpanelvisible": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.Boolean2LocalizedYesNo(ControlPanelVisible, formatProvider); + break; + } + if (!isPublic && accessLevel != Scope.Debug) + { + propertyNotFound = true; + result = PropertyAccess.ContentLocked; + } + return result; + } + + #endregion + + #region Private Methods + + private void ConfigureActiveTab() + { + if (Globals.IsAdminSkin()) + { + ActiveTab.SkinSrc = DefaultAdminSkin; + } + else if (String.IsNullOrEmpty(ActiveTab.SkinSrc)) + { + ActiveTab.SkinSrc = DefaultPortalSkin; + } + ActiveTab.SkinSrc = SkinController.FormatSkinSrc(ActiveTab.SkinSrc, this); + ActiveTab.SkinPath = SkinController.FormatSkinPath(ActiveTab.SkinSrc); + + if (Globals.IsAdminSkin()) + { + ActiveTab.ContainerSrc = DefaultAdminContainer; + } + else if (String.IsNullOrEmpty(ActiveTab.ContainerSrc)) + { + ActiveTab.ContainerSrc = DefaultPortalContainer; + } + + ActiveTab.ContainerSrc = SkinController.FormatSkinSrc(ActiveTab.ContainerSrc, this); + ActiveTab.ContainerPath = SkinController.FormatSkinPath(ActiveTab.ContainerSrc); + + ActiveTab.Panes = new ArrayList(); + ActiveTab.Modules = new ArrayList(); + var crumbs = new ArrayList(); + GetBreadCrumbsRecursively(ref crumbs, ActiveTab.TabID); + ActiveTab.BreadCrumbs = crumbs; + } + + private void ConfigureModule(ModuleInfo cloneModule) + { + if (Null.IsNull(cloneModule.StartDate)) + { + cloneModule.StartDate = DateTime.MinValue; + } + if (Null.IsNull(cloneModule.EndDate)) + { + cloneModule.EndDate = DateTime.MaxValue; + } + if (String.IsNullOrEmpty(cloneModule.ContainerSrc)) + { + cloneModule.ContainerSrc = ActiveTab.ContainerSrc; + } + + cloneModule.ContainerSrc = SkinController.FormatSkinSrc(cloneModule.ContainerSrc, this); + cloneModule.ContainerPath = SkinController.FormatSkinPath(cloneModule.ContainerSrc); + } + + private void GetBreadCrumbsRecursively(ref ArrayList breadCrumbs, int tabId) + { + TabInfo tab; + var tabController = new TabController(); + var portalTabs = tabController.GetTabsByPortal(PortalId); + var hostTabs = tabController.GetTabsByPortal(Null.NullInteger); + bool tabFound = portalTabs.TryGetValue(tabId, out tab); + if (!tabFound) + { + tabFound = hostTabs.TryGetValue(tabId, out tab); + } + //if tab was found + if (tabFound) + { + //add tab to breadcrumb collection + breadCrumbs.Insert(0, tab.Clone()); + + //get the tab parent + if (!Null.IsNull(tab.ParentId) && tabId != tab.ParentId) + { + GetBreadCrumbsRecursively(ref breadCrumbs, tab.ParentId); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The GetPortalSettings method builds the site Settings + /// + /// + /// + /// The current tabs id + /// The Portal object + /// + /// + /// ----------------------------------------------------------------------------- + private void GetPortalSettings(int tabID, PortalInfo portal) + { + PortalId = portal.PortalID; + PortalName = portal.PortalName; + LogoFile = portal.LogoFile; + FooterText = portal.FooterText; + ExpiryDate = portal.ExpiryDate; + UserRegistration = portal.UserRegistration; + BannerAdvertising = portal.BannerAdvertising; + Currency = portal.Currency; + AdministratorId = portal.AdministratorId; + Email = portal.Email; + HostFee = portal.HostFee; + HostSpace = portal.HostSpace; + PageQuota = portal.PageQuota; + UserQuota = portal.UserQuota; + AdministratorRoleId = portal.AdministratorRoleId; + AdministratorRoleName = portal.AdministratorRoleName; + RegisteredRoleId = portal.RegisteredRoleId; + RegisteredRoleName = portal.RegisteredRoleName; + Description = portal.Description; + KeyWords = portal.KeyWords; + BackgroundFile = portal.BackgroundFile; + GUID = portal.GUID; + SiteLogHistory = portal.SiteLogHistory; + AdminTabId = portal.AdminTabId; + SuperTabId = portal.SuperTabId; + SplashTabId = portal.SplashTabId; + HomeTabId = portal.HomeTabId; + LoginTabId = portal.LoginTabId; + RegisterTabId = portal.RegisterTabId; + UserTabId = portal.UserTabId; + SearchTabId = portal.SearchTabId; + DefaultLanguage = portal.DefaultLanguage; + HomeDirectory = portal.HomeDirectory; + HomeDirectoryMapPath = portal.HomeDirectoryMapPath; + Pages = portal.Pages; + Users = portal.Users; + CultureCode = portal.CultureCode; + + //update properties with default values + if (Null.IsNull(HostSpace)) + { + HostSpace = 0; + } + if (Null.IsNull(DefaultLanguage)) + { + DefaultLanguage = Localization.SystemLocale; + } + HomeDirectory = Globals.ApplicationPath + "/" + portal.HomeDirectory + "/"; + + //verify tab for portal. This assigns the Active Tab based on the Tab Id/PortalId + if (VerifyPortalTab(PortalId, tabID)) + { + if (ActiveTab != null) + { + ConfigureActiveTab(); + } + } + if (ActiveTab != null) + { + var objPaneModules = new Dictionary(); + foreach (ModuleInfo cloneModule in ActiveTab.ChildModules.Select(kvp => kvp.Value.Clone())) + { + ConfigureModule(cloneModule); + + if (objPaneModules.ContainsKey(cloneModule.PaneName) == false) + { + objPaneModules.Add(cloneModule.PaneName, 0); + } + cloneModule.PaneModuleCount = 0; + if (!cloneModule.IsDeleted) + { + objPaneModules[cloneModule.PaneName] = objPaneModules[cloneModule.PaneName] + 1; + cloneModule.PaneModuleIndex = objPaneModules[cloneModule.PaneName] - 1; + } + + ActiveTab.Modules.Add(cloneModule); + } + foreach (ModuleInfo module in ActiveTab.Modules) + { + module.PaneModuleCount = objPaneModules[module.PaneName]; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The VerifyPortalTab method verifies that the TabId/PortalId combination + /// is allowed and returns default/home tab ids if not + /// + /// + /// + /// + /// The Portal's id + /// The current tab's id + /// + /// + /// ----------------------------------------------------------------------------- + private bool VerifyPortalTab(int portalId, int tabId) + { + var tabController = new TabController(); + var portalTabs = tabController.GetTabsByPortal(portalId); + var hostTabs = tabController.GetTabsByPortal(Null.NullInteger); + + //Check portal + bool isVerified = VerifyTabExists(tabId, portalTabs); + + if (!isVerified) + { + //check host + isVerified = VerifyTabExists(tabId, hostTabs); + } + + if (!isVerified) + { + //check splash tab + isVerified = VerifySpecialTab(portalId, SplashTabId); + } + + if (!isVerified) + { + //check home tab + isVerified = VerifySpecialTab(portalId, HomeTabId); + } + + if (!isVerified) + { + TabInfo tab = (from TabInfo t in portalTabs.AsList() where !t.IsDeleted && t.IsVisible select t).FirstOrDefault(); + + if (tab != null) + { + isVerified = true; + ActiveTab = tab.Clone(); + } + } + + if (ActiveTab != null) + { + if (Null.IsNull(ActiveTab.StartDate)) + { + ActiveTab.StartDate = DateTime.MinValue; + } + if (Null.IsNull(ActiveTab.EndDate)) + { + ActiveTab.EndDate = DateTime.MaxValue; + } + } + + return isVerified; + } + + private bool VerifySpecialTab(int portalId, int tabId) + { + var tabController = new TabController(); + TabInfo tab; + bool isVerified = false; + + if (tabId > 0) + { + tab = tabController.GetTab(tabId, portalId, false); + if (tab != null) + { + ActiveTab = tab.Clone(); + isVerified = true; + } + } + + return isVerified; + } + + private bool VerifyTabExists(int tabId, TabCollection tabs) + { + TabInfo tab; + bool isVerified = false; + + if (tabId != Null.NullInteger) + { + if (tabs.TryGetValue(tabId, out tab)) + { + if (!tab.IsDeleted) + { + ActiveTab = tab.Clone(); + isVerified = true; + } + } + } + return isVerified; + } + + #endregion + + #region Obsolete Methods + + private ArrayList _desktopTabs; + + [Obsolete("Deprecated in DNN 5.0. Replaced by DefaultAdminContainer")] + public SkinInfo AdminContainer { get; set; } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DefaultAdminSkin")] + public SkinInfo AdminSkin { get; set; } + + [Obsolete("Deprecated in DNN 5.0. Replaced by Host.GetHostSettingsDictionary")] + public Hashtable HostSettings + { + get + { + var h = new Hashtable(); + foreach (ConfigurationSetting kvp in HostController.Instance.GetSettings().Values) + { + h.Add(kvp.Key, kvp.Value); + } + return h; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by extended UserMode property.")] + public bool ContentVisible + { + get + { + return UserMode != Mode.Layout; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DefaultPortalContainer")] + public SkinInfo PortalContainer { get; set; } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DefaultPortalSkin")] + public SkinInfo PortalSkin { get; set; } + + [Obsolete("Deprecated in DNN 5.0. Tabs are cached independeently of Portal Settings, and this property is thus redundant")] + public ArrayList DesktopTabs + { + get + { + if (_desktopTabs == null) + { + _desktopTabs = new ArrayList(); + + //Add each portal Tab to DesktopTabs + TabInfo objPortalTab; + foreach (TabInfo objTab in TabController.GetTabsBySortOrder(PortalId, CultureCode, true)) + { + // clone the tab object ( to avoid creating an object reference to the data cache ) + objPortalTab = objTab.Clone(); + + // set custom properties + if (objPortalTab.TabOrder == 0) + { + objPortalTab.TabOrder = 999; + } + if (Null.IsNull(objPortalTab.StartDate)) + { + objPortalTab.StartDate = DateTime.MinValue; + } + if (Null.IsNull(objPortalTab.EndDate)) + { + objPortalTab.EndDate = DateTime.MaxValue; + } + + _desktopTabs.Add(objPortalTab); + } + + //Add each host Tab to DesktopTabs + TabInfo objHostTab; + foreach (TabInfo objTab in TabController.GetTabsBySortOrder(Null.NullInteger, Null.NullString, true)) + { + // clone the tab object ( to avoid creating an object reference to the data cache ) + objHostTab = objTab.Clone(); + objHostTab.PortalID = PortalId; + objHostTab.StartDate = DateTime.MinValue; + objHostTab.EndDate = DateTime.MaxValue; + + _desktopTabs.Add(objHostTab); + } + } + + return _desktopTabs; + } + } + + [Obsolete("Deprecated in DNN 5.1. Replaced by Application.Version")] + public string Version + { + get + { + if (string.IsNullOrEmpty(_version)) + { + _version = DotNetNukeContext.Current.Application.Version.ToString(3); + } + return _version; + } + set + { + _version = value; + } + } + + [Obsolete("Deprecated in DNN 6.0")] + public int TimeZoneOffset + { + get + { + return Convert.ToInt32(TimeZone.BaseUtcOffset.TotalMinutes); + } + set + { + TimeZone = Localization.ConvertLegacyTimeZoneOffsetToTimeZoneInfo(value); + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.ExecuteScript")] + public static string ExecuteScript(string strScript) + { + return DataProvider.Instance().ExecuteScript(strScript); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.ExecuteScript")] + public static string ExecuteScript(string strScript, bool useTransactions) + { + return DataProvider.Instance().ExecuteScript(strScript); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by Globals.FindDatabaseVersion")] + public static bool FindDatabaseVersion(int major, int minor, int build) + { + return Globals.FindDatabaseVersion(major, minor, build); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.GetDatabaseVersion")] + public static IDataReader GetDatabaseVersion() + { + return DataProvider.Instance().GetDatabaseVersion(); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by Host.GetHostSettingsDictionary")] + public static Hashtable GetHostSettings() + { + var h = new Hashtable(); + foreach (KeyValuePair kvp in HostController.Instance.GetSettingsDictionary()) + { + h.Add(kvp.Key, kvp.Value); + } + return h; + } + + [Obsolete("Deprecated in DNN 5.0. Please use ModuleController.GetModuleSettings(ModuleId)")] + public static Hashtable GetModuleSettings(int moduleId) + { + return new ModuleController().GetModuleSettings(moduleId); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalAliasController.GetPortalAliasInfo")] + public static PortalAliasInfo GetPortalAliasInfo(string portalAlias) + { + return PortalAliasController.GetPortalAliasInfo(portalAlias); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalAliasController.GetPortalAliasByPortal")] + public static string GetPortalByID(int portalId, string portalAlias) + { + return PortalAliasController.GetPortalAliasByPortal(portalId, portalAlias); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalAliasController.GetPortalAliasByTab")] + public static string GetPortalByTab(int tabID, string portalAlias) + { + return PortalAliasController.GetPortalAliasByTab(tabID, portalAlias); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalAliasController.GetPortalAliasLookup")] + public static PortalAliasCollection GetPortalAliasLookup() + { + var portalAliasCollection = new PortalAliasCollection(); + foreach (var kvp in TestablePortalAliasController.Instance.GetPortalAliases()) + { + portalAliasCollection.Add(kvp.Key, kvp.Value); + } + + return portalAliasCollection; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.GetProviderPath")] + public static string GetProviderPath() + { + return DataProvider.Instance().GetProviderPath(); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalController.GetPortalSettingsDictionary")] + public static Hashtable GetSiteSettings(int portalId) + { + var h = new Hashtable(); + foreach (KeyValuePair kvp in PortalController.GetPortalSettingsDictionary(portalId)) + { + h.Add(kvp.Key, kvp.Value); + } + return h; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalController.GetPortalSettingsDictionary(portalId).TryGetValue(settingName) or for the most part by proeprties of PortalSettings")] + public static string GetSiteSetting(int portalId, string settingName) + { + string setting; + PortalController.GetPortalSettingsDictionary(portalId).TryGetValue(settingName, out setting); + return setting; + } + + [Obsolete("Deprecated in DNN 5.0. Please use ModuleController.GetTabModuleSettings(TabModuleId)")] + public static Hashtable GetTabModuleSettings(int tabModuleId) + { + return new ModuleController().GetTabModuleSettings(tabModuleId); + } + + [Obsolete("Deprecated in DNN 5.0. Please use ModuleController.GetTabModuleSettings(ModuleId)")] + public static Hashtable GetTabModuleSettings(int tabModuleId, Hashtable moduleSettings) + { + Hashtable tabModuleSettings = new ModuleController().GetTabModuleSettings(tabModuleId); + + // add the TabModuleSettings to the ModuleSettings + foreach (string strKey in tabModuleSettings.Keys) + { + moduleSettings[strKey] = tabModuleSettings[strKey]; + } + + return moduleSettings; + } + + [Obsolete("Deprecated in DNN 5.0. Please use ModuleController.GetTabModuleSettings(ModuleId)")] + public static Hashtable GetTabModuleSettings(Hashtable moduleSettings, Hashtable tabModuleSettings) + { + // add the TabModuleSettings to the ModuleSettings + foreach (string strKey in tabModuleSettings.Keys) + { + moduleSettings[strKey] = tabModuleSettings[strKey]; + } + + //Return the modifed ModuleSettings + return moduleSettings; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.UpdateDatabaseVersion")] + public static void UpdateDatabaseVersion(int major, int minor, int build) + { + DataProvider.Instance().UpdateDatabaseVersion(major, minor, build, DotNetNukeContext.Current.Application.Name); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by DataProvider.UpdatePortalSetting(Integer, String, String)")] + public static void UpdatePortalSetting(int portalId, string settingName, string settingValue) + { + PortalController.UpdatePortalSetting(portalId, settingName, settingValue); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by PortalController.UpdatePortalSetting(Integer, String, String)")] + public static void UpdateSiteSetting(int portalId, string settingName, string settingValue) + { + PortalController.UpdatePortalSetting(portalId, settingName, settingValue); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Portals/PortalTemplateModuleAction.cs b/DNN Platform/Library/Entities/Portals/PortalTemplateModuleAction.cs new file mode 100644 index 00000000000..ad4fae30d15 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalTemplateModuleAction.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Portals +{ + public enum PortalTemplateModuleAction + { + Ignore, + Merge, + Replace + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/PortalTemplateValidator.cs b/DNN Platform/Library/Entities/Portals/PortalTemplateValidator.cs new file mode 100644 index 00000000000..33a0e6f5b0b --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/PortalTemplateValidator.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Common; + +#endregion + +namespace DotNetNuke.Entities.Portals +{ + /// ----------------------------------------------------------------------------- + /// + /// The PortalTemplateValidator Class is used to validate the Portal Template + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class PortalTemplateValidator : XmlValidatorBase + { + public bool Validate(string xmlFilename, string schemaFileName) + { + SchemaSet.Add("", schemaFileName); + return Validate(xmlFilename); + } + } +} diff --git a/DNN Platform/Library/Entities/Portals/TestablePortalSettings.cs b/DNN Platform/Library/Entities/Portals/TestablePortalSettings.cs new file mode 100644 index 00000000000..2254c0c1e4e --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/TestablePortalSettings.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Common; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; + + +namespace DotNetNuke.Entities.Portals.Internal +{ + public class TestablePortalSettings : ComponentBase, IPortalSettings + { + public string AdministratorRoleName + { + get { return PortalSettings.Current.AdministratorRoleName; } + } + } +} diff --git a/DNN Platform/Library/Entities/Portals/UserCopiedCallback.cs b/DNN Platform/Library/Entities/Portals/UserCopiedCallback.cs new file mode 100644 index 00000000000..80fabe22dbe --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/UserCopiedCallback.cs @@ -0,0 +1,24 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Portals +{ + public delegate void UserCopiedCallback(UserCopiedEventArgs e); +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Portals/UserCopiedEventArgs.cs b/DNN Platform/Library/Entities/Portals/UserCopiedEventArgs.cs new file mode 100644 index 00000000000..b2f30d9ad76 --- /dev/null +++ b/DNN Platform/Library/Entities/Portals/UserCopiedEventArgs.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Portals +{ + public class UserCopiedEventArgs + { + public bool Cancel { get; set; } + public string PortalName { get; set; } + public float TotalUsers { get; set; } + public string UserName { get; set; } + public float UserNo { get; set; } + public string Stage { get; set; } + public int PortalGroupId { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Profile/ProfileController.cs b/DNN Platform/Library/Entities/Profile/ProfileController.cs new file mode 100644 index 00000000000..e6eb06779c0 --- /dev/null +++ b/DNN Platform/Library/Entities/Profile/ProfileController.cs @@ -0,0 +1,639 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Web; + +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Profile; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem.Internal; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Profile +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Profile + /// Class: ProfileController + /// ----------------------------------------------------------------------------- + /// + /// The ProfileController class provides Business Layer methods for profiles and + /// for profile property Definitions + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class ProfileController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ProfileController)); + #region Private Members + + private static readonly DataProvider _dataProvider = DataProvider.Instance(); + private static readonly ProfileProvider _profileProvider = ProfileProvider.Instance(); + private static int _orderCounter; + + #endregion + + #region Private Methdods + + private static void AddDefaultDefinition(int portalId, string category, string name, string strType, int length, UserVisibilityMode defaultVisibility, Dictionary types) + { + _orderCounter += 2; + AddDefaultDefinition(portalId, category, name, strType, length, _orderCounter, defaultVisibility, types); + } + + internal static void AddDefaultDefinition(int portalId, string category, string name, string type, int length, int viewOrder, UserVisibilityMode defaultVisibility, + Dictionary types) + { + ListEntryInfo typeInfo = types["DataType:" + type] ?? types["DataType:Unknown"]; + var propertyDefinition = new ProfilePropertyDefinition(portalId) + { + DataType = typeInfo.EntryID, + DefaultValue = "", + ModuleDefId = Null.NullInteger, + PropertyCategory = category, + PropertyName = name, + Required = false, + ViewOrder = viewOrder, + Visible = true, + Length = length, + DefaultVisibility = defaultVisibility + }; + AddPropertyDefinition(propertyDefinition); + } + + private static ProfilePropertyDefinition FillPropertyDefinitionInfo(IDataReader dr) + { + ProfilePropertyDefinition definition = null; + try + { + definition = FillPropertyDefinitionInfo(dr, true); + } + catch (Exception ex) + { + Logger.Error(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return definition; + } + + private static ProfilePropertyDefinition FillPropertyDefinitionInfo(IDataReader dr, bool checkForOpenDataReader) + { + ProfilePropertyDefinition definition = null; + + //read datareader + bool canContinue = true; + if (checkForOpenDataReader) + { + canContinue = false; + if (dr.Read()) + { + canContinue = true; + } + } + if (canContinue) + { + int portalid = 0; + portalid = Convert.ToInt32(Null.SetNull(dr["PortalId"], portalid)); + definition = new ProfilePropertyDefinition(portalid); + definition.PropertyDefinitionId = Convert.ToInt32(Null.SetNull(dr["PropertyDefinitionId"], definition.PropertyDefinitionId)); + definition.ModuleDefId = Convert.ToInt32(Null.SetNull(dr["ModuleDefId"], definition.ModuleDefId)); + definition.DataType = Convert.ToInt32(Null.SetNull(dr["DataType"], definition.DataType)); + definition.DefaultValue = Convert.ToString(Null.SetNull(dr["DefaultValue"], definition.DefaultValue)); + definition.PropertyCategory = Convert.ToString(Null.SetNull(dr["PropertyCategory"], definition.PropertyCategory)); + definition.PropertyName = Convert.ToString(Null.SetNull(dr["PropertyName"], definition.PropertyName)); + definition.Length = Convert.ToInt32(Null.SetNull(dr["Length"], definition.Length)); + if (dr.GetSchemaTable().Select("ColumnName = 'ReadOnly'").Length > 0) + { + definition.ReadOnly = Convert.ToBoolean(Null.SetNull(dr["ReadOnly"], definition.ReadOnly)); + } + definition.Required = Convert.ToBoolean(Null.SetNull(dr["Required"], definition.Required)); + definition.ValidationExpression = Convert.ToString(Null.SetNull(dr["ValidationExpression"], definition.ValidationExpression)); + definition.ViewOrder = Convert.ToInt32(Null.SetNull(dr["ViewOrder"], definition.ViewOrder)); + definition.Visible = Convert.ToBoolean(Null.SetNull(dr["Visible"], definition.Visible)); + definition.DefaultVisibility = (UserVisibilityMode) Convert.ToInt32(Null.SetNull(dr["DefaultVisibility"], definition.DefaultVisibility)); + definition.ProfileVisibility = new ProfileVisibility + { + VisibilityMode = definition.DefaultVisibility + }; + definition.Deleted = Convert.ToBoolean(Null.SetNull(dr["Deleted"], definition.Deleted)); + } + return definition; + } + + private static List FillPropertyDefinitionInfoCollection(IDataReader dr) + { + var arr = new List(); + try + { + while (dr.Read()) + { + //fill business object + ProfilePropertyDefinition definition = FillPropertyDefinitionInfo(dr, false); + //add to collection + arr.Add(definition); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arr; + } + + private static int GetEffectivePortalId(int portalId) + { + return PortalController.GetEffectivePortalId(portalId); + } + + private static IEnumerable GetPropertyDefinitions(int portalId) + { + //Get the Cache Key + string key = string.Format(DataCache.ProfileDefinitionsCacheKey, portalId); + + //Try fetching the List from the Cache + var definitions = (List) DataCache.GetCache(key); + if (definitions == null) + { + //definitions caching settings + Int32 timeOut = DataCache.ProfileDefinitionsCacheTimeOut*Convert.ToInt32(Host.Host.PerformanceSetting); + + //Get the List from the database + definitions = FillPropertyDefinitionInfoCollection(_dataProvider.GetPropertyDefinitionsByPortal(portalId)); + + //Cache the List + if (timeOut > 0) + { + DataCache.SetCache(key, definitions, TimeSpan.FromMinutes(timeOut)); + } + } + return definitions; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Adds the default property definitions for a portal + /// + /// Id of the Portal + /// ----------------------------------------------------------------------------- + public static void AddDefaultDefinitions(int portalId) + { + portalId = GetEffectivePortalId(portalId); + + _orderCounter = 1; + var listController = new ListController(); + Dictionary dataTypes = listController.GetListEntryInfoDictionary("DataType"); + + AddDefaultDefinition(portalId, "Name", "Prefix", "Text", 50, UserVisibilityMode.AllUsers, dataTypes); + AddDefaultDefinition(portalId, "Name", "FirstName", "Text", 50, UserVisibilityMode.AllUsers, dataTypes); + AddDefaultDefinition(portalId, "Name", "MiddleName", "Text", 50, UserVisibilityMode.AllUsers, dataTypes); + AddDefaultDefinition(portalId, "Name", "LastName", "Text", 50, UserVisibilityMode.AllUsers, dataTypes); + AddDefaultDefinition(portalId, "Name", "Suffix", "Text", 50, UserVisibilityMode.AllUsers, dataTypes); + AddDefaultDefinition(portalId, "Address", "Unit", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Address", "Street", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Address", "City", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Address", "Region", "Region", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Address", "Country", "Country", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Address", "PostalCode", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Contact Info", "Telephone", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Contact Info", "Cell", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Contact Info", "Fax", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Contact Info", "Website", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Contact Info", "IM", "Text", 50, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Preferences", "Biography", "RichText", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Preferences", "TimeZone", "TimeZone", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Preferences", "PreferredTimeZone", "TimeZoneInfo", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Preferences", "PreferredLocale", "Locale", 0, UserVisibilityMode.AdminOnly, dataTypes); + AddDefaultDefinition(portalId, "Preferences", "Photo", "Image", 0, UserVisibilityMode.AllUsers, dataTypes); + + //6.0 requires the old TimeZone property to be marked as Deleted + ProfilePropertyDefinition pdf = GetPropertyDefinitionByName(portalId, "TimeZone"); + if(pdf != null) + { + DeletePropertyDefinition(pdf); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a Property Defintion to the Data Store + /// + /// An ProfilePropertyDefinition object + /// The Id of the definition (or if negative the errorcode of the error) + /// ----------------------------------------------------------------------------- + public static int AddPropertyDefinition(ProfilePropertyDefinition definition) + { + int portalId = GetEffectivePortalId(definition.PortalId); + if (definition.Required) + { + definition.Visible = true; + } + int intDefinition = _dataProvider.AddPropertyDefinition(portalId, + definition.ModuleDefId, + definition.DataType, + definition.DefaultValue, + definition.PropertyCategory, + definition.PropertyName, + definition.ReadOnly, + definition.Required, + definition.ValidationExpression, + definition.ViewOrder, + definition.Visible, + definition.Length, + (int) definition.DefaultVisibility, + UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(definition, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PROFILEPROPERTY_CREATED); + ClearProfileDefinitionCache(definition.PortalId); + return intDefinition; + } + + /// ----------------------------------------------------------------------------- + /// + /// Clears the Profile Definitions Cache + /// + /// Id of the Portal + /// ----------------------------------------------------------------------------- + public static void ClearProfileDefinitionCache(int portalId) + { + DataCache.ClearDefinitionsCache(GetEffectivePortalId(portalId)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a Property Defintion from the Data Store + /// + /// The ProfilePropertyDefinition object to delete + /// ----------------------------------------------------------------------------- + public static void DeletePropertyDefinition(ProfilePropertyDefinition definition) + { + _dataProvider.DeletePropertyDefinition(definition.PropertyDefinitionId); + var objEventLog = new EventLogController(); + objEventLog.AddLog(definition, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PROFILEPROPERTY_DELETED); + ClearProfileDefinitionCache(definition.PortalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Property Defintion from the Data Store by id + /// + /// The id of the ProfilePropertyDefinition object to retrieve + /// Portal Id. + /// The ProfilePropertyDefinition object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinition GetPropertyDefinition(int definitionId, int portalId) + { + bool bFound = Null.NullBoolean; + ProfilePropertyDefinition definition = null; + foreach (ProfilePropertyDefinition def in GetPropertyDefinitions(GetEffectivePortalId(portalId))) + { + if (def.PropertyDefinitionId == definitionId) + { + definition = def; + bFound = true; + break; + } + } + if (!bFound) + { + //Try Database + definition = FillPropertyDefinitionInfo(_dataProvider.GetPropertyDefinition(definitionId)); + } + return definition; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Property Defintion from the Data Store by name + /// + /// The id of the Portal + /// The name of the ProfilePropertyDefinition object to retrieve + /// The ProfilePropertyDefinition object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinition GetPropertyDefinitionByName(int portalId, string name) + { + portalId = GetEffectivePortalId(portalId); + + bool bFound = Null.NullBoolean; + ProfilePropertyDefinition definition = null; + foreach (ProfilePropertyDefinition def in GetPropertyDefinitions(portalId)) + { + if (def.PropertyName == name) + { + definition = def; + bFound = true; + break; + } + } + if (!bFound) + { + //Try Database + definition = FillPropertyDefinitionInfo(_dataProvider.GetPropertyDefinitionByName(portalId, name)); + } + return definition; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Property Defintions from the Data Store by category + /// + /// The id of the Portal + /// The category of the Property Defintions to retrieve + /// A ProfilePropertyDefinitionCollection object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinitionCollection GetPropertyDefinitionsByCategory(int portalId, string category) + { + portalId = GetEffectivePortalId(portalId); + + var definitions = new ProfilePropertyDefinitionCollection(); + foreach (ProfilePropertyDefinition definition in GetPropertyDefinitions(portalId)) + { + if (definition.PropertyCategory == category) + { + definitions.Add(definition); + } + } + return definitions; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Property Defintions from the Data Store by portal + /// + /// The id of the Portal + /// A ProfilePropertyDefinitionCollection object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinitionCollection GetPropertyDefinitionsByPortal(int portalId) + { + return GetPropertyDefinitionsByPortal(portalId, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Property Defintions from the Data Store by portal + /// + /// The id of the Portal + /// Whether to use a clone object. + /// A ProfilePropertyDefinitionCollection object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinitionCollection GetPropertyDefinitionsByPortal(int portalId, bool clone) + { + return GetPropertyDefinitionsByPortal(portalId, clone, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Property Defintions from the Data Store by portal + /// + /// The id of the Portal + /// Whether to use a clone object. + /// Whether to include deleted profile properties. + /// A ProfilePropertyDefinitionCollection object + /// ----------------------------------------------------------------------------- + public static ProfilePropertyDefinitionCollection GetPropertyDefinitionsByPortal(int portalId, bool clone, bool includeDeleted) + { + portalId = GetEffectivePortalId(portalId); + + var definitions = new ProfilePropertyDefinitionCollection(); + foreach (ProfilePropertyDefinition definition in GetPropertyDefinitions(portalId)) + { + if (!definition.Deleted || includeDeleted) + { + definitions.Add(clone ? definition.Clone() : definition); + } + } + return definitions; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Profile Information for the User + /// + /// + /// The user whose Profile information we are retrieving. + /// ----------------------------------------------------------------------------- + public static void GetUserProfile(ref UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + _profileProvider.GetUserProfile(ref user); + user.PortalID = portalId; + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Property Defintion in the Data Store + /// + /// The ProfilePropertyDefinition object to update + /// ----------------------------------------------------------------------------- + public static void UpdatePropertyDefinition(ProfilePropertyDefinition definition) + { + + if (definition.Required) + { + definition.Visible = true; + } + _dataProvider.UpdatePropertyDefinition(definition.PropertyDefinitionId, + definition.DataType, + definition.DefaultValue, + definition.PropertyCategory, + definition.PropertyName, + definition.ReadOnly, + definition.Required, + definition.ValidationExpression, + definition.ViewOrder, + definition.Visible, + definition.Length, + (int) definition.DefaultVisibility, + UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(definition, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PROFILEPROPERTY_UPDATED); + ClearProfileDefinitionCache(definition.PortalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a User's Profile + /// + /// The use to update + /// + /// + /// ----------------------------------------------------------------------------- + public static void UpdateUserProfile(UserInfo user) + { + int portalId = GetEffectivePortalId(user.PortalID); + user.PortalID = portalId; + + //Update the User Profile + if (user.Profile.IsDirty) + { + _profileProvider.UpdateUserProfile(user); + } + + //Remove the UserInfo from the Cache, as it has been modified + DataCache.ClearUserCache(user.PortalID, user.Username); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a User's Profile + /// + /// The use to update + /// The collection of profile properties + /// The updated User + /// ----------------------------------------------------------------------------- + public static UserInfo UpdateUserProfile(UserInfo user, ProfilePropertyDefinitionCollection profileProperties) + { + int portalId = GetEffectivePortalId(user.PortalID); + user.PortalID = portalId; + + bool updateUser = Null.NullBoolean; + var photoChanged = Null.NullBoolean; + //Iterate through the Definitions + if (profileProperties != null) + { + foreach (ProfilePropertyDefinition propertyDefinition in profileProperties) + { + string propertyName = propertyDefinition.PropertyName; + string propertyValue = propertyDefinition.PropertyValue; + if (propertyDefinition.IsDirty) + { + user.Profile.SetProfileProperty(propertyName, propertyValue); + if (propertyName.ToLower() == "firstname" || propertyName.ToLower() == "lastname") + { + updateUser = true; + } + else if (propertyName.ToLowerInvariant() == "photo") + { + photoChanged = true; + } + } + } + UpdateUserProfile(user); + + //if user's photo changed, then create different size thumbnails of profile pictures. + if (photoChanged) + { + try + { + if (!string.IsNullOrEmpty(user.Profile.Photo) && int.Parse(user.Profile.Photo) > 0) + { + CreateThumbnails(user.Profile.PhotoURL); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + + } + + if (updateUser) + { + UserController.UpdateUser(portalId, user); + } + } + return user; + } + + private static void CreateThumbnails(string imagePath) + { + if (!string.IsNullOrEmpty(imagePath)) + { + imagePath = HttpContext.Current.Server.MapPath(imagePath); + CreateThumbnail(imagePath, "l", 64, 64); + CreateThumbnail(imagePath, "s", 50, 50); + CreateThumbnail(imagePath, "xs", 32, 32); + } + } + + private static void CreateThumbnail(string imagePath, string type, int width, int height) + { + var extension = Path.GetExtension(imagePath); + var path = imagePath.Replace(extension, "_" + type + extension); + if (!FileWrapper.Instance.Exists(path)) + { + File.Copy(imagePath, path); + ImageUtils.CreateImage(path, height, width); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates the Profile properties for the User (determines if all required properties + /// have been set) + /// + /// The Id of the portal. + /// The profile. + /// ----------------------------------------------------------------------------- + public static bool ValidateProfile(int portalId, UserProfile objProfile) + { + bool isValid = true; + foreach (ProfilePropertyDefinition propertyDefinition in objProfile.ProfileProperties) + { + if (propertyDefinition.Required && string.IsNullOrEmpty(propertyDefinition.PropertyValue)) + { + isValid = false; + break; + } + } + return isValid; + } + + #endregion + + #region Obsolete Methods + + [Obsolete("This method has been deprecated. Please use GetPropertyDefinition(ByVal definitionId As Integer, ByVal portalId As Integer) instead")] + public static ProfilePropertyDefinition GetPropertyDefinition(int definitionId) + { + return (ProfilePropertyDefinition) CBO.FillObject(_dataProvider.GetPropertyDefinition(definitionId), typeof (ProfilePropertyDefinition)); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinition.cs b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinition.cs new file mode 100644 index 00000000000..01fe40eb217 --- /dev/null +++ b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinition.cs @@ -0,0 +1,601 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.ComponentModel; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.UI.WebControls; + +namespace DotNetNuke.Entities.Profile +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Profile + /// Class: ProfilePropertyDefinition + /// ----------------------------------------------------------------------------- + /// + /// The ProfilePropertyDefinition class provides a Business Layer entity for + /// property Definitions + /// + /// + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [XmlRoot("profiledefinition", IsNullable = false)] + [Serializable] + public class ProfilePropertyDefinition : BaseEntityInfo + { + #region Private Members + + private int _dataType = Null.NullInteger; + private string _defaultValue; + private UserVisibilityMode _defaultVisibility = UserVisibilityMode.AdminOnly; + private bool _deleted; + private int _length; + private int _moduleDefId = Null.NullInteger; + private int _portalId; + private ProfileVisibility _profileVisibility = new ProfileVisibility + { + VisibilityMode = UserVisibilityMode.AdminOnly + }; + private string _propertyCategory; + private string _propertyName; + private string _propertyValue; + private bool _readOnly; + private bool _required; + private string _ValidationExpression; + private int _viewOrder; + private bool _visible; + + #endregion + + #region Constructors + + public ProfilePropertyDefinition() + { + PropertyDefinitionId = Null.NullInteger; + //Get the default PortalSettings + PortalSettings _Settings = PortalController.GetCurrentPortalSettings(); + PortalId = _Settings.PortalId; + } + + public ProfilePropertyDefinition(int portalId) + { + PropertyDefinitionId = Null.NullInteger; + PortalId = portalId; + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Data Type of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Editor("DotNetNuke.UI.WebControls.DNNListEditControl, DotNetNuke", typeof (EditControl))] + [List("DataType", "", ListBoundField.Id, ListBoundField.Value)] + [IsReadOnly(true)] + [Required(true)] + [SortOrder(1)] + [XmlIgnore] + public int DataType + { + get + { + return _dataType; + } + set + { + if (_dataType != value) + { + IsDirty = true; + } + _dataType = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Default Value of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(4)] + [XmlIgnore] + public string DefaultValue + { + get + { + return _defaultValue; + } + set + { + if (_defaultValue != value) + { + IsDirty = true; + } + _defaultValue = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Default Visibility of the Profile Property + /// + /// + /// [sbwalker] 06/28/2010 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(10)] + [XmlIgnore] + public UserVisibilityMode DefaultVisibility + { + get + { + return _defaultVisibility; + } + set + { + if (_defaultVisibility != value) + { + IsDirty = true; + } + _defaultVisibility = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Deleted + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public bool Deleted + { + get + { + return _deleted; + } + set + { + _deleted = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Definition has been modified since it has been retrieved + /// + /// + /// [cnurse] 02/21/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public bool IsDirty { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Length of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(3)] + [XmlElement("length")] + public int Length + { + get + { + return _length; + } + set + { + if (_length != value) + { + IsDirty = true; + } + _length = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleDefId + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public int ModuleDefId + { + get + { + return _moduleDefId; + } + set + { + _moduleDefId = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the PortalId + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public int PortalId + { + get + { + return _portalId; + } + set + { + _portalId = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Category of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Required(true)] + [SortOrder(2)] + [XmlElement("propertycategory")] + public string PropertyCategory + { + get + { + return _propertyCategory; + } + set + { + if (_propertyCategory != value) + { + IsDirty = true; + } + _propertyCategory = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Id of the ProfilePropertyDefinition + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public int PropertyDefinitionId { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Name of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Required(true)] + [IsReadOnly(true)] + [SortOrder(0)] + [RegularExpressionValidator("^[a-zA-Z0-9._%\\-+']+$")] + [XmlElement("propertyname")] + public string PropertyName + { + get + { + return _propertyName; + } + set + { + if (_propertyName != value) + { + IsDirty = true; + } + _propertyName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Value of the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public string PropertyValue + { + get + { + return _propertyValue; + } + set + { + if (_propertyValue != value) + { + IsDirty = true; + } + _propertyValue = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the property is read only + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(7)] + [XmlIgnore] + public bool ReadOnly + { + get + { + return _readOnly; + } + set + { + if (_readOnly != value) + { + IsDirty = true; + } + _readOnly = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the property is required + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(6)] + [XmlIgnore] + public bool Required + { + get + { + return _required; + } + set + { + if (_required != value) + { + IsDirty = true; + } + _required = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a Validation Expression (RegEx) for the Profile Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(5)] + [XmlIgnore] + public string ValidationExpression + { + get + { + return _ValidationExpression; + } + set + { + if (_ValidationExpression != value) + { + IsDirty = true; + } + _ValidationExpression = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the View Order of the Property + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [IsReadOnly(true)] + [SortOrder(9)] + [XmlIgnore] + public int ViewOrder + { + get + { + return _viewOrder; + } + set + { + if (_viewOrder != value) + { + IsDirty = true; + } + _viewOrder = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the property is visible + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(8)] + [XmlIgnore] + public bool Visible + { + get + { + return _visible; + } + set + { + if (_visible != value) + { + IsDirty = true; + } + _visible = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the property is visible + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + [XmlIgnore] + public ProfileVisibility ProfileVisibility + { + get + { + return _profileVisibility; + } + set + { + if (_profileVisibility != value) + { + IsDirty = true; + } + _profileVisibility = value; + } + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Clears the IsDirty Flag + /// + /// + /// [cnurse] 02/23/2006 created + /// + /// ----------------------------------------------------------------------------- + public void ClearIsDirty() + { + IsDirty = false; + } + + /// + /// Clone a ProfilePropertyDefinition + /// + /// A ProfilePropertyDefinition + public ProfilePropertyDefinition Clone() + { + var clone = new ProfilePropertyDefinition(PortalId) + { + DataType = DataType, + DefaultValue = DefaultValue, + Length = Length, + ModuleDefId = ModuleDefId, + PropertyCategory = PropertyCategory, + PropertyDefinitionId = PropertyDefinitionId, + PropertyName = PropertyName, + PropertyValue = PropertyValue, + ReadOnly = ReadOnly, + Required = Required, + ValidationExpression = ValidationExpression, + ViewOrder = ViewOrder, + DefaultVisibility = DefaultVisibility, + ProfileVisibility = ProfileVisibility.Clone(), + Visible = Visible, + Deleted = Deleted + }; + clone.ClearIsDirty(); + return clone; + } + + #endregion + + #region Obsolete + + [Obsolete("Deprecated in 6.2 as profile visibility has been extended")] + [Browsable(false)] + [XmlIgnore] + public UserVisibilityMode Visibility + { + get + { + return ProfileVisibility.VisibilityMode; + } + set + { + if (ProfileVisibility.VisibilityMode != value) + { + IsDirty = true; + } + ProfileVisibility.VisibilityMode = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionCollection.cs b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionCollection.cs new file mode 100644 index 00000000000..b92e3c52a89 --- /dev/null +++ b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionCollection.cs @@ -0,0 +1,321 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Profile +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Profile + /// Class: ProfilePropertyDefinitionCollection + /// ----------------------------------------------------------------------------- + /// + /// The ProfilePropertyDefinitionCollection class provides Business Layer methods for + /// a collection of property Definitions + /// + /// + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ProfilePropertyDefinitionCollection : CollectionBase + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new default collection + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinitionCollection() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new Collection from an ArrayList of ProfilePropertyDefinition objects + /// + /// An ArrayList of ProfilePropertyDefinition objects + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinitionCollection(ArrayList definitionsList) + { + AddRange(definitionsList); + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new Collection from a ProfilePropertyDefinitionCollection + /// + /// A ProfilePropertyDefinitionCollection + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinitionCollection(ProfilePropertyDefinitionCollection collection) + { + AddRange(collection); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets an item in the collection. + /// + /// This overload returns the item by its index. + /// The index to get + /// A ProfilePropertyDefinition object + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinition this[int index] + { + get + { + return (ProfilePropertyDefinition) List[index]; + } + set + { + List[index] = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an item in the collection. + /// + /// This overload returns the item by its name + /// The name of the Property to get + /// A ProfilePropertyDefinition object + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinition this[string name] + { + get + { + return GetByName(name); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a property Definition to the collectio. + /// + /// A ProfilePropertyDefinition object + /// The index of the property Definition in the collection + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public int Add(ProfilePropertyDefinition value) + { + return List.Add(value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Add an ArrayList of ProfilePropertyDefinition objects + /// + /// An ArrayList of ProfilePropertyDefinition objects + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public void AddRange(ArrayList definitionsList) + { + foreach (ProfilePropertyDefinition objProfilePropertyDefinition in definitionsList) + { + Add(objProfilePropertyDefinition); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Add an existing ProfilePropertyDefinitionCollection + /// + /// A ProfilePropertyDefinitionCollection + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public void AddRange(ProfilePropertyDefinitionCollection collection) + { + foreach (ProfilePropertyDefinition objProfilePropertyDefinition in collection) + { + Add(objProfilePropertyDefinition); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Determines whether the collection contains a property definition + /// + /// A ProfilePropertyDefinition object + /// A Boolean True/False + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public bool Contains(ProfilePropertyDefinition value) + { + return List.Contains(value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a sub-collection of items in the collection by category. + /// + /// The category to get + /// A ProfilePropertyDefinitionCollection object + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinitionCollection GetByCategory(string category) + { + var collection = new ProfilePropertyDefinitionCollection(); + foreach (ProfilePropertyDefinition profileProperty in InnerList) + { + if (profileProperty.PropertyCategory == category) + { + collection.Add(profileProperty); + } + } + return collection; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an item in the collection by Id. + /// + /// The id of the Property to get + /// A ProfilePropertyDefinition object + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinition GetById(int id) + { + ProfilePropertyDefinition profileItem = null; + foreach (ProfilePropertyDefinition profileProperty in InnerList) + { + if (profileProperty.PropertyDefinitionId == id) + { + profileItem = profileProperty; + } + } + return profileItem; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an item in the collection by name. + /// + /// The name of the Property to get + /// A ProfilePropertyDefinition object + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinition GetByName(string name) + { + ProfilePropertyDefinition profileItem = null; + foreach (ProfilePropertyDefinition profileProperty in InnerList) + { + if (profileProperty.PropertyName == name) + { + //Found Profile property + profileItem = profileProperty; + } + } + return profileItem; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the index of a property Definition + /// + /// A ProfilePropertyDefinition object + /// The index of the property Definition in the collection + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public int IndexOf(ProfilePropertyDefinition value) + { + return List.IndexOf(value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Inserts a property Definition into the collectio. + /// + /// A ProfilePropertyDefinition object + /// The index to insert the item at + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public void Insert(int index, ProfilePropertyDefinition value) + { + List.Insert(index, value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Removes a property definition from the collection + /// + /// The ProfilePropertyDefinition object to remove + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public void Remove(ProfilePropertyDefinition value) + { + List.Remove(value); + } + + /// ----------------------------------------------------------------------------- + /// + /// Sorts the collection using the ProfilePropertyDefinitionComparer (ie by ViewOrder) + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public void Sort() + { + InnerList.Sort(new ProfilePropertyDefinitionComparer()); + } + } +} diff --git a/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionComparer.cs b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionComparer.cs new file mode 100644 index 00000000000..3a98f70dc4a --- /dev/null +++ b/DNN Platform/Library/Entities/Profile/ProfilePropertyDefinitionComparer.cs @@ -0,0 +1,66 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Profile +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Profile + /// Class: ProfilePropertyDefinitionComparer + /// ----------------------------------------------------------------------------- + /// + /// The ProfilePropertyDefinitionComparer class provides an implementation of + /// IComparer to sort the ProfilePropertyDefinitionCollection by ViewOrder + /// + /// + /// + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public class ProfilePropertyDefinitionComparer : IComparer + { + #region IComparer Members + + /// ----------------------------------------------------------------------------- + /// + /// Compares two ProfilePropertyDefinition objects + /// + /// A ProfilePropertyDefinition object + /// A ProfilePropertyDefinition object + /// An integer indicating whether x greater than y, x=y or x less than y + /// + /// [cnurse] 01/31/2006 created + /// + /// ----------------------------------------------------------------------------- + public int Compare(object x, object y) + { + return ((ProfilePropertyDefinition) x).ViewOrder.CompareTo(((ProfilePropertyDefinition) y).ViewOrder); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Profile/ProfileVisibility.cs b/DNN Platform/Library/Entities/Profile/ProfileVisibility.cs new file mode 100644 index 00000000000..2f5dccd1fee --- /dev/null +++ b/DNN Platform/Library/Entities/Profile/ProfileVisibility.cs @@ -0,0 +1,113 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +namespace DotNetNuke.Entities.Profile +{ + [Serializable] + public class ProfileVisibility + { + public ProfileVisibility() + { + RoleVisibilities = new List(); + RelationshipVisibilities = new List(); + } + + public ProfileVisibility(int portalId, string extendedVisibility) : this() + { + if (!String.IsNullOrEmpty(extendedVisibility)) + { + var relationshipController = new RelationshipController(); + + var lists = extendedVisibility.Split(';'); + + if (!String.IsNullOrEmpty(lists[0].Substring(2).TrimEnd(','))) + { + var roles = lists[0].Substring(2).TrimEnd(',').Split(','); + foreach (var role in roles) + { + int roleId = Int32.Parse(role); + RoleInfo userRole = TestableRoleController.Instance.GetRole(portalId, r => r.RoleID == roleId); + RoleVisibilities.Add(userRole); + } + } + if (!String.IsNullOrEmpty(lists[1].Substring(2).TrimEnd(','))) + { + var relationships = lists[1].Substring(2).TrimEnd(',').Split(','); + foreach (var relationship in relationships) + { + Relationship userRelationship = RelationshipController.Instance.GetRelationship(Int32.Parse(relationship)); + RelationshipVisibilities.Add(userRelationship); + } + } + } + + } + + public UserVisibilityMode VisibilityMode { get; set; } + + public IList RoleVisibilities { get; set; } + + public IList RelationshipVisibilities { get; set; } + + public ProfileVisibility Clone() + { + var pv = new ProfileVisibility() + { + VisibilityMode = VisibilityMode, + RoleVisibilities = new List(RoleVisibilities), + RelationshipVisibilities = new List(RelationshipVisibilities) + }; + return pv; + } + + public string ExtendedVisibilityString() + { + if (VisibilityMode == UserVisibilityMode.FriendsAndGroups) + { + var sb = new StringBuilder(); + sb.Append("G:"); + foreach (var role in RoleVisibilities) + { + sb.Append(role.RoleID.ToString(CultureInfo.InvariantCulture) + ","); + } + sb.Append(";R:"); + foreach (var relationship in RelationshipVisibilities) + { + sb.Append(relationship.RelationshipId.ToString(CultureInfo.InvariantCulture) + ","); + } + + return sb.ToString(); + } + + return String.Empty; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/Internal/ITabController.cs b/DNN Platform/Library/Entities/Tabs/Internal/ITabController.cs new file mode 100644 index 00000000000..6e1985fb93f --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/Internal/ITabController.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Tabs.Internal +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface ITabController + { + void DeleteTabUrl(TabUrlInfo tabUrl, int portalId, bool clearCache); + + /// + /// Gets the tab. + /// + /// The tab id. + /// The portal id. + /// tab info. + TabInfo GetTab(int tabId, int portalId); + + Dictionary GetCustomAliases(int tabId, int portalId); + + List GetAliasSkins(int tabId, int portalId); + + List GetTabUrls(int tabId, int portalId); + + void SaveTabUrl(TabUrlInfo tabUrl, int portalId, bool clearCache); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/Internal/TabControllerImpl.cs b/DNN Platform/Library/Entities/Tabs/Internal/TabControllerImpl.cs new file mode 100644 index 00000000000..bae1ef89861 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/Internal/TabControllerImpl.cs @@ -0,0 +1,311 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +namespace DotNetNuke.Entities.Tabs.Internal +{ + internal class TabControllerImpl : ITabController + { + readonly TabController _legacyController = new TabController(); + + private object GetAliasSkinsCallback(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = DataProvider.Instance().GetTabAliasSkins(portalID); + var dic = new Dictionary>(); + try + { + while (dr.Read()) + { + //fill business object + var tabAliasSkin = CBO.FillObject(dr, false); + + //add Tab Alias Skin to dictionary + if (dic.ContainsKey(tabAliasSkin.TabId)) + { + //Add Tab Alias Skin to Tab Alias Skin Collection already in dictionary for TabId + dic[tabAliasSkin.TabId].Add(tabAliasSkin); + } + else + { + //Create new Tab Alias Skin Collection for TabId + var collection = new List { tabAliasSkin }; + + //Add Collection to Dictionary + dic.Add(tabAliasSkin.TabId, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + private object GetCustomAliasesCallback(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = DataProvider.Instance().GetTabCustomAliases(portalID); + var dic = new Dictionary>(); + try + { + while (dr.Read()) + { + //fill business object + var tabId = (int)dr["TabId"]; + var customAlias = (string)dr["httpAlias"]; + var cultureCode = (string)dr["cultureCode"]; + + //add Custom Alias to dictionary + if (dic.ContainsKey(tabId)) + { + //Add Custom Alias to Custom Alias Collection already in dictionary for TabId + dic[tabId][cultureCode] = customAlias; + } + else + { + //Create new Custom Alias Collection for TabId + var collection = new Dictionary {{cultureCode, customAlias}}; + + //Add Collection to Dictionary + dic.Add(tabId, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + private object GetTabUrlsCallback(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = DataProvider.Instance().GetTabUrls(portalID); + var dic = new Dictionary>(); + try + { + while (dr.Read()) + { + //fill business object + var tabRedirect = CBO.FillObject(dr, false); + + //add Tab Redirect to dictionary + if (dic.ContainsKey(tabRedirect.TabId)) + { + //Add Tab Redirect to Tab Redirect Collection already in dictionary for TabId + dic[tabRedirect.TabId].Add(tabRedirect); + } + else + { + //Create new Tab Redirect Collection for TabId + var collection = new List { tabRedirect }; + + //Add Collection to Dictionary + dic.Add(tabRedirect.TabId, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + private Dictionary> GetAliasSkins(int portalId) + { + string cacheKey = string.Format(DataCache.TabAliasSkinCacheKey, portalId); + return CBO.GetCachedObject>>(new CacheItemArgs(cacheKey, + DataCache.TabAliasSkinCacheTimeOut, + DataCache.TabAliasSkinCachePriority, + portalId), + GetAliasSkinsCallback); + + } + + private Dictionary> GetCustomAliases(int portalId) + { + string cacheKey = string.Format(DataCache.TabCustomAliasCacheKey, portalId); + return CBO.GetCachedObject>>(new CacheItemArgs(cacheKey, + DataCache.TabCustomAliasCacheTimeOut, + DataCache.TabCustomAliasCachePriority, + portalId), + GetCustomAliasesCallback); + + } + + internal Dictionary> GetTabUrls(int portalId) + { + string cacheKey = string.Format(DataCache.TabUrlCacheKey, portalId); + return CBO.GetCachedObject>>(new CacheItemArgs(cacheKey, + DataCache.TabUrlCacheTimeOut, + DataCache.TabUrlCachePriority, + portalId), + GetTabUrlsCallback); + + } + + public void DeleteTabUrl(TabUrlInfo tabUrl, int portalId, bool clearCache) + { + DataProvider.Instance().DeleteTabUrl(tabUrl.TabId, tabUrl.SeqNum); + + var objEventLog = new EventLogController(); + objEventLog.AddLog("tabUrl.TabId", + tabUrl.TabId.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.TABURL_DELETED); + if (clearCache) + { + DataCache.RemoveCache(String.Format(DataCache.TabUrlCacheKey, portalId)); + var tab = GetTab(tabUrl.TabId, portalId); + tab.ClearTabUrls(); + } + } + + /// + /// Gets the tab. + /// + /// The tab id. + /// The portal id. + /// tab info. + public TabInfo GetTab(int tabId, int portalId) + { + return _legacyController.GetTab(tabId, portalId, false); + } + + public Dictionary GetCustomAliases(int tabId, int portalId) + { + //Get the Portal CustomAlias Dictionary + Dictionary> dicCustomAliases = GetCustomAliases(portalId); + + //Get the Collection from the Dictionary + Dictionary customAliases; + bool bFound = dicCustomAliases.TryGetValue(tabId, out customAliases); + if (!bFound) + { + //Return empty collection + customAliases = new Dictionary(); + } + return customAliases; + } + + public List GetAliasSkins(int tabId, int portalId) + { + //Get the Portal AliasSkin Dictionary + Dictionary> dicTabAliases = GetAliasSkins(portalId); + + //Get the Collection from the Dictionary + List tabAliases; + bool bFound = dicTabAliases.TryGetValue(tabId, out tabAliases); + if (!bFound) + { + //Return empty collection + tabAliases = new List(); + } + return tabAliases; + } + + public List GetTabUrls(int tabId, int portalId) + { + //Get the Portal TabUrl Dictionary + Dictionary> dicTabUrls = GetTabUrls(portalId); + + //Get the Collection from the Dictionary + List tabRedirects; + bool bFound = dicTabUrls.TryGetValue(tabId, out tabRedirects); + if (!bFound) + { + //Return empty collection + tabRedirects = new List(); + } + return tabRedirects; + } + + public void SaveTabUrl(TabUrlInfo tabUrl, int portalId, bool clearCache) + { + var portalAliasId = (tabUrl.PortalAliasUsage == PortalAliasUsageType.Default) + ? Null.NullInteger + : tabUrl.PortalAliasId; + + var saveLog = EventLogController.EventLogType.TABURL_CREATED; + + if (tabUrl.HttpStatus == "200") + { + saveLog = EventLogController.EventLogType.TABURL_CREATED; + + } + else + { + //need to see if sequence number exists to decide if insert or update + List t = GetTabUrls(portalId, tabUrl.TabId); + var existingSeq = t.FirstOrDefault(r => r.SeqNum == tabUrl.SeqNum); + if (existingSeq == null) + { + saveLog = EventLogController.EventLogType.TABURL_CREATED; + } + } + + DataProvider.Instance().SaveTabUrl(tabUrl.TabId, tabUrl.SeqNum, portalAliasId, (int)tabUrl.PortalAliasUsage, tabUrl.Url, tabUrl.QueryString, tabUrl.CultureCode, tabUrl.HttpStatus, tabUrl.IsSystem,UserController.GetCurrentUserInfo().UserID); + + var objEventLog = new EventLogController(); + objEventLog.AddLog("tabUrl", + tabUrl.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + saveLog); + + if (clearCache) + { + DataCache.RemoveCache(String.Format(DataCache.TabUrlCacheKey, portalId)); + _legacyController.ClearCache(portalId); + var tab = GetTab(tabUrl.TabId, portalId); + tab.ClearTabUrls(); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/Internal/TestableTabController.cs b/DNN Platform/Library/Entities/Tabs/Internal/TestableTabController.cs new file mode 100644 index 00000000000..a7099c83da4 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/Internal/TestableTabController.cs @@ -0,0 +1,36 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Entities.Tabs.Internal +{ + public class TestableTabController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new TabControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/PortalAliasUsageType.cs b/DNN Platform/Library/Entities/Tabs/PortalAliasUsageType.cs new file mode 100644 index 00000000000..f528f6d272a --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/PortalAliasUsageType.cs @@ -0,0 +1,39 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + + + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + public enum PortalAliasUsageType + { + Default = 0, + ChildPagesInherit = 1, + ChildPagesDoNotInherit = 2, + InheritedFromParent = 3 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/TabAliasSkinInfo.cs b/DNN Platform/Library/Entities/Tabs/TabAliasSkinInfo.cs new file mode 100644 index 00000000000..0560f250678 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabAliasSkinInfo.cs @@ -0,0 +1,69 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + /// + ///Class to represent a TabAliasSkinInfo object + /// + [Serializable] + public class TabAliasSkinInfo : BaseEntityInfo, IHydratable + { + #region Public Properties + + public int TabAliasSkinId { get; set; } + public string HttpAlias { get; set; } + public int PortalAliasId { get; set; } + public string SkinSrc { get; set; } + public int TabId { get; set; } + + #endregion + + public int KeyID + { + get { return TabAliasSkinId; } + set { TabAliasSkinId = value; } + } + + public void Fill(IDataReader dr) + { + base.FillInternal(dr); + + TabAliasSkinId = Null.SetNullInteger(dr["TabAliasSkinId"]); + HttpAlias = Null.SetNullString(dr["HttpAlias"]); + PortalAliasId = Null.SetNullInteger(dr["PortalAliasId"]); + SkinSrc = Null.SetNullString(dr["SkinSrc"]); + TabId = Null.SetNullInteger(dr["TabId"]); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/TabCollection.cs b/DNN Platform/Library/Entities/Tabs/TabCollection.cs new file mode 100644 index 00000000000..53794261ab1 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabCollection.cs @@ -0,0 +1,333 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Security; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + /// + /// Represents the collection of Tabs for a portal + /// + /// + [Serializable] + public class TabCollection : Dictionary + { + //This is used to provide a collection of children + [NonSerialized] + private readonly Dictionary> _children; + + //This is used to return a sorted List + [NonSerialized] + private readonly List _list; + + //This is used to provide a culture based set of tabs + [NonSerialized] + private readonly Dictionary> _localizedTabs; + + #region Constructors + + public TabCollection() + { + _list = new List(); + _children = new Dictionary>(); + _localizedTabs = new Dictionary>(); + } + + // The special constructor is used to deserialize values. + public TabCollection(SerializationInfo info, StreamingContext context) + : base(info, context) + { + _list = new List(); + _children = new Dictionary>(); + _localizedTabs = new Dictionary>(); + } + + public override void OnDeserialization(object sender) + { + base.OnDeserialization(sender); + + foreach (var tab in Values) + { + //Update all child collections + AddInternal(tab); + } + } + + public TabCollection(IEnumerable tabs) : this() + { + AddRange(tabs); + } + + #endregion + + #region Private Methods + + private void AddInternal(TabInfo tab) + { + if (tab.ParentId == Null.NullInteger) + { + //Add tab to Children collection + AddToChildren(tab); + + //Add to end of List as all zero-level tabs are returned in order first + _list.Add(tab); + } + else + { + //Find Parent in list + for (int index = 0; index <= _list.Count - 1; index++) + { + TabInfo parentTab = _list[index]; + if (parentTab.TabID == tab.ParentId) + { + int childCount = AddToChildren(tab); + + //Insert tab in master List + _list.Insert(index + childCount, tab); + } + } + } + //Add to localized tabs + if (tab.PortalID == Null.NullInteger || IsLocalizationEnabled(tab.PortalID)) + { + AddToLocalizedTabs(tab); + } + } + + private int AddToChildren(TabInfo tab) + { + List childList; + if (!_children.TryGetValue(tab.ParentId, out childList)) + { + childList = new List(); + _children.Add(tab.ParentId, childList); + } + + //Add tab to end of child list as children are returned in order + childList.Add(tab); + return childList.Count; + } + + private void AddToLocalizedTabCollection(TabInfo tab, string cultureCode) + { + List localizedTabCollection; + + if (!_localizedTabs.TryGetValue(cultureCode.ToLowerInvariant(), out localizedTabCollection)) + { + localizedTabCollection = new List(); + _localizedTabs.Add(cultureCode.ToLowerInvariant(), localizedTabCollection); + } + + //Add tab to end of localized tabs + localizedTabCollection.Add(tab); + } + + private void AddToLocalizedTabs(TabInfo tab) + { + if (string.IsNullOrEmpty(tab.CultureCode)) + { + //Add to all cultures + foreach (var locale in LocaleController.Instance.GetLocales(tab.PortalID).Values) + { + AddToLocalizedTabCollection(tab, locale.Code); + } + } + else + { + AddToLocalizedTabCollection(tab, tab.CultureCode); + } + } + + private List GetDescendants(int tabId, int tabLevel) + { + var descendantTabs = new List(); + for (int index = 0; index <= _list.Count - 1; index++) + { + TabInfo parentTab = _list[index]; + if (parentTab.TabID == tabId) + { + //Found Parent - so add descendents + for (int descendantIndex = index + 1; descendantIndex <= _list.Count - 1; descendantIndex++) + { + TabInfo descendantTab = _list[descendantIndex]; + + if ((tabLevel == Null.NullInteger)) + { + tabLevel = parentTab.Level; + } + + if (descendantTab.Level > tabLevel) + { + //Descendant so add to collection + descendantTabs.Add(descendantTab); + } + else + { + break; + } + } + break; + } + } + return descendantTabs; + } + + private static bool IsLocalizationEnabled() + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + return (portalSettings != null) ? portalSettings.ContentLocalizationEnabled : Null.NullBoolean; + } + + private static bool IsLocalizationEnabled(int portalId) + { + return PortalController.GetPortalSettingAsBoolean("ContentLocalizationEnabled", portalId, false); + } + + #endregion + + #region Public Methods + + public void Add(TabInfo tab) + { + //Call base class to add to base Dictionary + Add(tab.TabID, tab); + + //Update all child collections + AddInternal(tab); + } + + public void AddRange(IEnumerable tabs) + { + foreach (TabInfo tab in tabs) + { + Add(tab); + } + } + + public List AsList() + { + return _list; + } + + public List DescendentsOf(int tabId) + { + return GetDescendants(tabId, Null.NullInteger); + } + + public List DescendentsOf(int tabId, int originalTabLevel) + { + return GetDescendants(tabId, originalTabLevel); + } + + public bool IsDescendentOf(int ancestorId, int testTabId) + { + return DescendentsOf(ancestorId).Any(tab => tab.TabID == testTabId); + } + + public ArrayList ToArrayList() + { + return new ArrayList(_list); + } + + public TabCollection WithCulture(string cultureCode, bool includeNeutral) + { + return WithCulture(cultureCode, includeNeutral, IsLocalizationEnabled()); + } + public TabCollection WithCulture(string cultureCode, bool includeNeutral, bool localizationEnabled) + { + TabCollection collection; + if (localizationEnabled) + { + if (string.IsNullOrEmpty(cultureCode)) + { + //No culture passed in - so return all tabs + collection = this; + } + else + { + List tabs; + if (!_localizedTabs.TryGetValue(cultureCode.ToLowerInvariant(), out tabs)) + { + collection = new TabCollection(new List()); + } + else + { + collection = !includeNeutral + ? new TabCollection(from t in tabs + where t.CultureCode.ToLowerInvariant() == cultureCode.ToLowerInvariant() + select t) + : new TabCollection(tabs); + } + } + } + else + { + //Return all tabs + collection = this; + } + return collection; + } + + public List WithParentId(int parentId) + { + List tabs; + if (!_children.TryGetValue(parentId, out tabs)) + { + tabs = new List(); + } + return tabs; + } + + public TabInfo WithTabId(int tabId) + { + TabInfo t = null; + if (ContainsKey(tabId)) + { + t = this[tabId]; + } + return t; + } + + public TabInfo WithTabNameAndParentId(string tabName, int parentId) + { + return (from t in _list where t.TabName.Equals(tabName, StringComparison.InvariantCultureIgnoreCase) && t.ParentId == parentId select t).SingleOrDefault(); + } + + public TabInfo WithTabName(string tabName) + { + return (from t in _list where !string.IsNullOrEmpty(t.TabName) && t.TabName.Equals(tabName, StringComparison.InvariantCultureIgnoreCase) select t).FirstOrDefault(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Tabs/TabController.cs b/DNN Platform/Library/Entities/Tabs/TabController.cs new file mode 100644 index 00000000000..c56b99c48a2 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabController.cs @@ -0,0 +1,2734 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs.Internal; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + /// + /// TabController provides all operation to tabinfo. + /// + /// + /// Tab is equal to page in DotNetNuke. + /// Tabs will be a sitemap for a poatal, and every request at first need to check whether there is valid tab information + /// include in the url, if not it will use default tab to display information. + /// + public class TabController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(TabController)); + private static readonly DataProvider Provider = DataProvider.Instance(); + + /// + /// Gets the current page in current http request. + /// + /// Current Page Info. + public static TabInfo CurrentPage + { + get + { + TabInfo tab = null; + if (PortalController.GetCurrentPortalSettings() != null) + { + tab = PortalController.GetCurrentPortalSettings().ActiveTab; + } + return tab; + } + } + + #region Private Methods + + private static void AddAllTabsModules(TabInfo tab) + { + var objmodules = new ModuleController(); + var portalSettings = new PortalSettings(tab.TabID, tab.PortalID); + foreach (ModuleInfo allTabsModule in objmodules.GetAllTabsModules(tab.PortalID, true)) + { + //[DNN-6276]We need to check that the Module is not implicitly deleted. ie If all instances are on Pages + //that are all "deleted" then even if the Module itself is not deleted, we would not expect the + //Module to be added + var canAdd = + (from ModuleInfo allTabsInstance in objmodules.GetModuleTabs(allTabsModule.ModuleID) select new TabController().GetTab(allTabsInstance.TabID, tab.PortalID, false)).Any( + t => !t.IsDeleted) && (!portalSettings.ContentLocalizationEnabled || allTabsModule.CultureCode == tab.CultureCode); + if (canAdd) + { + objmodules.CopyModule(allTabsModule, tab, Null.NullString, true); + } + } + } + + private int AddTabInternal(TabInfo tab, int afterTabId, int beforeTabId, bool includeAllTabsModules) + { + ValidateTabPath(tab); + + //First create ContentItem as we need the ContentItemID + CreateContentItem(tab); + + //Add Tab + if (afterTabId > 0) + { + tab.TabID = Provider.AddTabAfter(tab, afterTabId, UserController.GetCurrentUserInfo().UserID); + } + else + { + tab.TabID = beforeTabId > 0 + ? Provider.AddTabBefore(tab, beforeTabId, UserController.GetCurrentUserInfo().UserID) + : Provider.AddTabToEnd(tab, UserController.GetCurrentUserInfo().UserID); + } + + //Clear the Cache + ClearCache(tab.PortalID); + + ITermController termController = Util.GetTermController(); + termController.RemoveTermsFromContent(tab); + foreach (Term term in tab.Terms) + { + termController.AddTermToContent(term, tab); + } + + var eventLog = new EventLogController(); + eventLog.AddLog(tab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, + "", EventLogController.EventLogType.TAB_CREATED); + + //Add Tab Permissions + TabPermissionController.SaveTabPermissions(tab); + + //Add TabSettings - use Try/catch as tabs are added during upgrade ptocess and the sproc may not exist + try + { + UpdateTabSettings(ref tab); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + + //Add AllTabs Modules + if (includeAllTabsModules && tab.PortalID != Null.NullInteger) + { + AddAllTabsModules(tab); + } + + return tab.TabID; + } + + private void CreateTabRedirect(TabInfo tab) + { + var settings = PortalController.GetCurrentPortalSettings(); + + + if (settings != null && tab.TabUrls.Count(u => u.HttpStatus == "200") == 0) + { + var domainRoot = Globals.AddHTTP(settings.PortalAlias.HTTPAlias); + + if (!String.IsNullOrEmpty(domainRoot)) + { + var url = Globals.NavigateURL(tab.TabID); + + url = url.Replace(domainRoot, ""); + + var seqNum = (tab.TabUrls.Count > 0) ? tab.TabUrls.Max(t => t.SeqNum) + 1 : 1; + var tabUrl = new TabUrlInfo() + { + TabId = tab.TabID, + SeqNum = seqNum, + PortalAliasId = -1, + PortalAliasUsage = PortalAliasUsageType.Default, + Url = url, + QueryString = String.Empty, + CultureCode = tab.CultureCode, + HttpStatus = "301", + IsSystem = true + }; + + TestableTabController.Instance.SaveTabUrl(tabUrl, tab.PortalID, false); + } + } + } + + private void CreateTabRedirects(TabInfo tab) + { + CreateTabRedirect(tab); + + var descendants = GetTabsByPortal(tab.PortalID).DescendentsOf(tab.TabID); + + //Create Redirect for descendant tabs + foreach (TabInfo descendantTab in descendants) + { + CreateTabRedirect(descendantTab); + } + } + + private static void DeserializeTabSettings(XmlNodeList nodeTabSettings, TabInfo objTab) + { + foreach (XmlNode oTabSettingNode in nodeTabSettings) + { + string sKey = XmlUtils.GetNodeValue(oTabSettingNode.CreateNavigator(), "settingname"); + string sValue = XmlUtils.GetNodeValue(oTabSettingNode.CreateNavigator(), "settingvalue"); + objTab.TabSettings[sKey] = sValue; + } + } + + private static void DeserializeTabPermissions(XmlNodeList nodeTabPermissions, TabInfo tab, bool isAdminTemplate) + { + var permissionController = new PermissionController(); + int permissionID = 0; + foreach (XmlNode tabPermissionNode in nodeTabPermissions) + { + string permissionKey = XmlUtils.GetNodeValue(tabPermissionNode.CreateNavigator(), "permissionkey"); + string permissionCode = XmlUtils.GetNodeValue(tabPermissionNode.CreateNavigator(), "permissioncode"); + string roleName = XmlUtils.GetNodeValue(tabPermissionNode.CreateNavigator(), "rolename"); + bool allowAccess = XmlUtils.GetNodeValueBoolean(tabPermissionNode, "allowaccess"); + ArrayList arrPermissions = permissionController.GetPermissionByCodeAndKey(permissionCode, permissionKey); + int i; + for (i = 0; i <= arrPermissions.Count - 1; i++) + { + var permission = (PermissionInfo)arrPermissions[i]; + permissionID = permission.PermissionID; + } + int roleID = int.MinValue; + switch (roleName) + { + case Globals.glbRoleAllUsersName: + roleID = Convert.ToInt32(Globals.glbRoleAllUsers); + break; + case Globals.glbRoleUnauthUserName: + roleID = Convert.ToInt32(Globals.glbRoleUnauthUser); + break; + default: + var portalController = new PortalController(); + PortalInfo portal = portalController.GetPortal(tab.PortalID); + RoleInfo role = TestableRoleController.Instance.GetRole(portal.PortalID, + r => r.RoleName == roleName); + if (role != null) + { + roleID = role.RoleID; + } + else + { + if (isAdminTemplate && roleName.ToLower() == "administrators") + { + roleID = portal.AdministratorRoleId; + } + } + break; + } + if (roleID != int.MinValue) + { + var tabPermission = new TabPermissionInfo + { + TabID = tab.TabID, + PermissionID = permissionID, + RoleID = roleID, + UserID = Null.NullInteger, + AllowAccess = allowAccess + }; + + bool canAdd = !tab.TabPermissions.Cast() + .Any(tp => tp.TabID == tabPermission.TabID + && tp.PermissionID == tabPermission.PermissionID + && tp.RoleID == tabPermission.RoleID + && tp.UserID == tabPermission.UserID); + if (canAdd) + { + tab.TabPermissions.Add(tabPermission); + } + } + } + } + + private static int GetIndexOfTab(TabInfo objTab, IEnumerable tabs) + { + return Null.NullInteger + tabs.TakeWhile(tab => tab.TabID != objTab.TabID).Count(); + } + + private static int GetPortalId(int tabId, int portalId) + { + if (Null.IsNull(portalId)) + { + Dictionary portalDic = PortalController.GetPortalDictionary(); + if (portalDic != null && portalDic.ContainsKey(tabId)) + { + portalId = portalDic[tabId]; + } + } + return portalId; + } + + private static object GetTabsByPortalCallBack(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + List tabs = CBO.FillCollection(Provider.GetTabs(portalID)); + return new TabCollection(tabs); + } + + private static object GetTabPathDictionaryCallback(CacheItemArgs cacheItemArgs) + { + string cultureCode = Convert.ToString(cacheItemArgs.ParamList[0]); + var portalID = (int)cacheItemArgs.ParamList[1]; + var tabpathDic = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + IDataReader dr = DataProvider.Instance().GetTabPaths(portalID, cultureCode); + try + { + while (dr.Read()) + { + tabpathDic[Null.SetNullString(dr["TabPath"])] = Null.SetNullInteger(dr["TabID"]); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return tabpathDic; + } + + private IEnumerable GetSiblingTabs(TabInfo objTab) + { + return GetTabsByPortal(objTab.PortalID).WithCulture(objTab.CultureCode, true).WithParentId(objTab.ParentId); + } + + private void HardDeleteTabInternal(int tabId) + { + //Delete all tabModule Instances + var moduleController = new ModuleController(); + foreach (ModuleInfo m in moduleController.GetTabModules(tabId).Values) + { + moduleController.DeleteTabModule(m.TabID, m.ModuleID, false); + } + + //Delete Tab + Provider.DeleteTab(tabId); + + //Log deletion + var eventLog = new EventLogController(); + eventLog.AddLog("TabID", + tabId.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.TAB_DELETED); + } + + private bool SoftDeleteChildTabs(int intTabid, PortalSettings portalSettings) + { + bool bDeleted = true; + foreach (TabInfo objtab in GetTabsByParent(intTabid, portalSettings.PortalId)) + { + bDeleted = SoftDeleteTabInternal(objtab, portalSettings); + if (!bDeleted) + { + break; + } + } + return bDeleted; + } + + private bool SoftDeleteTabInternal(TabInfo tabToDelete, PortalSettings portalSettings) + { + bool deleted = true; + if (!IsSpecialTab(tabToDelete.TabID, portalSettings)) + { + if (SoftDeleteChildTabs(tabToDelete.TabID, portalSettings)) + { + tabToDelete.IsDeleted = true; + UpdateTab(tabToDelete); + + var moduleCtrl = new ModuleController(); + foreach (ModuleInfo m in moduleCtrl.GetTabModules(tabToDelete.TabID).Values) + { + moduleCtrl.DeleteTabModule(m.TabID, m.ModuleID, true); + } + + var eventLogController = new EventLogController(); + eventLogController.AddLog(tabToDelete, portalSettings, portalSettings.UserId, "", + EventLogController.EventLogType.TAB_SENT_TO_RECYCLE_BIN); + } + else + { + deleted = false; + } + } + else + { + deleted = false; + } + return deleted; + } + + private static void UpdateTabVersion(int tabId) + { + Provider.UpdateTabVersion(tabId, Guid.NewGuid()); + } + + private static void ValidateTabPath(TabInfo tab) + { + string tabPath = Globals.GenerateTabPath(tab.ParentId, tab.TabName); + int tabId = GetTabByTabPath(tab.PortalID, tabPath, tab.CultureCode); + if (tabId > Null.NullInteger) + { + //Tab exists so Throw + throw new TabExistsException(tabId, + string.Format("Page Exists in portal: {0}, path: {1}, culture: {2}", + tab.PortalID, tab.TabPath, tab.CultureCode)); + } + } + + #endregion + + /// ----------------------------------------------------------------------------- + /// + /// Adds a tab + /// + /// The tab to be added + /// The tab is added to the end of the current Level. + /// + /// [cnurse] 04/30/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int AddTab(TabInfo objTab) + { + return AddTab(objTab, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a tab + /// + /// The tab to be added + /// Flag that indicates whether to add the "AllTabs" + /// Modules + /// The tab is added to the end of the current Level. + /// + /// [cnurse] 04/30/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int AddTab(TabInfo objTab, bool includeAllTabsModules) + { + //Add tab to store + int tabID = AddTabInternal(objTab, -1, -1, includeAllTabsModules); + + //Clear the Cache + ClearCache(objTab.PortalID); + + return tabID; + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a tab after the specified tab + /// + /// The tab to be added + /// Id of the tab after which this tab is added + /// + /// [cnurse] 04/30/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int AddTabAfter(TabInfo tab, int afterTabId) + { + //Add tab to store + int tabID = AddTabInternal(tab, afterTabId, -1, true); + + //Clear the Cache + ClearCache(tab.PortalID); + + return tabID; + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a tab before the specified tab + /// + /// The tab to be added + /// Id of the tab before which this tab is added + /// + /// [cnurse] 04/30/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int AddTabBefore(TabInfo objTab, int beforeTabId) + { + //Add tab to store + int tabID = AddTabInternal(objTab, -1, beforeTabId, true); + + //Clear the Cache + ClearCache(objTab.PortalID); + + return tabID; + } + + /// + /// Clears tabs and portal cache for the specific portal. + /// + /// The portal id. + public void ClearCache(int portalId) + { + DataCache.ClearTabsCache(portalId); + + //Clear the Portal cache so the Pages count is correct + DataCache.ClearPortalCache(portalId, false); + + DataCache.RemoveCache(DataCache.PortalDictionaryCacheKey); + + CacheController.FlushPageIndexFromCache(); + } + + /// + /// Creates content item for the tab.. + /// + /// The updated tab. + public void CreateContentItem(TabInfo tab) + { + //First create ContentItem as we need the ContentItemID + var typeController = new ContentTypeController(); + ContentType contentType = + (from t in typeController.GetContentTypes() where t.ContentType == "Tab" select t).SingleOrDefault(); + + IContentController contentController = Util.GetContentController(); + tab.Content = String.IsNullOrEmpty(tab.Title) ? tab.TabName : tab.Title; + if (contentType != null) + { + tab.ContentTypeId = contentType.ContentTypeId; + } + tab.Indexed = false; + contentController.AddContentItem(tab); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a tab permanently from the database + /// + /// TabId of the tab to be deleted + /// PortalId of the portal + /// + /// The tab will not delete if it has child tab(s). + /// + /// + /// [Vicen] 19/09/2004 Added skin deassignment before deleting the tab. + /// + /// ----------------------------------------------------------------------------- + public void DeleteTab(int tabId, int portalId) + { + //parent tabs can not be deleted + if (GetTabsByPortal(portalId).WithParentId(tabId).Count == 0) + { + HardDeleteTabInternal(tabId); + } + ClearCache(portalId); + } + + /// + /// Deletes a tab permanently from the database + /// + /// The tab id. + /// The portal id. + /// if set to true will delete all child tabs. + /// + /// + /// + public void DeleteTab(int tabId, int portalId, bool deleteDescendants) + { + List descendantList = GetTabsByPortal(portalId).DescendentsOf(tabId); + if (deleteDescendants && descendantList.Count > 0) + { + //Iterate through descendants from bottom - which will remove children first + for (int i = descendantList.Count - 1; i >= 0; i += -1) + { + HardDeleteTabInternal(descendantList[i].TabID); + } + } + DeleteTab(tabId, portalId); + + ClearCache(portalId); + } + + /// + /// Delete a Setting of a tab instance + /// + /// ID of the affected tab + /// Name of the setting to be deleted + /// + /// [jlucarino] 2009-10-01 Created + /// + public void DeleteTabSetting(int tabId, string settingName) + { + Provider.DeleteTabSetting(tabId, settingName); + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.LogProperties.Add(new LogDetailInfo("TabID", tabId.ToString())); + eventLogInfo.LogProperties.Add(new LogDetailInfo("SettingName", settingName)); + eventLogInfo.LogTypeKey = EventLogController.EventLogType.TAB_SETTING_DELETED.ToString(); + eventLogController.AddLog(eventLogInfo); + + UpdateTabVersion(tabId); + DataCache.RemoveCache("GetTabSettings" + tabId); + } + + /// + /// Delete all Settings of a tab instance + /// + /// ID of the affected tab + /// + /// [jlucarino] 2009-10-01 Created + /// + public void DeleteTabSettings(int tabId) + { + Provider.DeleteTabSettings(tabId); + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.LogProperties.Add(new LogDetailInfo("TabId", tabId.ToString())); + eventLogInfo.LogTypeKey = EventLogController.EventLogType.TAB_SETTING_DELETED.ToString(); + eventLogController.AddLog(eventLogInfo); + UpdateTabVersion(tabId); + DataCache.RemoveCache("GetTabSettings" + tabId); + } + + /// + /// Deletes all tabs for a specific language. Double checks if we are not deleting pages for the default language + /// Clears the tab cache optionally + /// + /// + /// + /// + public bool DeleteTranslatedTabs(int portalId, string cultureCode, bool clearCache) + { + bool returnValue = true; + if (PortalController.GetCurrentPortalSettings() != null) + { + var defaultLanguage = PortalController.GetCurrentPortalSettings().DefaultLanguage; + if (cultureCode != defaultLanguage) + { + Provider.DeleteTranslatedTabs(portalId, cultureCode); + + if (clearCache) + { + ClearCache(portalId); + } + + } + } + return returnValue; + } + + /// + /// Reverts page culture back to Neutral (Null), to ensure a non localized site + /// clears the tab cache optionally + /// + /// + /// + /// + public void EnsureNeutralLanguage(int portalId, string cultureCode, bool clearCache) + { + Provider.EnsureNeutralLanguage(portalId, cultureCode); + if (clearCache) + { + ClearCache(portalId); + } + } + + /// + /// Converts one single tab to a neutral culture + /// clears the tab cache optionally + /// + /// + /// + /// + /// + public void ConvertTabToNeutralLanguage(int portalId, int tabId, string cultureCode, bool clearCache) + { + //parent tabs can not be deleted + if (GetTabsByPortal(portalId).WithParentId(tabId).Count == 0) + { + // delete all translated / localized tabs for this tab + var tab = GetTab(tabId, portalId, true); + foreach (var localizedTab in tab.LocalizedTabs.Values) + { + HardDeleteTabInternal(localizedTab.TabID); + } + + // reset culture of current tab back to neutral + Provider.ConvertTabToNeutralLanguage(portalId, tabId, cultureCode); + if (clearCache) + { + ClearCache(portalId); + } + } + + } + + /// + /// Returns True if a page is missing a translated version in at least one other language + /// + /// + /// + /// + public bool HasMissingLanguages(int portalId, int tabId) + { + var currentTab = GetTab(tabId, portalId, false); + var workingTab = currentTab; + var locales = LocaleController.Instance.GetLocales(portalId); + var LocaleCount = locales.Count; + if (currentTab.DefaultLanguageTab != null) + { + workingTab = currentTab.DefaultLanguageTab; + } + + var localizedCount = 1 + + locales.Values.Where(locale => !LocaleController.Instance.IsDefaultLanguage(locale.Code)) + .Count(locale => workingTab.LocalizedTabs.Values.Any(localizedTab => localizedTab.CultureCode == locale.Code)); + + return ((LocaleCount - localizedCount) != 0); + + } + + /// + /// Adds localized copies of the page in all missing languages + /// + /// + /// + public void AddMissingLanguages(int portalId, int tabId) + { + var currentTab = GetTab(tabId, portalId, false); + if (currentTab.CultureCode != null) + { + var defaultLocale = LocaleController.Instance.GetDefaultLocale(portalId); + var workingTab = currentTab; + if (workingTab.CultureCode != defaultLocale.Code && workingTab.DefaultLanguageTab == null) + { + // we are adding missing languages to a single culture page that is not in the default language + // so we must first add a page in the default culture + + CreateLocalizedCopy(workingTab, defaultLocale, false); + } + + if (currentTab.DefaultLanguageTab != null) + { + workingTab = currentTab.DefaultLanguageTab; + } + + foreach (Locale locale in LocaleController.Instance.GetLocales(portalId).Values) + { + if (!LocaleController.Instance.IsDefaultLanguage(locale.Code)) + { + bool missing = true; + foreach (var localizedTab in workingTab.LocalizedTabs.Values.Where(localizedTab => localizedTab.CultureCode == locale.Code)) + { + missing = false; + } + if (missing) + { + CreateLocalizedCopy(workingTab, locale, false); + } + } + } + + } + } + + /// + /// Gets all tabs. + /// + /// tab collection + public ArrayList GetAllTabs() + { + return CBO.FillCollection(Provider.GetAllTabs(), typeof(TabInfo)); + } + + /// + /// Gets the tab. + /// + /// The tab id. + /// The portal id. + /// if set to true will get tab info directly from database. + /// tab info. + public TabInfo GetTab(int tabId, int portalId, bool ignoreCache) + { + TabInfo tab; + + //if we are using the cache + if (ignoreCache || Host.Host.PerformanceSetting == Globals.PerformanceSettings.NoCaching) + { + tab = CBO.FillObject(Provider.GetTab(tabId)); + } + else + { + //if we do not know the PortalId then try to find it in the Portals Dictionary using the TabId + portalId = GetPortalId(tabId, portalId); + + //if we have the PortalId then try to get the TabInfo object + tab = GetTabsByPortal(portalId).WithTabId(tabId) ?? + GetTabsByPortal(GetPortalId(tabId, Null.NullInteger)).WithTabId(tabId); + + if (tab == null) + { + //recheck the info directly from database to make sure we can avoid error if the cache doesn't update + // correctly, this may occurred when install is set up in web farm. + tab = CBO.FillObject(Provider.GetTab(tabId)); + + // if tab is not null means that the cache doesn't update correctly, we need clear the cache + // and let it rebuild cache when request next time. + if (tab != null) + { + ClearCache(tab.PortalID); + } + else + { + Logger.WarnFormat("Unable to find tabId {0} of portal {1}", tabId, portalId); + } + } + } + + return tab; + } + + /// + /// Gets the tab by unique ID. + /// + /// The unique ID. + /// tab info. + public TabInfo GetTabByUniqueID(Guid uniqueID) + { + return CBO.FillObject(Provider.GetTabByUniqueID(uniqueID)); + } + + /// + /// Gets the tab by culture. + /// + /// The tab id. + /// The portal id. + /// The locale. + /// tab info. + public TabInfo GetTabByCulture(int tabId, int portalId, Locale locale) + { + TabInfo localizedTab = null; + TabCollection tabs = GetTabsByPortal(portalId); + + //Get Tab specified by Id + TabInfo originalTab = tabs.WithTabId(tabId); + + if (locale != null && originalTab != null) + { + //Check if tab is in the requested culture + if (string.IsNullOrEmpty(originalTab.CultureCode) || originalTab.CultureCode == locale.Code) + { + localizedTab = originalTab; + } + else + { + //See if tab exists for culture + if (originalTab.IsDefaultLanguage) + { + originalTab.LocalizedTabs.TryGetValue(locale.Code, out localizedTab); + } + else + { + if (originalTab.DefaultLanguageTab != null) + { + if (originalTab.DefaultLanguageTab.CultureCode == locale.Code) + { + localizedTab = originalTab.DefaultLanguageTab; + } + else + { + if ( + !originalTab.DefaultLanguageTab.LocalizedTabs.TryGetValue(locale.Code, + out localizedTab)) + { + localizedTab = originalTab.DefaultLanguageTab; + } + } + } + } + } + } + return localizedTab; + } + + /// + /// Gets the name of the tab by name. + /// + /// Name of the tab. + /// The portal id. + /// tab info. + public TabInfo GetTabByName(string tabName, int portalId) + { + return GetTabsByPortal(portalId).WithTabName(tabName); + } + + /// + /// Gets the name of the tab by name and parent id. + /// + /// Name of the tab. + /// The portal id. + /// The parent id. + /// tab info + public TabInfo GetTabByName(string tabName, int portalId, int parentId) + { + return GetTabsByPortal(portalId).WithTabNameAndParentId(tabName, parentId); + } + + /// + /// Gets the tab count in portal. + /// + /// The portal id. + /// tab's count. + public int GetTabCount(int portalId) + { + return GetTabsByPortal(portalId).Count; + } + + /// + /// Gets the tabs by portal. + /// + /// The portal id. + /// tab collection + public TabCollection GetTabsByPortal(int portalId) + { + string cacheKey = string.Format(DataCache.TabCacheKey, portalId); + return CBO.GetCachedObject(new CacheItemArgs(cacheKey, + DataCache.TabCacheTimeOut, + DataCache.TabCachePriority, + portalId), + GetTabsByPortalCallBack); + } + + /// + /// read all settings for a tab from TabSettings table + /// + /// ID of the Tab to query + /// + /// (cached) hashtable containing all settings + /// + /// + /// [jlucarino] 2009-08-31 Created + /// + public Hashtable GetTabSettings(int tabId) + { + string cacheKey = "GetTabSettings" + tabId; + var tabSettings = (Hashtable)DataCache.GetCache(cacheKey); + if (tabSettings == null) + { + tabSettings = new Hashtable(); + IDataReader dr = Provider.GetTabSettings(tabId); + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + tabSettings[dr.GetString(0)] = dr.GetString(1); + } + else + { + tabSettings[dr.GetString(0)] = ""; + } + } + dr.Close(); + + //cache data + int intCacheTimeout = 20 * Convert.ToInt32(Host.Host.PerformanceSetting); + DataCache.SetCache(cacheKey, tabSettings, TimeSpan.FromMinutes(intCacheTimeout)); + } + return tabSettings; + } + + /// + /// Gets the tabs which use the module. + /// + /// The module ID. + /// tab collection + public IDictionary GetTabsByModuleID(int moduleID) + { + return CBO.FillDictionary("TabID", Provider.GetTabsByModuleID(moduleID)); + } + + /// + /// Gets the tabs which use the package. + /// + /// The portal ID. + /// The package ID. + /// if set to true [for host]. + /// tab collection + public IDictionary GetTabsByPackageID(int portalID, int packageID, bool forHost) + { + return CBO.FillDictionary("TabID", Provider.GetTabsByPackageID(portalID, packageID, forHost)); + } + + /// + /// Moves the tab by the tab move type. + /// + /// The obj tab. + /// The type. + /// + /// + /// + /// TabController tabCtrl = new TabController(); + /// tabCtrl.MoveTab(tab, TabMoveType.Up); + /// + /// + public void MoveTab(TabInfo tab, TabMoveType type) + { + //Get the List of tabs with the same parent + IOrderedEnumerable siblingTabs = GetSiblingTabs(tab).OrderBy(t => t.TabOrder); + int tabIndex = GetIndexOfTab(tab, siblingTabs); + switch (type) + { + case TabMoveType.Top: + MoveTabBefore(tab, siblingTabs.First().TabID); + break; + case TabMoveType.Bottom: + MoveTabAfter(tab, siblingTabs.Last().TabID); + break; + case TabMoveType.Up: + MoveTabBefore(tab, siblingTabs.ElementAt(tabIndex - 1).TabID); + break; + case TabMoveType.Down: + MoveTabAfter(tab, siblingTabs.ElementAt(tabIndex + 1).TabID); + break; + case TabMoveType.Promote: + MoveTabAfter(tab, tab.ParentId); + break; + case TabMoveType.Demote: + MoveTabToParent(tab, siblingTabs.ElementAt(tabIndex - 1).TabID); + break; + } + ClearCache(tab.PortalID); + } + + /// + /// Moves the tab after a specific tab. + /// + /// The tab want to move. + /// will move objTab after this tab. + public void MoveTabAfter(TabInfo tab, int afterTabId) + { + //Get AfterTab + var afterTab = GetTab(afterTabId, tab.PortalID, false); + + //Create Tab Redirects + if (afterTab.ParentId != tab.ParentId) + { + CreateTabRedirects(tab); + } + + //Move Tab + Provider.MoveTabAfter(tab.TabID, afterTabId, UserController.GetCurrentUserInfo().UserID); + + //Clear the Cache + ClearCache(tab.PortalID); + } + + /// + /// Moves the tab before a specific tab. + /// + /// The tab want to move. + /// will move objTab before this tab. + public void MoveTabBefore(TabInfo tab, int beforeTabId) + { + //Get AfterTab + var beforeTab = GetTab(beforeTabId, tab.PortalID, false); + + //Create Tab Redirects + if (beforeTab.ParentId != tab.ParentId) + { + CreateTabRedirects(tab); + } + + //Move Tab + Provider.MoveTabBefore(tab.TabID, beforeTabId, UserController.GetCurrentUserInfo().UserID); + + //Clear the Cache + ClearCache(tab.PortalID); + } + + public void MoveTabToParent(TabInfo tab, int parentId) + { + //Create Tab Redirects + if (parentId != tab.ParentId) + { + CreateTabRedirects(tab); + } + + //Move Tab + Provider.MoveTabToParent(tab.TabID, parentId, UserController.GetCurrentUserInfo().UserID); + + //Clear the Cache + ClearCache(tab.PortalID); + } + + /// + /// Populates the bread crumbs. + /// + /// The tab. + public void PopulateBreadCrumbs(ref TabInfo tab) + { + if ((tab.BreadCrumbs == null)) + { + var crumbs = new ArrayList(); + PopulateBreadCrumbs(tab.PortalID, ref crumbs, tab.TabID); + tab.BreadCrumbs = crumbs; + } + } + + /// + /// Populates the bread crumbs. + /// + /// The portal ID. + /// The bread crumbs. + /// The tab ID. + public void PopulateBreadCrumbs(int portalID, ref ArrayList breadCrumbs, int tabID) + { + //find the tab in the tabs collection + TabInfo tab; + var tabController = new TabController(); + TabCollection portalTabs = tabController.GetTabsByPortal(portalID); + TabCollection hostTabs = tabController.GetTabsByPortal(Null.NullInteger); + bool found = portalTabs.TryGetValue(tabID, out tab); + if (!found) + { + found = hostTabs.TryGetValue(tabID, out tab); + } + //if tab was found + if (found) + { + breadCrumbs.Insert(0, tab.Clone()); + + //get the tab parent + if (!Null.IsNull(tab.ParentId)) + { + PopulateBreadCrumbs(portalID, ref breadCrumbs, tab.ParentId); + } + } + } + + /// + /// Restores the tab. + /// + /// The obj tab. + /// The portal settings. + public void RestoreTab(TabInfo tab, PortalSettings portalSettings) + { + if (tab.DefaultLanguageTab != null) + { + //We are trying to restore the child, so recall this function with the master language's tab id + RestoreTab(tab.DefaultLanguageTab, portalSettings); + return; + } + + tab.IsDeleted = false; + UpdateTab(tab); + + //Restore any localized children + foreach (TabInfo localizedtab in tab.LocalizedTabs.Values) + { + localizedtab.IsDeleted = false; + UpdateTab(localizedtab); + } + + var eventLogController = new EventLogController(); + eventLogController.AddLog(tab, portalSettings, portalSettings.UserId, "", + EventLogController.EventLogType.TAB_RESTORED); + + var moduleController = new ModuleController(); + ArrayList allTabsModules = moduleController.GetAllTabsModules(tab.PortalID, true); + foreach (ModuleInfo objModule in allTabsModules) + { + moduleController.CopyModule(objModule, tab, Null.NullString, true); + } + + ClearCache(tab.PortalID); + } + + /// + /// Soft Deletes the tab by setting the IsDeleted property to true. + /// + /// The tab id. + /// The portal settings. + /// + public bool SoftDeleteTab(int tabId, PortalSettings portalSettings) + { + bool deleted; + TabInfo tab = GetTab(tabId, portalSettings.PortalId, false); + if (tab != null) + { + if (tab.DefaultLanguageTab != null && + LocaleController.Instance.GetLocales(portalSettings.PortalId).ContainsKey(tab.CultureCode)) + { + //We are trying to delete the child, so recall this function with the master language's tab id + return SoftDeleteTab(tab.DefaultLanguageTab.TabID, portalSettings); + } + + //Delete the Tab + deleted = SoftDeleteTabInternal(tab, portalSettings); + + //Delete any localized children + if (deleted) + { + foreach (TabInfo localizedtab in tab.LocalizedTabs.Values) + { + SoftDeleteTabInternal(localizedtab, portalSettings); + } + } + } + else + { + deleted = false; + } + return deleted; + } + + /// + /// Updates the tab to databse. + /// + /// The updated tab. + public void UpdateTab(TabInfo updatedTab) + { + TabInfo originalTab = GetTab(updatedTab.TabID, updatedTab.PortalID, true); + + //Update ContentItem If neccessary + if (updatedTab.ContentItemId == Null.NullInteger && updatedTab.TabID != Null.NullInteger) + { + CreateContentItem(updatedTab); + } + + //Create Tab Redirects + if (originalTab.ParentId != updatedTab.ParentId || originalTab.TabName != updatedTab.TabName) + { + CreateTabRedirects(updatedTab); + } + + //Update Tab to DataStore + Provider.UpdateTab(updatedTab.TabID, + updatedTab.ContentItemId, + updatedTab.PortalID, + updatedTab.VersionGuid, + updatedTab.DefaultLanguageGuid, + updatedTab.LocalizedVersionGuid, + updatedTab.TabName, + updatedTab.IsVisible, + updatedTab.DisableLink, + updatedTab.ParentId, + updatedTab.IconFileRaw, + updatedTab.IconFileLargeRaw, + updatedTab.Title, + updatedTab.Description, + updatedTab.KeyWords, + updatedTab.IsDeleted, + updatedTab.Url, + updatedTab.SkinSrc, + updatedTab.ContainerSrc, + updatedTab.StartDate, + updatedTab.EndDate, + updatedTab.RefreshInterval, + updatedTab.PageHeadText, + updatedTab.IsSecure, + updatedTab.PermanentRedirect, + updatedTab.SiteMapPriority, + UserController.GetCurrentUserInfo().UserID, + updatedTab.CultureCode); + + //Update Tags + List terms = updatedTab.Terms; + ITermController termController = Util.GetTermController(); + termController.RemoveTermsFromContent(updatedTab); + foreach (Term term in terms) + { + termController.AddTermToContent(term, updatedTab); + } + + var eventLogController = new EventLogController(); + eventLogController.AddLog(updatedTab, PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, "", + EventLogController.EventLogType.TAB_UPDATED); + + //Update Tab permissions + TabPermissionController.SaveTabPermissions(updatedTab); + + //Update TabSettings - use Try/catch as tabs are added during upgrade ptocess and the sproc may not exist + try + { + UpdateTabSettings(ref updatedTab); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + + //Update Tab Version + UpdateTabVersion(updatedTab.TabID); + + //Clear Tab Caches + ClearCache(updatedTab.PortalID); + if (updatedTab.PortalID != originalTab.PortalID) + { + ClearCache(originalTab.PortalID); + } + } + + /// + /// Updates the tab settings. + /// + /// The updated tab. + private void UpdateTabSettings(ref TabInfo updatedTab) + { + foreach (string sKeyLoopVariable in updatedTab.TabSettings.Keys) + { + string sKey = sKeyLoopVariable; + UpdateTabSetting(updatedTab.TabID, sKey, Convert.ToString(updatedTab.TabSettings[sKey])); + } + } + + /// + /// Adds or updates a tab's setting value + /// + /// ID of the tab to update + /// name of the setting property + /// value of the setting (String). + /// empty SettingValue will remove the setting, if not preserveIfEmpty is true + /// + /// [jlucarino] 2009-10-01 Created + /// + public void UpdateTabSetting(int tabId, string settingName, string settingValue) + { + IDataReader dr = Provider.GetTabSetting(tabId, settingName); + if (dr.Read()) + { + if (dr.GetString(0) != settingValue) + { + Provider.UpdateTabSetting(tabId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.TAB_SETTING_UPDATED, + "TabId", tabId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + } + else + { + Provider.AddTabSetting(tabId, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + EventLogController.AddSettingLog(EventLogController.EventLogType.TAB_SETTING_CREATED, + "TabId", tabId, settingName, settingValue, + UserController.GetCurrentUserInfo().UserID); + } + dr.Close(); + + UpdateTabVersion(tabId); + DataCache.RemoveCache("GetTabSettings" + tabId); + } + + /// + /// Updates the translation status. + /// + /// The localized tab. + /// if set to true means the tab has already been translated. + public void UpdateTranslationStatus(TabInfo localizedTab, bool isTranslated) + { + if (isTranslated && (localizedTab.DefaultLanguageTab != null)) + { + localizedTab.LocalizedVersionGuid = localizedTab.DefaultLanguageTab.LocalizedVersionGuid; + } + else + { + localizedTab.LocalizedVersionGuid = Guid.NewGuid(); + } + DataProvider.Instance() + .UpdateTabTranslationStatus(localizedTab.TabID, localizedTab.LocalizedVersionGuid, + UserController.GetCurrentUserInfo().UserID); + + //Clear Tab Caches + ClearCache(localizedTab.PortalID); + } + + #region Static Methods + + /// + /// Copies the design to children. + /// + /// The parent tab. + /// The skin SRC. + /// The container SRC. + public static void CopyDesignToChildren(TabInfo parentTab, string skinSrc, string containerSrc) + { + CopyDesignToChildren(parentTab, skinSrc, containerSrc, + PortalController.GetActivePortalLanguage(parentTab.PortalID)); + } + + /// + /// Copies the design to children. + /// + /// The parent tab. + /// The skin SRC. + /// The container SRC. + /// The culture code. + public static void CopyDesignToChildren(TabInfo parentTab, string skinSrc, string containerSrc, + string cultureCode) + { + bool clearCache = Null.NullBoolean; + var tabController = new TabController(); + List childTabs = tabController.GetTabsByPortal(parentTab.PortalID).DescendentsOf(parentTab.TabID); + foreach (TabInfo tab in childTabs) + { + if (TabPermissionController.CanAdminPage(tab)) + { + //Update ContentItem If neccessary + if (tab.ContentItemId == Null.NullInteger && tab.TabID != Null.NullInteger) + { + tabController.CreateContentItem(tab); + } + + Provider.UpdateTab(tab.TabID, + tab.ContentItemId, + tab.PortalID, + tab.VersionGuid, + tab.DefaultLanguageGuid, + tab.LocalizedVersionGuid, + tab.TabName, + tab.IsVisible, + tab.DisableLink, + tab.ParentId, + tab.IconFileRaw, + tab.IconFileLargeRaw, + tab.Title, + tab.Description, + tab.KeyWords, + tab.IsDeleted, + tab.Url, + skinSrc, + containerSrc, + tab.StartDate, + tab.EndDate, + tab.RefreshInterval, + tab.PageHeadText, + tab.IsSecure, + tab.PermanentRedirect, + tab.SiteMapPriority, + UserController.GetCurrentUserInfo().UserID, + tab.CultureCode); + + UpdateTabVersion(tab.TabID); + + var eventLogController = new EventLogController(); + eventLogController.AddLog(tab, PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, "", + EventLogController.EventLogType.TAB_UPDATED); + clearCache = true; + } + } + if (clearCache) + { + DataCache.ClearTabsCache(childTabs[0].PortalID); + } + } + + /// + /// Copies the permissions to children. + /// + /// The parent tab. + /// The new permissions. + public static void CopyPermissionsToChildren(TabInfo parentTab, TabPermissionCollection newPermissions) + { + bool clearCache = Null.NullBoolean; + List childTabs = + new TabController().GetTabsByPortal(parentTab.PortalID).DescendentsOf(parentTab.TabID); + foreach (TabInfo tab in childTabs) + { + if (TabPermissionController.CanAdminPage(tab)) + { + tab.TabPermissions.Clear(); + tab.TabPermissions.AddRange(newPermissions); + TabPermissionController.SaveTabPermissions(tab); + UpdateTabVersion(tab.TabID); + clearCache = true; + } + } + if (clearCache) + { + DataCache.ClearTabsCache(childTabs[0].PortalID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Processes all panes and modules in the template file + /// + /// Template file node for the panes is current tab + /// PortalId of the new portal + /// Tab being processed + /// Tabs need to merge. + /// Modules Hashtable. + /// + /// + /// + /// [VMasanas] 03/09/2004 Created + /// [VMasanas] 15/10/2004 Modified for new skin structure + /// [cnurse] 15/10/2004 Modified to allow for merging template + /// with existing pages + /// [cnurse] 10/02/2007 Moved from PortalController + /// + /// ----------------------------------------------------------------------------- + public static void DeserializePanes(XmlNode nodePanes, int portalId, int tabId, + PortalTemplateModuleAction mergeTabs, Hashtable hModules) + { + var moduleController = new ModuleController(); + + Dictionary dicModules = moduleController.GetTabModules(tabId); + + //If Mode is Replace remove all the modules already on this Tab + if (mergeTabs == PortalTemplateModuleAction.Replace) + { + foreach (KeyValuePair kvp in dicModules.Where(kvp => !kvp.Value.AllTabs)) + { + moduleController.DeleteTabModule(tabId, kvp.Value.ModuleID, false); + } + } + + //iterate through the panes + foreach (XmlNode nodePane in nodePanes.ChildNodes) + { + //iterate through the modules + if (nodePane.SelectSingleNode("modules") != null) + { + XmlNode selectSingleNode = nodePane.SelectSingleNode("modules"); + if (selectSingleNode != null) + { + foreach (XmlNode nodeModule in selectSingleNode) + { + ModuleController.DeserializeModule(nodeModule, nodePane, portalId, tabId, mergeTabs, + hModules); + } + } + } + } + } + + /// + /// Deserializes the tab. + /// + /// The node tab. + /// The obj tab. + /// The portal id. + /// The merge tabs. + /// + public static TabInfo DeserializeTab(XmlNode tabNode, TabInfo tab, int portalId, + PortalTemplateModuleAction mergeTabs) + { + return DeserializeTab(tabNode, tab, new Hashtable(), portalId, false, mergeTabs, new Hashtable()); + } + + /// + /// Deserializes the tab. + /// + /// The node tab. + /// The obj tab. + /// The h tabs. + /// The portal id. + /// if set to true [is admin template]. + /// The merge tabs. + /// The h modules. + /// + public static TabInfo DeserializeTab(XmlNode tabNode, TabInfo tab, Hashtable tabs, int portalId, + bool isAdminTemplate, PortalTemplateModuleAction mergeTabs, + Hashtable modules) + { + var tabController = new TabController(); + string tabName = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "name"); + if (!String.IsNullOrEmpty(tabName)) + { + if (tab == null) + { + tab = new TabInfo { TabID = Null.NullInteger, ParentId = Null.NullInteger, TabName = tabName }; + } + tab.PortalID = portalId; + if (string.IsNullOrEmpty(tab.Title)) + { + tab.Title = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "title"); + } + + if (string.IsNullOrEmpty(tab.Description)) + { + tab.Description = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "description"); + } + + tab.KeyWords = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "keywords"); + tab.IsVisible = XmlUtils.GetNodeValueBoolean(tabNode, "visible", true); + tab.DisableLink = XmlUtils.GetNodeValueBoolean(tabNode, "disabled"); + tab.IconFile = Globals.ImportFile(portalId, XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "iconfile")); + tab.IconFileLarge = Globals.ImportFile(portalId, + XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "iconfilelarge")); + tab.Url = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "url"); + tab.StartDate = XmlUtils.GetNodeValueDate(tabNode, "startdate", Null.NullDate); + tab.EndDate = XmlUtils.GetNodeValueDate(tabNode, "enddate", Null.NullDate); + tab.RefreshInterval = XmlUtils.GetNodeValueInt(tabNode, "refreshinterval", Null.NullInteger); + tab.PageHeadText = XmlUtils.GetNodeValue(tabNode, "pageheadtext", Null.NullString); + tab.IsSecure = XmlUtils.GetNodeValueBoolean(tabNode, "issecure", false); + tab.SiteMapPriority = XmlUtils.GetNodeValueSingle(tabNode, "sitemappriority", (float)0.5); + tab.CultureCode = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "cultureCode"); + //objTab.UniqueId = New Guid(XmlUtils.GetNodeValue(nodeTab, "guid", Guid.NewGuid.ToString())); + //objTab.VersionGuid = New Guid(XmlUtils.GetNodeValue(nodeTab, "versionGuid", Guid.NewGuid.ToString())); + tab.UseBaseFriendlyUrls = XmlUtils.GetNodeValueBoolean(tabNode, "UseBaseFriendlyUrls", false); + + tab.TabPermissions.Clear(); + DeserializeTabPermissions(tabNode.SelectNodes("tabpermissions/permission"), tab, isAdminTemplate); + + DeserializeTabSettings(tabNode.SelectNodes("tabsettings/tabsetting"), tab); + + //set tab skin and container + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(tabNode, "skinsrc", ""))) + { + tab.SkinSrc = XmlUtils.GetNodeValue(tabNode, "skinsrc", ""); + } + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(tabNode, "containersrc", ""))) + { + tab.ContainerSrc = XmlUtils.GetNodeValue(tabNode, "containersrc", ""); + } + + tabName = tab.TabName; + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "parent"))) + { + if (tabs[XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "parent")] != null) + { + //parent node specifies the path (tab1/tab2/tab3), use saved tabid + tab.ParentId = Convert.ToInt32(tabs[XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "parent")]); + tabName = XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "parent") + "/" + tab.TabName; + } + else + { + //Parent node doesn't spcecify the path, search by name. + //Possible incoherence if tabname not unique + TabInfo objParent = + tabController.GetTabByName(XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "parent"), + portalId); + if (objParent != null) + { + tab.ParentId = objParent.TabID; + tabName = objParent.TabName + "/" + tab.TabName; + } + else + { + //parent tab not found! + tab.ParentId = Null.NullInteger; + tabName = tab.TabName; + } + } + } + + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "defaultLanguageTab"))) + { + if (tabs[XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "defaultLanguageTab")] != null) + { + //parent node specifies the path (tab1/tab2/tab3), use saved tabid + int defaultLanguageTabId = + Convert.ToInt32(tabs[XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "defaultLanguageTab")]); + TabInfo defaultLanguageTab = tabController.GetTab(defaultLanguageTabId, portalId, false); + if (defaultLanguageTab != null) + { + tab.DefaultLanguageGuid = defaultLanguageTab.UniqueId; + } + } + else + { + //Parent node doesn't spcecify the path, search by name. + //Possible incoherence if tabname not unique + TabInfo defaultLanguageTab = + tabController.GetTabByName( + XmlUtils.GetNodeValue(tabNode.CreateNavigator(), "defaultLanguageTab"), portalId); + if (defaultLanguageTab != null) + { + tab.DefaultLanguageGuid = defaultLanguageTab.UniqueId; + } + } + } + + //create/update tab + if (tab.TabID == Null.NullInteger) + { + tab.TabID = tabController.AddTab(tab); + } + else + { + tabController.UpdateTab(tab); + } + + //extra check for duplicate tabs in same level + if (tabs[tabName] == null) + { + tabs.Add(tabName, tab.TabID); + } + } + + //Parse Panes + if (tabNode.SelectSingleNode("panes") != null) + { + DeserializePanes(tabNode.SelectSingleNode("panes"), portalId, tab.TabID, mergeTabs, modules); + } + + //Finally add "tabid" to node + tabNode.AppendChild(XmlUtils.CreateElement(tabNode.OwnerDocument, "tabid", tab.TabID.ToString())); + return tab; + } + + /// + /// Gets the portal tabs. + /// + /// The portal id. + /// The exclude tab id. + /// if set to true [include none specified]. + /// if set to true [include hidden]. + /// + public static List GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, + bool includeHidden) + { + return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), + excludeTabId, + includeNoneSpecified, + "<" + Localization.GetString("None_Specified") + ">", + includeHidden, + false, + false, + false, + false); + } + + /// + /// Gets the portal tabs. + /// + /// The portal id. + /// The exclude tab id. + /// if set to true [include none specified]. + /// if set to true [include hidden]. + /// if set to true [include deleted]. + /// if set to true [include URL]. + /// + public static List GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, + bool includeHidden, bool includeDeleted, bool includeURL) + { + return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), + excludeTabId, + includeNoneSpecified, + "<" + Localization.GetString("None_Specified") + ">", + includeHidden, + includeDeleted, + includeURL, + false, + false); + } + + /// + /// Gets the portal tabs. + /// + /// The portal id. + /// The exclude tab id. + /// if set to true [include none specified]. + /// The none specified text. + /// if set to true [include hidden]. + /// if set to true [include deleted]. + /// if set to true [include URL]. + /// if set to true [check view permisison]. + /// if set to true [check edit permission]. + /// + public static List GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, + string noneSpecifiedText, bool includeHidden, bool includeDeleted, + bool includeURL, + bool checkViewPermisison, bool checkEditPermission) + { + return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), + excludeTabId, + includeNoneSpecified, + noneSpecifiedText, + includeHidden, + includeDeleted, + includeURL, + checkViewPermisison, + checkEditPermission); + } + + /// + /// Gets the portal tabs. + /// + /// The tabs. + /// The exclude tab id. + /// if set to true [include none specified]. + /// The none specified text. + /// if set to true [include hidden]. + /// if set to true [include deleted]. + /// if set to true [include URL]. + /// if set to true [check view permisison]. + /// if set to true [check edit permission]. + /// + public static List GetPortalTabs(List tabs, int excludeTabId, bool includeNoneSpecified, + string noneSpecifiedText, bool includeHidden, bool includeDeleted, + bool includeURL, + bool checkViewPermisison, bool checkEditPermission) + { + var listTabs = new List(); + if (includeNoneSpecified) + { + var tab = new TabInfo { TabID = -1, TabName = noneSpecifiedText, TabOrder = 0, ParentId = -2 }; + listTabs.Add(tab); + } + foreach (TabInfo objTab in tabs) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + if (((excludeTabId < 0) || (objTab.TabID != excludeTabId)) && + (!objTab.IsSuperTab || objUserInfo.IsSuperUser)) + { + if ((objTab.IsVisible || includeHidden) && (objTab.IsDeleted == false || includeDeleted) && + (objTab.TabType == TabType.Normal || includeURL)) + { + //Check if User has View/Edit Permission for this tab + if (checkEditPermission || checkViewPermisison) + { + const string permissionList = "ADD,COPY,EDIT,MANAGE"; + if (checkEditPermission && + TabPermissionController.HasTabPermission(objTab.TabPermissions, permissionList)) + { + listTabs.Add(objTab); + } + else if (checkViewPermisison && TabPermissionController.CanViewPage(objTab)) + { + listTabs.Add(objTab); + } + } + else + { + //Add Tab to List + listTabs.Add(objTab); + } + } + } + } + return listTabs; + } + + /// + /// Gets the tab by tab path. + /// + /// The portal id. + /// The tab path. + /// The culture code. + /// + public static int GetTabByTabPath(int portalId, string tabPath, string cultureCode) + { + Dictionary tabpathDic = GetTabPathDictionary(portalId, cultureCode); + if (tabpathDic.ContainsKey(tabPath)) + { + return tabpathDic[tabPath]; + } + return -1; + } + + /// + /// Gets the tab path dictionary. + /// + /// The portal id. + /// The culture code. + /// + public static Dictionary GetTabPathDictionary(int portalId, string cultureCode) + { + string cacheKey = string.Format(DataCache.TabPathCacheKey, cultureCode, portalId); + return + CBO.GetCachedObject>( + new CacheItemArgs(cacheKey, DataCache.TabPathCacheTimeOut, DataCache.TabPathCachePriority, + cultureCode, portalId), + GetTabPathDictionaryCallback); + } + + /// + /// Gets the tabs by parent. + /// + /// The parent id. + /// The portal id. + /// + public static List GetTabsByParent(int parentId, int portalId) + { + return new TabController().GetTabsByPortal(portalId).WithParentId(parentId); + } + + /// + /// Gets the tabs by sort order. + /// + /// The portal id. + /// The culture code. + /// if set to true [include neutral]. + /// + public static List GetTabsBySortOrder(int portalId, string cultureCode, bool includeNeutral) + { + return new TabController().GetTabsByPortal(portalId).WithCulture(cultureCode, includeNeutral).AsList(); + } + + /// + /// Get all TabInfo for the current culture in SortOrder + /// + /// The portalid to load tabs for + /// + /// List of TabInfo oredered by default SortOrder + /// + /// + /// This method uses the Active culture. There is an overload + /// which allows the culture information to be specified. + /// + public static List GetTabsBySortOrder(int portalId) + { + return GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true); + } + + /// + /// Determines whether is special tab. + /// + /// The tab id. + /// The portal id. + /// + public static bool IsSpecialTab(int tabId, int portalId) + { + Dictionary locales = LocaleController.Instance.GetLocales(portalId); + var portalController = new PortalController(); + bool isSpecial = false; + foreach (Locale locale in locales.Values) + { + PortalInfo portal = portalController.GetPortal(portalId, locale.Code); + var portalSettings = new PortalSettings(portal); + isSpecial = IsSpecialTab(tabId, portalSettings); + + if (isSpecial) + { + break; + } + } + + return isSpecial; + } + + /// + /// Determines whether is special tab. + /// + /// The tab id. + /// The portal settings. + /// + /// true if is special tab; otherwise, false. + /// + public static bool IsSpecialTab(int tabId, PortalSettings portalSettings) + { + return tabId == portalSettings.SplashTabId || tabId == portalSettings.HomeTabId || + tabId == portalSettings.LoginTabId || tabId == portalSettings.UserTabId || + tabId == portalSettings.AdminTabId || tabId == portalSettings.SuperTabId; + } + + /// + /// SerializeTab + /// + /// The Xml Document to use for the Tab + /// The TabInfo object to serialize + /// A flag used to determine if the Module content is included + public static XmlNode SerializeTab(XmlDocument tabXml, TabInfo objTab, bool includeContent) + { + return SerializeTab(tabXml, null, objTab, null, includeContent); + } + + /// + /// SerializeTab + /// + /// The Xml Document to use for the Tab + /// A Hashtable used to store the names of the tabs + /// The TabInfo object to serialize + /// The Portal object to which the tab belongs + /// A flag used to determine if the Module content is included + public static XmlNode SerializeTab(XmlDocument tabXml, Hashtable tabs, TabInfo tab, PortalInfo portal, + bool includeContent) + { + XmlNode newnode; + CBO.SerializeObject(tab, tabXml); + + XmlNode tabNode = tabXml.SelectSingleNode("tab"); + if (tabNode != null) + { + if (tabNode.Attributes != null) + { + tabNode.Attributes.Remove(tabNode.Attributes["xmlns:xsd"]); + tabNode.Attributes.Remove(tabNode.Attributes["xmlns:xsi"]); + } + + //remove unwanted elements + // ReSharper disable AssignNullToNotNullAttribute + tabNode.RemoveChild(tabNode.SelectSingleNode("tabid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("moduleID")); + tabNode.RemoveChild(tabNode.SelectSingleNode("taborder")); + tabNode.RemoveChild(tabNode.SelectSingleNode("portalid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("parentid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("isdeleted")); + tabNode.RemoveChild(tabNode.SelectSingleNode("tabpath")); + tabNode.RemoveChild(tabNode.SelectSingleNode("haschildren")); + tabNode.RemoveChild(tabNode.SelectSingleNode("skindoctype")); + tabNode.RemoveChild(tabNode.SelectSingleNode("uniqueid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("versionguid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("defaultLanguageGuid")); + tabNode.RemoveChild(tabNode.SelectSingleNode("localizedVersionGuid")); + XmlNodeList xmlNodeList = tabNode.SelectNodes("tabpermissions/permission"); + if (xmlNodeList != null && xmlNodeList.Count == 0) + { + // for some reason serialization of permissions did not work + // we are using a different method here to make sure that + // permissions are included in the tabinfo xml + XmlDocument tabPermissions = new XmlDocument(); + CBO.SerializeObject(tab.TabPermissions, tabPermissions); + + XmlNode permissionsNode = tabXml.CreateElement("tabpermissions"); + var tabPermissionsNodeList = tabPermissions.SelectNodes("tabpermissions/TabPermissionInfo"); + if (tabPermissionsNodeList != null) + { + foreach (XmlNode nodePermission in tabPermissionsNodeList) + { + var newNode = tabXml.CreateElement("permission"); + newNode.InnerXml = nodePermission.InnerXml; + permissionsNode.AppendChild(newNode); + } + } + tabNode.AppendChild(permissionsNode); + + // re-select the permissions node + xmlNodeList = tabNode.SelectNodes("tabpermissions/permission"); + } + if (xmlNodeList != null) + { + foreach (XmlNode nodePermission in xmlNodeList) + { + nodePermission.RemoveChild(nodePermission.SelectSingleNode("tabpermissionid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("permissionid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("tabid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("roleid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("userid")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("username")); + nodePermission.RemoveChild(nodePermission.SelectSingleNode("displayname")); + } + } + // ReSharper restore AssignNullToNotNullAttribute + } + + //Manage Url + XmlNode urlNode = tabXml.SelectSingleNode("tab/url"); + switch (tab.TabType) + { + case TabType.Normal: + urlNode.Attributes.Append(XmlUtils.CreateAttribute(tabXml, "type", "Normal")); + break; + case TabType.Tab: + urlNode.Attributes.Append(XmlUtils.CreateAttribute(tabXml, "type", "Tab")); + //Get the tab being linked to + TabInfo tempTab = new TabController().GetTab(Int32.Parse(tab.Url), tab.PortalID, false); + urlNode.InnerXml = tempTab.TabPath; + break; + case TabType.File: + urlNode.Attributes.Append(XmlUtils.CreateAttribute(tabXml, "type", "File")); + IFileInfo file = FileManager.Instance.GetFile(Int32.Parse(tab.Url.Substring(7))); + urlNode.InnerXml = file.RelativePath; + break; + case TabType.Url: + urlNode.Attributes.Append(XmlUtils.CreateAttribute(tabXml, "type", "Url")); + break; + } + + + //serialize TabSettings + XmlUtils.SerializeHashtable(tab.TabSettings, tabXml, tabNode, "tabsetting", "settingname", "settingvalue"); + if (portal != null) + { + if (tab.TabID == portal.SplashTabId) + { + newnode = tabXml.CreateElement("tabtype"); + newnode.InnerXml = "splashtab"; + tabNode.AppendChild(newnode); + } + else if (tab.TabID == portal.HomeTabId) + { + newnode = tabXml.CreateElement("tabtype"); + newnode.InnerXml = "hometab"; + tabNode.AppendChild(newnode); + } + else if (tab.TabID == portal.UserTabId) + { + newnode = tabXml.CreateElement("tabtype"); + newnode.InnerXml = "usertab"; + tabNode.AppendChild(newnode); + } + else if (tab.TabID == portal.LoginTabId) + { + newnode = tabXml.CreateElement("tabtype"); + newnode.InnerXml = "logintab"; + tabNode.AppendChild(newnode); + } + } + if (tabs != null) + { + //Manage Parent Tab + if (!Null.IsNull(tab.ParentId)) + { + newnode = tabXml.CreateElement("parent"); + newnode.InnerXml = HttpContext.Current.Server.HtmlEncode(tabs[tab.ParentId].ToString()); + tabNode.AppendChild(newnode); + + //save tab as: ParentTabName/CurrentTabName + tabs.Add(tab.TabID, tabs[tab.ParentId] + "/" + tab.TabName); + } + else + { + //save tab as: CurrentTabName + tabs.Add(tab.TabID, tab.TabName); + } + } + + //Manage Content Localization + if (tab.DefaultLanguageTab != null) + { + + try + { + newnode = tabXml.CreateElement("defaultLanguageTab"); + newnode.InnerXml = HttpContext.Current.Server.HtmlEncode(tabs[tab.DefaultLanguageTab.TabID].ToString()); + tabNode.AppendChild(newnode); + } + catch { } + } + + XmlNode panesNode; + XmlNode paneNode; + XmlNode nameNode; + XmlNode modulesNode; + XmlNode moduleNode; + XmlDocument moduleXml; + ModuleInfo module; + var moduleController = new ModuleController(); + + //Serialize modules + panesNode = tabNode.AppendChild(tabXml.CreateElement("panes")); + foreach (KeyValuePair kvp in moduleController.GetTabModules(tab.TabID)) + { + module = kvp.Value; + if (!module.IsDeleted) + { + moduleXml = new XmlDocument(); + moduleNode = ModuleController.SerializeModule(moduleXml, module, includeContent); + if (panesNode.SelectSingleNode("descendant::pane[name='" + module.PaneName + "']") == null) + { + //new pane found + paneNode = moduleXml.CreateElement("pane"); + nameNode = paneNode.AppendChild(moduleXml.CreateElement("name")); + nameNode.InnerText = module.PaneName; + paneNode.AppendChild(moduleXml.CreateElement("modules")); + panesNode.AppendChild(tabXml.ImportNode(paneNode, true)); + } + modulesNode = panesNode.SelectSingleNode("descendant::pane[name='" + module.PaneName + "']/modules"); + modulesNode.AppendChild(tabXml.ImportNode(moduleNode, true)); + } + } + return tabNode; + } + + /// + /// check whether have conflict between tab path and portal alias. + /// + /// portal id. + /// tab path. + /// + public static bool IsDuplicateWithPortalAlias(int portalId, string tabPath) + { + IEnumerable aliasLookup = TestablePortalAliasController.Instance.GetPortalAliases().Values; + + foreach (PortalAliasInfo alias in TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId)) + { + string checkAlias = string.Format("{0}{1}", alias.HTTPAlias, tabPath.Replace("//", "/")); + if (aliasLookup.Any(a => a.HTTPAlias.Equals(checkAlias, StringComparison.InvariantCultureIgnoreCase))) + { + return true; + } + } + + return false; + } + + public static bool IsValidTabName(string tabName, out string invalidType) + { + var valid = true; + invalidType = string.Empty; + + if (string.IsNullOrEmpty(tabName.Trim())) + { + invalidType = "EmptyTabName"; + valid = false; + } + else if ((Regex.IsMatch(tabName, "^LPT[1-9]$|^COM[1-9]$", RegexOptions.IgnoreCase))) + { + invalidType = "InvalidTabName"; + valid = false; + } + else if ((Regex.IsMatch(HtmlUtils.StripNonWord(tabName, false), "^AUX$|^CON$|^NUL$|^SITEMAP$|^LINKCLICK$|^KEEPALIVE$|^DEFAULT$|^ERRORPAGE$|^LOGIN$|^REGISTER$", RegexOptions.IgnoreCase))) + { + invalidType = "InvalidTabName"; + valid = false; + } + + return valid; + } + + #endregion + + #region Content Localization + + /// + /// Creates the localized copies. + /// + /// The original tab. + public void CreateLocalizedCopies(TabInfo originalTab) + { + Locale defaultLocale = LocaleController.Instance.GetDefaultLocale(originalTab.PortalID); + foreach (Locale subLocale in LocaleController.Instance.GetLocales(originalTab.PortalID).Values) + { + if (subLocale.Code != defaultLocale.Code) + { + CreateLocalizedCopy(originalTab, subLocale); + } + } + } + + /// + /// Creates the localized copy. + /// + /// The tabs. + /// The locale. + public void CreateLocalizedCopy(List tabs, Locale locale) + { + foreach (TabInfo t in tabs) + { + CreateLocalizedCopy(t, locale); + } + } + + /// + /// Creates the localized copy. + /// + /// The original tab. + /// The locale. + public void CreateLocalizedCopy(TabInfo originalTab, Locale locale) + { + CreateLocalizedCopy(originalTab,locale,true); + } + + /// + /// Creates the localized copy. + /// + /// The original tab. + /// The locale. + /// Clear the cache? + public void CreateLocalizedCopy(TabInfo originalTab, Locale locale, bool clearCache) + { + try + { + Logger.TraceFormat("Localizing TabId: {0}, TabPath: {1}, Locale: {2}",originalTab.TabID,originalTab.TabPath,locale.Code); + var defaultLocale = LocaleController.Instance.GetDefaultLocale(originalTab.PortalID); + + //First Clone the Tab + TabInfo localizedCopy = originalTab.Clone(); + localizedCopy.TabID = Null.NullInteger; + + //Set Guids and Culture Code + localizedCopy.UniqueId = Guid.NewGuid(); + localizedCopy.VersionGuid = Guid.NewGuid(); + localizedCopy.LocalizedVersionGuid = Guid.NewGuid(); + localizedCopy.CultureCode = locale.Code; + localizedCopy.TabName = localizedCopy.TabName + " (" + locale.Code + ")"; + if (locale == defaultLocale) + { + originalTab.DefaultLanguageGuid = localizedCopy.UniqueId; + UpdateTab(originalTab); + } + else + { + localizedCopy.DefaultLanguageGuid = originalTab.UniqueId; + } + + //Copy Permissions from original Tab for Admins only + var portalCtrl = new PortalController(); + PortalInfo portal = portalCtrl.GetPortal(originalTab.PortalID); + localizedCopy.TabPermissions.AddRange( + originalTab.TabPermissions.Where(p => p.RoleID == portal.AdministratorRoleId)); + + //Get the original Tabs Parent + //check the original whether have parent. + if (!Null.IsNull(originalTab.ParentId)) + { + TabInfo originalParent = GetTab(originalTab.ParentId, originalTab.PortalID, false); + + if (originalParent != null) + { + //Get the localized parent + TabInfo localizedParent = GetTabByCulture(originalParent.TabID, originalParent.PortalID, locale); + + localizedCopy.ParentId = localizedParent.TabID; + } + } + + //Save Tab + AddTabInternal(localizedCopy, -1, -1, true); + + //Make shallow copies of all modules + var moduleCtrl = new ModuleController(); + moduleCtrl.CopyModules(originalTab, localizedCopy, true); + + //Convert these shallow copies to deep copies + foreach (KeyValuePair kvp in moduleCtrl.GetTabModules(localizedCopy.TabID)) + { + moduleCtrl.LocalizeModule(kvp.Value, locale); + } + + //Add Translator Role + GiveTranslatorRoleEditRights(localizedCopy, null); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + throw; + } + + //Clear the Cache + if (clearCache) + ClearCache(originalTab.PortalID); + } + + /// + /// Gets the default culture tab list. + /// + /// The portalid. + /// + public List GetDefaultCultureTabList(int portalid) + { + return (from kvp in GetTabsByPortal(portalid) + where !kvp.Value.TabPath.StartsWith("//Admin") + && !kvp.Value.IsDeleted + select kvp.Value).ToList(); + } + + /// + /// Gets the culture tab list. + /// + /// The portalid. + /// + public List GetCultureTabList(int portalid) + { + return (from kvp in GetTabsByPortal(portalid) + where !kvp.Value.TabPath.StartsWith("//Admin") + && kvp.Value.CultureCode == PortalController.GetCurrentPortalSettings().DefaultLanguage + && !kvp.Value.IsDeleted + select kvp.Value).ToList(); + } + + /// + /// Gives the translator role edit rights. + /// + /// The localized tab. + /// The users. + public void GiveTranslatorRoleEditRights(TabInfo localizedTab, Dictionary users) + { + var roleCtrl = new RoleController(); + var permissionCtrl = new PermissionController(); + ArrayList permissionsList = permissionCtrl.GetPermissionByCodeAndKey("SYSTEM_TAB", "EDIT"); + + string translatorRoles = + PortalController.GetPortalSetting( + string.Format("DefaultTranslatorRoles-{0}", localizedTab.CultureCode), localizedTab.PortalID, ""); + foreach (string translatorRole in translatorRoles.Split(';')) + { + if (users != null) + { + foreach (UserInfo translator in roleCtrl.GetUsersByRoleName(localizedTab.PortalID, translatorRole)) + { + users[translator.UserID] = translator; + } + } + + if (permissionsList != null && permissionsList.Count > 0) + { + var translatePermisison = (PermissionInfo)permissionsList[0]; + string roleName = translatorRole; + RoleInfo role = TestableRoleController.Instance.GetRole(localizedTab.PortalID, + r => r.RoleName == roleName); + if (role != null) + { + TabPermissionInfo perm = + localizedTab.TabPermissions.Where( + tp => tp.RoleID == role.RoleID && tp.PermissionKey == "EDIT").SingleOrDefault(); + if (perm == null) + { + //Create Permission + var tabTranslatePermission = new TabPermissionInfo(translatePermisison) + { + RoleID = role.RoleID, + AllowAccess = true, + RoleName = roleName + }; + localizedTab.TabPermissions.Add(tabTranslatePermission); + UpdateTab(localizedTab); + } + } + } + } + } + + /// + /// Localizes the tab. + /// + /// The original tab. + /// The locale. + public void LocalizeTab(TabInfo originalTab, Locale locale) + { + LocalizeTab(originalTab,locale,true); + } + + /// + /// Localizes the tab, with optional clear cache + /// + /// + /// + /// + public void LocalizeTab(TabInfo originalTab, Locale locale, bool clearCache) + { + Provider.LocalizeTab(originalTab.TabID, locale.Code, UserController.GetCurrentUserInfo().UserID); + if (clearCache) + DataCache.ClearModuleCache(originalTab.TabID); + } + + /// + /// Publishes the tab. + /// + /// The publish tab. + public void PublishTab(TabInfo publishTab) + { + //To publish a subsidiary language tab we need to enable the View Permissions + if (publishTab != null && publishTab.DefaultLanguageTab != null) + { + foreach (TabPermissionInfo perm in + publishTab.DefaultLanguageTab.TabPermissions.Where(p => p.PermissionKey == "VIEW")) + { + TabPermissionInfo sourcePerm = perm; + TabPermissionInfo targetPerm = + publishTab.TabPermissions.Where( + p => + p.PermissionKey == sourcePerm.PermissionKey && p.RoleID == sourcePerm.RoleID && + p.UserID == sourcePerm.UserID).SingleOrDefault(); + + if (targetPerm == null) + { + publishTab.TabPermissions.Add(sourcePerm); + } + + TabPermissionController.SaveTabPermissions(publishTab); + } + } + } + + /// + /// Checks whether the tab is published. Published means: view permissions of tab are identical to the DefaultLanguageTab + /// + /// The tab that is checked + /// true if tab is published + public bool IsTabPublished(TabInfo publishTab) + { + bool returnValue = true; + //To publish a subsidiary language tab we need to enable the View Permissions + if (publishTab != null && publishTab.DefaultLanguageTab != null) + { + foreach (TabPermissionInfo perm in + publishTab.DefaultLanguageTab.TabPermissions.Where(p => p.PermissionKey == "VIEW")) + { + TabPermissionInfo sourcePerm = perm; + TabPermissionInfo targetPerm = + publishTab.TabPermissions.Where( + p => + p.PermissionKey == sourcePerm.PermissionKey && p.RoleID == sourcePerm.RoleID && + p.UserID == sourcePerm.UserID).SingleOrDefault(); + + if (targetPerm == null) + { + returnValue = false; + break; + } + } + } + return returnValue; + } + + /// + /// Publishes the tabs. + /// + /// The tabs. + public void PublishTabs(List tabs) + { + foreach (TabInfo t in tabs) + { + if (t.IsTranslated) + { + PublishTab(t); + } + } + } + + #endregion + + #region Obsolete + + [Obsolete("This method has replaced in DotNetNuke 5.0 by CopyDesignToChildren(TabInfo,String, String)")] + public void CopyDesignToChildren(ArrayList tabs, string skinSrc, string containerSrc) + { + foreach (TabInfo tab in tabs) + { + Provider.UpdateTab(tab.TabID, + tab.ContentItemId, + tab.PortalID, + tab.VersionGuid, + tab.DefaultLanguageGuid, + tab.LocalizedVersionGuid, + tab.TabName, + tab.IsVisible, + tab.DisableLink, + tab.ParentId, + tab.IconFileRaw, + tab.IconFileLargeRaw, + tab.Title, + tab.Description, + tab.KeyWords, + tab.IsDeleted, + tab.Url, + skinSrc, + containerSrc, + tab.StartDate, + tab.EndDate, + tab.RefreshInterval, + tab.PageHeadText, + tab.IsSecure, + tab.PermanentRedirect, + tab.SiteMapPriority, + UserController.GetCurrentUserInfo().UserID, + tab.CultureCode); + var eventLog = new EventLogController(); + eventLog.AddLog(tab, PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, "", + EventLogController.EventLogType.TAB_UPDATED); + } + if (tabs.Count > 0) + { + DataCache.ClearTabsCache(((TabInfo)tabs[0]).PortalID); + } + } + + [Obsolete("Deprecated in DotNetNuke 5.0. Replaced by CopyPermissionsToChildren(TabInfo, TabPermissionCollection)")] + public void CopyPermissionsToChildren(ArrayList tabs, TabPermissionCollection newPermissions) + { + foreach (TabInfo tab in tabs) + { + tab.TabPermissions.Clear(); + tab.TabPermissions.AddRange(newPermissions); + TabPermissionController.SaveTabPermissions(tab); + } + if (tabs.Count > 0) + { + DataCache.ClearTabsCache(((TabInfo)tabs[0]).PortalID); + } + } + + [Obsolete("Deprecated in DotNetNuke 5.5.Replaced by ModuleController.CopyModules")] + public void CopyTab(int portalId, int fromTabId, int toTabId, bool asReference) + { + var modules = new ModuleController(); + TabInfo sourceTab = GetTab(fromTabId, portalId, false); + TabInfo destinationTab = GetTab(fromTabId, toTabId, false); + + if (sourceTab != null && destinationTab != null) + { + modules.CopyModules(sourceTab, destinationTab, asReference); + } + } + + [Obsolete("Deprecated in DNN 6.2. Replaced by SoftDeleteTab(tabId, portalSettings)")] + public static bool DeleteTab(int tabId, PortalSettings portalSettings, int userId) + { + return new TabController().SoftDeleteTab(tabId, portalSettings); + } + + [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal PortalId As Integer, ByVal mergeTabs As PortalTemplateModuleAction)")] + public static TabInfo DeserializeTab(string tabName, XmlNode nodeTab, int portalId) + { + return DeserializeTab(nodeTab, null, new Hashtable(), portalId, false, PortalTemplateModuleAction.Ignore, + new Hashtable()); + } + + [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal PortalId As Integer, ByVal mergeTabs As PortalTemplateModuleAction)")] + public static TabInfo DeserializeTab(XmlNode tabNode, TabInfo tab, int portalId) + { + return DeserializeTab(tabNode, tab, new Hashtable(), portalId, false, PortalTemplateModuleAction.Ignore, + new Hashtable()); + } + + [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal hTabs As Hashtable, ByVal PortalId As Integer, ByVal IsAdminTemplate As Boolean, ByVal mergeTabs As PortalTemplateModuleAction, ByVal hModules As Hashtable)")] + public static TabInfo DeserializeTab(string tabName, XmlNode nodeTab, TabInfo objTab, Hashtable hTabs, + int portalId, bool isAdminTemplate, PortalTemplateModuleAction mergeTabs, + Hashtable hModules) + { + return DeserializeTab(nodeTab, objTab, hTabs, portalId, isAdminTemplate, mergeTabs, hModules); + } + + [Obsolete("Deprecated in DNN 6.2. Method is redundant. Replaced by GetAllTabs()")] + public ArrayList GetAllTabs(bool checkLegacyFields) + { + return GetAllTabs(); + } + + [Obsolete("This method is obsolete. It has been replaced by GetTab(ByVal TabId As Integer, ByVal PortalId As Integer, ByVal ignoreCache As Boolean) ")] + public TabInfo GetTab(int tabId) + { + return GetTab(tabId, GetPortalId(tabId, Null.NullInteger), false); + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by GetTabByTabPath(portalId, tabPath, cultureCode) ")] + public static int GetTabByTabPath(int portalId, string tabPath) + { + return GetTabByTabPath(portalId, tabPath, Null.NullString); + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by GetTabPathDictionary(portalId, cultureCode) ")] + public static Dictionary GetTabPathDictionary(int portalId) + { + return GetTabPathDictionary(portalId, Null.NullString); + } + + [Obsolete("This method has been replaced in 5.0 by GetTabPathDictionary(ByVal portalId As Integer) As Dictionary(Of String, Integer) ")] + public static Dictionary GetTabPathDictionary() + { + var tabpathDic = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + IDataReader dr = DataProvider.Instance().GetTabPaths(Null.NullInteger, Null.NullString); + try + { + while (dr.Read()) + { + string strKey = "//" + Null.SetNullInteger(dr["PortalID"]) + Null.SetNullString(dr["TabPath"]); + tabpathDic[strKey] = Null.SetNullInteger(dr["TabID"]); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return tabpathDic; + } + + [Obsolete("This method has replaced in DotNetNuke 5.0 by GetTabsByPortal()")] + public ArrayList GetTabs(int portalId) + { + return GetTabsByPortal(portalId).ToArrayList(); + } + + [Obsolete("This method is obsolete. It has been replaced by GetTabsByParent(ByVal ParentId As Integer, ByVal PortalId As Integer) ")] + public ArrayList GetTabsByParentId(int parentId) + { + return new ArrayList(GetTabsByParent(parentId, GetPortalId(parentId, Null.NullInteger))); + } + + [Obsolete("This method has replaced in DotNetNuke 5.0 by GetTabsByParent(ByVal ParentId As Integer, ByVal PortalId As Integer)")] + public ArrayList GetTabsByParentId(int parentId, int portalId) + { + var arrTabs = new ArrayList(); + foreach (TabInfo objTab in GetTabsByParent(parentId, portalId)) + { + arrTabs.Add(objTab); + } + return arrTabs; + } + + [Obsolete("Deprecated in DNN 6.2. Replaced by RestoreTab(tabId, portalSettings)")] + public static void RestoreTab(TabInfo tab, PortalSettings portalSettings, int userId) + { + new TabController().RestoreTab(tab, portalSettings); + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by UpdateTab(updatedTab)")] + public void UpdateTab(TabInfo updatedTab, string cultureCode) + { + updatedTab.CultureCode = cultureCode; + UpdateTab(updatedTab); + } + + [Obsolete("Deprecated in DNN 6.2. Tab Ordering is handled in the DB ")] + public void UpdateTabOrder(int portalID, int tabId, int tabOrder, int level, int parentId) + { + TabInfo objTab = GetTab(tabId, portalID, false); + objTab.TabOrder = tabOrder; + objTab.Level = level; + objTab.ParentId = parentId; + UpdateTabOrder(objTab); + } + + [Obsolete("Deprecated in DNN 6.2. Tab Ordering is handled in the DB ")] + public void UpdateTabOrder(TabInfo objTab) + { + Provider.UpdateTabOrder(objTab.TabID, objTab.TabOrder, objTab.ParentId, + UserController.GetCurrentUserInfo().UserID); + UpdateTabVersion(objTab.TabID); + var eventLogController = new EventLogController(); + eventLogController.AddLog(objTab, PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, "", + EventLogController.EventLogType.TAB_ORDER_UPDATED); + ClearCache(objTab.PortalID); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/TabExistsException.cs b/DNN Platform/Library/Entities/Tabs/TabExistsException.cs new file mode 100644 index 00000000000..49af82837f2 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabExistsException.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + public class TabExistsException : Exception + { + public TabExistsException(int tabId, string message) : base(message) + { + TabId = tabId; + } + + public int TabId { get; private set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/TabExtensions.cs b/DNN Platform/Library/Entities/Tabs/TabExtensions.cs new file mode 100644 index 00000000000..bf0ee854146 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabExtensions.cs @@ -0,0 +1,109 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; +using System.Linq; + +namespace DotNetNuke.Entities.Tabs +{ + public static class TabExtensions + { + public static bool ContainsAlias(this List aliases, string httpAlias) + { + return aliases.Any(tas => System.String.Compare(httpAlias, tas.HttpAlias, System.StringComparison.OrdinalIgnoreCase) == 0); + } + + public static TabAliasSkinInfo FindByHttpAlias(this List aliases, string httpAlias) + { + return aliases.FirstOrDefault(tas => System.String.Compare(httpAlias, tas.HttpAlias, System.StringComparison.OrdinalIgnoreCase) == 0); + } + + public static int GetNextAvailableSeqNum(this List redirects, bool positive) + { + int seqNum = 1; + foreach (TabUrlInfo redirect in redirects) + { + if (positive) + { + if (redirect.SeqNum >= seqNum) + { + seqNum = redirect.SeqNum + 1; + //602 : when seqnum == 0, then duplicate key problems arise + if (seqNum == 0) + { + seqNum++; + } + } + } + else + { + seqNum = -1; + if (redirect.SeqNum <= seqNum) + { + seqNum = redirect.SeqNum - 1; + //602 : don't allow seqnum to become zero + if (seqNum == 0) + { + seqNum--; + } + } + } + } + return seqNum; + } + + public static TabUrlInfo FindByAliasId(this List redirects, int portalAliasId) + { + return redirects.FirstOrDefault(redirect => redirect.PortalAliasId == portalAliasId && portalAliasId != 0); + } + + public static TabUrlInfo CurrentUrl(this List redirects, string cultureCode) + { + TabUrlInfo result = null; + TabUrlInfo lastSystemUrl = null; + TabUrlInfo lastCustomUrl = null; + foreach (var redirect in redirects) + { + if (redirect.HttpStatus == "200" && redirect.CultureCode == cultureCode) + { + if (redirect.IsSystem) + { + lastSystemUrl = redirect; + } + else + { + lastCustomUrl = redirect; + } + } + } + //look at the results + if (lastCustomUrl != null) + { + result = lastCustomUrl; + } + else if (lastSystemUrl != null) + { + result = lastSystemUrl; + } + return result; + } + } +} diff --git a/DNN Platform/Library/Entities/Tabs/TabInfo.cs b/DNN Platform/Library/Entities/Tabs/TabInfo.cs new file mode 100644 index 00000000000..da8c74520ba --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabInfo.cs @@ -0,0 +1,1022 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Web; +using System.Xml; +using System.Xml.Serialization; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs.Internal; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Entities.Tabs +{ + [XmlRoot("tab", IsNullable = false)] + [Serializable] + public class TabInfo : ContentItem, IPropertyAccess + { + #region Private Members + + private string _administratorRoles; + private string _authorizedRoles; + private TabInfo _defaultLanguageTab; + private bool _isSuperTab; + private Dictionary _localizedTabs; + private TabPermissionCollection _permissions; + private Hashtable _settings; + private string _skinDoctype; + private bool _superTabIdSet = Null.NullBoolean; + private readonly SharedDictionary _localizedTabNameDictionary = new SharedDictionary(); + private readonly SharedDictionary _fullUrlDictionary = new SharedDictionary(); + private string _iconFile; + private string _iconFileRaw; + private string _iconFileLarge; + private string _iconFileLargeRaw; + + private List _aliasSkins; + private Dictionary _customAliases; + private List _tabUrls; + + #endregion + + #region Constructors + + public TabInfo() + : this(new SharedDictionary(), new SharedDictionary()) + { + + } + + + private TabInfo(SharedDictionary localizedTabNameDictionary, SharedDictionary fullUrlDictionary) + { + _localizedTabNameDictionary = localizedTabNameDictionary; + _fullUrlDictionary = fullUrlDictionary; + + PortalID = Null.NullInteger; + _authorizedRoles = Null.NullString; + ParentId = Null.NullInteger; + IconFile = Null.NullString; + IconFileLarge = Null.NullString; + _administratorRoles = Null.NullString; + Title = Null.NullString; + Description = Null.NullString; + KeyWords = Null.NullString; + Url = Null.NullString; + SkinSrc = Null.NullString; + _skinDoctype = Null.NullString; + ContainerSrc = Null.NullString; + TabPath = Null.NullString; + StartDate = Null.NullDate; + EndDate = Null.NullDate; + RefreshInterval = Null.NullInteger; + PageHeadText = Null.NullString; + SiteMapPriority = 0.5F; + + //UniqueId, Version Guid, and Localized Version Guid should be initialised to a new value + UniqueId = Guid.NewGuid(); + VersionGuid = Guid.NewGuid(); + LocalizedVersionGuid = Guid.NewGuid(); + + //Default Language Guid should be initialised to a null Guid + DefaultLanguageGuid = Null.NullGuid; + + IsVisible = true; + DisableLink = false; + } + + #endregion + + #region Auto-Properties + + [XmlIgnore] + public ArrayList BreadCrumbs { get; set; } + + [XmlIgnore] + public string ContainerPath { get; set; } + + [XmlElement("containersrc")] + public string ContainerSrc { get; set; } + + [XmlElement("cultureCode")] + public string CultureCode { get; set; } + + [XmlElement("defaultLanguageGuid")] + public Guid DefaultLanguageGuid { get; set; } + + [XmlElement("description")] + public string Description { get; set; } + + [XmlElement("disabled")] + public bool DisableLink { get; set; } + + [XmlElement("enddate")] + public DateTime EndDate { get; set; } + + [XmlElement("haschildren")] + public bool HasChildren { get; set; } + + [XmlElement("isdeleted")] + public bool IsDeleted { get; set; } + + [XmlElement("issecure")] + public bool IsSecure { get; set; } + + [XmlElement("visible")] + public bool IsVisible { get; set; } + + [XmlElement("keywords")] + public string KeyWords { get; set; } + + [XmlIgnore] + public int Level { get; set; } + + [XmlElement("localizedVersionGuid")] + public Guid LocalizedVersionGuid { get; set; } + + [XmlIgnore] + public ArrayList Modules { get; set; } + + [XmlElement("pageheadtext")] + public string PageHeadText { get; set; } + + [XmlIgnore] + public ArrayList Panes { get; set; } + + [XmlElement("parentid")] + public int ParentId { get; set; } + + [XmlElement("permanentredirect")] + public bool PermanentRedirect { get; set; } + + [XmlElement("portalid")] + public int PortalID { get; set; } + + [XmlElement("refreshinterval")] + public int RefreshInterval { get; set; } + + [XmlElement("sitemappriority")] + public float SiteMapPriority { get; set; } + + [XmlIgnore] + public string SkinPath { get; set; } + + [XmlElement("skinsrc")] + public string SkinSrc { get; set; } + + [XmlElement("startdate")] + public DateTime StartDate { get; set; } + + [XmlElement("name")] + public string TabName { get; set; } + + [XmlElement("taborder")] + public int TabOrder { get; set; } + + [XmlElement("tabpath")] + public string TabPath { get; set; } + + [XmlElement("title")] + public string Title { get; set; } + + [XmlElement("uniqueid")] + public Guid UniqueId { get; set; } + + [XmlElement("versionguid")] + public Guid VersionGuid { get; set; } + + #endregion + + #region Public Properties + + [XmlIgnore] + public Dictionary ChildModules + { + get + { + return new ModuleController().GetTabModules(TabID); + } + } + + [XmlIgnore] + public TabInfo DefaultLanguageTab + { + get + { + if (_defaultLanguageTab == null && (!DefaultLanguageGuid.Equals(Null.NullGuid))) + { + var tabCtrl = new TabController(); + _defaultLanguageTab = (from kvp in tabCtrl.GetTabsByPortal(PortalID) where kvp.Value.UniqueId == DefaultLanguageGuid select kvp.Value).SingleOrDefault(); + } + return _defaultLanguageTab; + } + } + + [XmlIgnore] + public bool DoNotRedirect + { + get + { + bool doNotRedirect; + if (TabSettings.ContainsKey("DoNotRedirect") && !string.IsNullOrEmpty(TabSettings["DoNotRedirect"].ToString())) + { + doNotRedirect = bool.Parse(TabSettings["DoNotRedirect"].ToString()); + } + else + { + doNotRedirect = false; + } + return doNotRedirect; + } + } + + [XmlElement("iconfile")] + public string IconFile + { + get + { + IconFileGetter(ref _iconFile, _iconFileRaw); + return _iconFile; + } + + set + { + _iconFileRaw = value; + _iconFile = null; + } + } + + [XmlElement("iconfilelarge")] + public string IconFileLarge + { + get + { + IconFileGetter(ref _iconFileLarge, _iconFileLargeRaw); + return _iconFileLarge; + } + + set + { + _iconFileLargeRaw = value; + _iconFileLarge = null; + } + } + + [XmlIgnore] + public string IconFileRaw + { + get + { + return _iconFileRaw; + } + } + + [XmlIgnore] + public string IconFileLargeRaw + { + get + { + return _iconFileLargeRaw; + } + } + + [XmlIgnore] + public string IndentedTabName + { + get + { + string indentedTabName = Null.NullString; + for (int intCounter = 1; intCounter <= Level; intCounter++) + { + indentedTabName += "..."; + } + indentedTabName += LocalizedTabName; + return indentedTabName; + } + } + + [XmlIgnore] + public bool IsDefaultLanguage + { + get + { + return (DefaultLanguageGuid == Null.NullGuid); + } + } + + [XmlIgnore] + public bool IsNeutralCulture + { + get + { + return string.IsNullOrEmpty(CultureCode); + } + } + + [XmlIgnore] + public bool IsSuperTab + { + get + { + if (_superTabIdSet) + { + return _isSuperTab; + } + return (PortalID == Null.NullInteger); + } + set + { + _isSuperTab = value; + _superTabIdSet = true; + } + } + + [XmlIgnore] + public bool IsTranslated + { + get + { + bool isTranslated = true; + if (DefaultLanguageTab != null) + { + //Child language + isTranslated = (LocalizedVersionGuid == DefaultLanguageTab.LocalizedVersionGuid); + } + return isTranslated; + } + } + + [XmlIgnore] + public override int KeyID + { + get + { + return TabID; + } + set + { + TabID = value; + } + } + + [XmlIgnore] + public string LocalizedTabName + { + get + { + if (String.IsNullOrEmpty(TabPath)) return TabName; + + var key = Thread.CurrentThread.CurrentUICulture.ToString(); + string localizedTabName; + using (_localizedTabNameDictionary.GetReadLock()) + { + _localizedTabNameDictionary.TryGetValue(key, out localizedTabName); + } + + if (String.IsNullOrEmpty(localizedTabName)) + { + using (_localizedTabNameDictionary.GetWriteLock()) + { + localizedTabName = Localization.GetString(TabPath + ".String", Localization.GlobalResourceFile, true); + if (string.IsNullOrEmpty(localizedTabName)) + { + localizedTabName = TabName; + } + + if (!_localizedTabNameDictionary.ContainsKey(key)) + { + _localizedTabNameDictionary.Add(key, localizedTabName.Trim()); + } + } + } + + return localizedTabName; + } + } + + [XmlIgnore] + public Dictionary LocalizedTabs + { + get + { + if (_localizedTabs == null) + { + var tabCtrl = new TabController(); + _localizedTabs = + (from kvp in tabCtrl.GetTabsByPortal(PortalID) + where kvp.Value.DefaultLanguageGuid == UniqueId && LocaleController.Instance.GetLocale(PortalID, kvp.Value.CultureCode) != null + select kvp.Value).ToDictionary(t => t.CultureCode); + } + return _localizedTabs; + } + } + + [XmlElement("skindoctype")] + public string SkinDoctype + { + get + { + if (string.IsNullOrEmpty(SkinSrc) == false && string.IsNullOrEmpty(_skinDoctype)) + { + _skinDoctype = CheckIfDoctypeConfigExists(); + if (string.IsNullOrEmpty(_skinDoctype)) + { + _skinDoctype = Host.Host.DefaultDocType; + } + } + return _skinDoctype; + } + set + { + _skinDoctype = value; + } + } + + [XmlArray("tabpermissions"), XmlArrayItem("permission")] + public TabPermissionCollection TabPermissions + { + get + { + return _permissions ?? (_permissions = new TabPermissionCollection(TabPermissionController.GetTabPermissions(TabID, PortalID))); + } + } + + [XmlIgnore] + public Hashtable TabSettings + { + get + { + return _settings ?? (_settings = (TabID == Null.NullInteger) ? new Hashtable() : new TabController().GetTabSettings(TabID)); + } + } + + [XmlIgnore] + public TabType TabType + { + get + { + return Globals.GetURLType(Url); + } + } + + #endregion + + #region Url Properties + + [XmlIgnore] + public List AliasSkins + { + get + { + return _aliasSkins ?? (_aliasSkins = (TabID == Null.NullInteger) ? new List() : TestableTabController.Instance.GetAliasSkins(TabID, PortalID)); + } + } + + [XmlIgnore] + public Dictionary CustomAliases + { + get + { + return _customAliases ?? (_customAliases = (TabID == Null.NullInteger) ? new Dictionary() : TestableTabController.Instance.GetCustomAliases(TabID, PortalID)); + } + } + + [XmlIgnore] + public string FullUrl + { + get + { + var key = string.Format("{0}_{1}", Globals.AddHTTP(PortalSettings.Current.PortalAlias.HTTPAlias), + Thread.CurrentThread.CurrentCulture); + + string fullUrl; + using (_fullUrlDictionary.GetReadLock()) + { + _fullUrlDictionary.TryGetValue(key, out fullUrl); + } + + if (String.IsNullOrEmpty(fullUrl)) + { + using (_fullUrlDictionary.GetWriteLock()) + { + switch (TabType) + { + case TabType.Normal: + //normal tab + fullUrl = Globals.NavigateURL(TabID, IsSuperTab); + break; + case TabType.Tab: + //alternate tab url + fullUrl = Globals.NavigateURL(Convert.ToInt32(Url)); + break; + case TabType.File: + //file url + fullUrl = Globals.LinkClick(Url, TabID, Null.NullInteger); + break; + case TabType.Url: + //external url + fullUrl = Url; + break; + } + + if (!_fullUrlDictionary.ContainsKey(key)) + { + if (fullUrl != null) + { + _fullUrlDictionary.Add(key, fullUrl.Trim()); + } + } + } + } + + return fullUrl; + } + } + + [XmlIgnore] + public bool TabPermissionsSpecified + { + get { return false; } + } + + [XmlIgnore] + public List TabUrls + { + get + { + return _tabUrls ?? (_tabUrls = (TabID == Null.NullInteger) ? new List() : TestableTabController.Instance.GetTabUrls(TabID, PortalID)); + } + } + + [XmlElement("url")] + public string Url { get; set; } + + [XmlIgnore] + public bool UseBaseFriendlyUrls { get; set; } + + #endregion + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope currentScope, ref bool propertyNotFound) + { + string outputFormat = string.Empty; + if (format == string.Empty) + { + outputFormat = "g"; + } + + string lowerPropertyName = propertyName.ToLower(); + if (currentScope == Scope.NoSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + propertyNotFound = true; + + string result = string.Empty; + bool isPublic = true; + switch (lowerPropertyName) + { + case "tabid": + propertyNotFound = false; + result = (TabID.ToString(outputFormat, formatProvider)); + break; + case "taborder": + isPublic = false; + propertyNotFound = false; + result = (TabOrder.ToString(outputFormat, formatProvider)); + break; + case "portalid": + propertyNotFound = false; + result = (PortalID.ToString(outputFormat, formatProvider)); + break; + case "tabname": + propertyNotFound = false; + result = PropertyAccess.FormatString(LocalizedTabName, format); + break; + case "isvisible": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsVisible, formatProvider)); + break; + case "parentid": + isPublic = false; + propertyNotFound = false; + result = (ParentId.ToString(outputFormat, formatProvider)); + break; + case "level": + isPublic = false; + propertyNotFound = false; + result = (Level.ToString(outputFormat, formatProvider)); + break; + case "iconfile": + propertyNotFound = false; + result = PropertyAccess.FormatString(IconFile, format); + break; + case "iconfilelarge": + propertyNotFound = false; + result = PropertyAccess.FormatString(IconFileLarge, format); + break; + case "disablelink": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(DisableLink, formatProvider)); + break; + case "title": + propertyNotFound = false; + result = PropertyAccess.FormatString(Title, format); + break; + case "description": + propertyNotFound = false; + result = PropertyAccess.FormatString(Description, format); + break; + case "keywords": + propertyNotFound = false; + result = PropertyAccess.FormatString(KeyWords, format); + break; + case "isdeleted": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsDeleted, formatProvider)); + break; + case "url": + propertyNotFound = false; + result = PropertyAccess.FormatString(Url, format); + break; + case "skinsrc": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(SkinSrc, format); + break; + case "containersrc": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(ContainerSrc, format); + break; + case "tabpath": + propertyNotFound = false; + result = PropertyAccess.FormatString(TabPath, format); + break; + case "startdate": + isPublic = false; + propertyNotFound = false; + result = (StartDate.ToString(outputFormat, formatProvider)); + break; + case "enddate": + isPublic = false; + propertyNotFound = false; + result = (EndDate.ToString(outputFormat, formatProvider)); + break; + case "haschildren": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(HasChildren, formatProvider)); + break; + case "refreshinterval": + isPublic = false; + propertyNotFound = false; + result = (RefreshInterval.ToString(outputFormat, formatProvider)); + break; + case "pageheadtext": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(PageHeadText, format); + break; + case "skinpath": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(SkinPath, format); + break; + case "skindoctype": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(SkinDoctype, format); + break; + case "containerpath": + isPublic = false; + propertyNotFound = false; + result = PropertyAccess.FormatString(ContainerPath, format); + break; + case "issupertab": + isPublic = false; + propertyNotFound = false; + result = (PropertyAccess.Boolean2LocalizedYesNo(IsSuperTab, formatProvider)); + break; + case "fullurl": + propertyNotFound = false; + result = PropertyAccess.FormatString(FullUrl, format); + break; + case "sitemappriority": + propertyNotFound = false; + result = PropertyAccess.FormatString(SiteMapPriority.ToString(), format); + break; + } + if (!isPublic && currentScope != Scope.Debug) + { + propertyNotFound = true; + result = PropertyAccess.ContentLocked; + } + return result; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.fullyCacheable; + } + } + + #endregion + + #region Private Methods + + /// + /// Look for skin level doctype configuration file, and inject the value into the top of default.aspx + /// when no configuration if found, the doctype for versions prior to 4.4 is used to maintain backwards compatibility with existing skins. + /// Adds xmlns and lang parameters when appropiate. + /// + /// + /// + /// [cathal] 28/05/2006 Created + /// + private string CheckIfDoctypeConfigExists() + { + string doctypeConfig = string.Empty; + if (!string.IsNullOrEmpty(SkinSrc)) + { + string fileName = HttpContext.Current.Server.MapPath(SkinSrc.Replace(".ascx", ".doctype.xml")); + if (File.Exists(fileName)) + { + try + { + var xmlSkinDocType = new XmlDocument(); + xmlSkinDocType.Load(fileName); + string strDocType = xmlSkinDocType.FirstChild.InnerText; + doctypeConfig = strDocType; + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + } + } + return doctypeConfig; + } + + private void IconFileGetter(ref string iconFile, string iconRaw) + { + if ((!String.IsNullOrEmpty(iconRaw) && iconRaw.StartsWith("~")) || PortalID == Null.NullInteger) + { + iconFile = iconRaw; + } + else if (iconFile == null && !String.IsNullOrEmpty(iconRaw) && PortalID != Null.NullInteger) + { + IFileInfo fileInfo; + if (iconRaw.StartsWith("FileID=", StringComparison.InvariantCultureIgnoreCase)) + { + var fileId = Convert.ToInt32(iconRaw.Substring(7)); + fileInfo = FileManager.Instance.GetFile(fileId); + } + else + { + fileInfo = FileManager.Instance.GetFile(PortalID, iconRaw); + } + + iconFile = fileInfo != null ? FileManager.Instance.GetUrl(fileInfo) : iconRaw; + } + } + + #endregion + + #region Internal Methods + + internal void ClearTabUrls() + { + _tabUrls = null; + } + + #endregion + + #region Public Methods + + public TabInfo Clone() + { + var clonedTab = new TabInfo(_localizedTabNameDictionary, _fullUrlDictionary) + { + TabID = TabID, + TabOrder = TabOrder, + PortalID = PortalID, + TabName = TabName, + IsVisible = IsVisible, + ParentId = ParentId, + Level = Level, + IconFile = _iconFileRaw, + IconFileLarge = _iconFileLargeRaw, + DisableLink = DisableLink, + Title = Title, + Description = Description, + KeyWords = KeyWords, + IsDeleted = IsDeleted, + Url = Url, + SkinSrc = SkinSrc, + ContainerSrc = ContainerSrc, + TabPath = TabPath, + StartDate = StartDate, + EndDate = EndDate, + HasChildren = HasChildren, + SkinPath = SkinPath, + ContainerPath = ContainerPath, + IsSuperTab = IsSuperTab, + RefreshInterval = RefreshInterval, + PageHeadText = PageHeadText, + IsSecure = IsSecure, + PermanentRedirect = PermanentRedirect + }; + + + + + if (BreadCrumbs != null) + { + clonedTab.BreadCrumbs = new ArrayList(); + foreach (TabInfo t in BreadCrumbs) + { + clonedTab.BreadCrumbs.Add(t.Clone()); + } + } + + Clone(clonedTab, this); + + //localized properties + clonedTab.UniqueId = UniqueId; + clonedTab.VersionGuid = VersionGuid; + clonedTab.DefaultLanguageGuid = DefaultLanguageGuid; + clonedTab.LocalizedVersionGuid = LocalizedVersionGuid; + clonedTab.CultureCode = CultureCode; + + clonedTab.Panes = new ArrayList(); + clonedTab.Modules = new ArrayList(); + return clonedTab; + } + + /// ----------------------------------------------------------------------------- + /// + /// Fills a TabInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public override void Fill(IDataReader dr) + { + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + UniqueId = Null.SetNullGuid(dr["UniqueId"]); + VersionGuid = Null.SetNullGuid(dr["VersionGuid"]); + DefaultLanguageGuid = Null.SetNullGuid(dr["DefaultLanguageGuid"]); + LocalizedVersionGuid = Null.SetNullGuid(dr["LocalizedVersionGuid"]); + CultureCode = Null.SetNullString(dr["CultureCode"]); + + TabOrder = Null.SetNullInteger(dr["TabOrder"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + TabName = Null.SetNullString(dr["TabName"]); + IsVisible = Null.SetNullBoolean(dr["IsVisible"]); + ParentId = Null.SetNullInteger(dr["ParentId"]); + Level = Null.SetNullInteger(dr["Level"]); + IconFile = Null.SetNullString(dr["IconFile"]); + IconFileLarge = Null.SetNullString(dr["IconFileLarge"]); + DisableLink = Null.SetNullBoolean(dr["DisableLink"]); + Title = Null.SetNullString(dr["Title"]); + Description = Null.SetNullString(dr["Description"]); + KeyWords = Null.SetNullString(dr["KeyWords"]); + IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]); + Url = Null.SetNullString(dr["Url"]); + SkinSrc = Null.SetNullString(dr["SkinSrc"]); + ContainerSrc = Null.SetNullString(dr["ContainerSrc"]); + TabPath = Null.SetNullString(dr["TabPath"]); + StartDate = Null.SetNullDateTime(dr["StartDate"]); + EndDate = Null.SetNullDateTime(dr["EndDate"]); + HasChildren = Null.SetNullBoolean(dr["HasChildren"]); + RefreshInterval = Null.SetNullInteger(dr["RefreshInterval"]); + PageHeadText = Null.SetNullString(dr["PageHeadText"]); + IsSecure = Null.SetNullBoolean(dr["IsSecure"]); + PermanentRedirect = Null.SetNullBoolean(dr["PermanentRedirect"]); + SiteMapPriority = Null.SetNullSingle(dr["SiteMapPriority"]); + BreadCrumbs = null; + Panes = null; + Modules = null; + } + + public string GetCurrentUrl(string cultureCode) + { + string url = null; + if (_tabUrls != null && _tabUrls.Count > 0) + { + TabUrlInfo tabUrl = _tabUrls.CurrentUrl(cultureCode); + if (tabUrl != null) + { + url = tabUrl.Url; + } + } + return url ?? (""); + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DNN 5.1. All permission checks are done through Permission Collections")] + [XmlIgnore] + public string AdministratorRoles + { + get + { + if (string.IsNullOrEmpty(_administratorRoles)) + { + _administratorRoles = TabPermissions.ToString("EDIT"); + } + return _administratorRoles; + } + set + { + _administratorRoles = value; + } + } + + [Obsolete("Deprecated in DNN 5.1. All permission checks are done through Permission Collections")] + [XmlIgnore] + public string AuthorizedRoles + { + get + { + if (string.IsNullOrEmpty(_authorizedRoles)) + { + _authorizedRoles = TabPermissions.ToString("VIEW"); + } + return _authorizedRoles; + } + set + { + _authorizedRoles = value; + } + } + + [Obsolete("Deprecated in DNN 5.0. The artificial differences between Regular and Admin pages was removed.")] + public bool IsAdminTab + { + get + { + if (IsSuperTab) + { + return true; + } + return false; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Tabs/TabMoveType.cs b/DNN Platform/Library/Entities/Tabs/TabMoveType.cs new file mode 100644 index 00000000000..c9a2f9231b8 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabMoveType.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Tabs +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : TabMoveType + ///----------------------------------------------------------------------------- + /// + /// Identifies common tab move types + /// + /// + /// + ///----------------------------------------------------------------------------- + public enum TabMoveType + { + Up, + Down, + Top, + Bottom, + Promote, + Demote + } +} diff --git a/DNN Platform/Library/Entities/Tabs/TabType.cs b/DNN Platform/Library/Entities/Tabs/TabType.cs new file mode 100644 index 00000000000..ff012dad893 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabType.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Entities.Tabs +{ + public enum TabType + { + File, + Normal, + Tab, + Url, + Member + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Tabs/TabUrlInfo.cs b/DNN Platform/Library/Entities/Tabs/TabUrlInfo.cs new file mode 100644 index 00000000000..4f760000737 --- /dev/null +++ b/DNN Platform/Library/Entities/Tabs/TabUrlInfo.cs @@ -0,0 +1,35 @@ +using System; + +namespace DotNetNuke.Entities.Tabs +{ + /// + ///Class to represent a TabUrl object + /// + [Serializable] //584 support sql session state + public class TabUrlInfo + { + #region Constructors + + public TabUrlInfo() + { + PortalAliasUsage = PortalAliasUsageType.Default; + } + + #endregion + + #region Public Properties + + public string CultureCode { get; set; } + public string HttpStatus { get; set; } + public bool IsSystem { get; set; } + public int PortalAliasId { get; set; } + public PortalAliasUsageType PortalAliasUsage { get; set; } + public string QueryString { get; set; } + public int SeqNum { get; set; } + public int TabId { get; set; } + public string Url { get; set; } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ActionType.cs b/DNN Platform/Library/Entities/Urls/ActionType.cs new file mode 100644 index 00000000000..c53542a5457 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ActionType.cs @@ -0,0 +1,37 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum ActionType + { + IgnoreRequest, + Continue, + Redirect302Now, + Redirect301, + CheckFor301, + Redirect302, + Output404, + Output500 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/AdvancedFriendlyUrlProvider.cs b/DNN Platform/Library/Entities/Urls/AdvancedFriendlyUrlProvider.cs new file mode 100644 index 00000000000..7f0c93e3e84 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/AdvancedFriendlyUrlProvider.cs @@ -0,0 +1,1404 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class AdvancedFriendlyUrlProvider : FriendlyUrlProviderBase + { + + #region Internal Properties + + private FriendlyUrlSettings Settings + { + get + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + return new FriendlyUrlSettings(portalSettings.PortalId) { UrlFormat = "Advanced" }; + } + } + + #endregion + + #region Constructor + + internal AdvancedFriendlyUrlProvider(NameValueCollection attributes) + : base(attributes) + { + } + + #endregion + + #region Overriden methods + + internal override string FriendlyUrl(TabInfo tab, string path) + { + return FriendlyUrl(tab, path, Globals.glbDefaultPage, PortalController.GetCurrentPortalSettings()); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName) + { + return FriendlyUrl(tab, path, pageName, PortalController.GetCurrentPortalSettings()); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings portalSettings) + { + if (portalSettings == null) + { + throw new ArgumentNullException("portalSettings"); + } + return FriendlyUrlInternal(tab, path, pageName, String.Empty, portalSettings); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias) + { + return FriendlyUrlInternal(tab, path, pageName, portalAlias, null); + } + + #endregion + + #region Addvanced Friendly Url Methods + + /// + /// Return a FriendlyUrl for the supplied Tab, but don't improve it past the standard DNN Friendly Url version + /// + internal static string BaseFriendlyUrl(TabInfo tab, string path, string pageName, string httpAlias, FriendlyUrlSettings settings) + { + bool cultureSpecificAlias; + + //Call GetFriendlyAlias to get the Alias part of the url + string friendlyPath = GetFriendlyAlias(path, + ref httpAlias, + tab.PortalID, + settings, + null, + out cultureSpecificAlias); + + //Call GetFriendlyQueryString to get the QueryString part of the url + friendlyPath = GetFriendlyQueryString(tab, friendlyPath, pageName, settings); + + return friendlyPath; + } + + /// + /// Return a full-improved Friendly Url for the supplied tab + /// + /// The current page + /// The non-friendly path to the page + /// The name of the page + /// The current portal alias to use + /// If true, then the Friendly Url will be constructed without using any custom redirects + /// The current Friendly Url Settings to use + /// + /// + public static string ImprovedFriendlyUrl(TabInfo tab, + string path, + string pageName, + string httpAlias, + bool ignoreCustomRedirects, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + List messages; + return ImprovedFriendlyUrlWithMessages(tab, + path, + pageName, + httpAlias, + ignoreCustomRedirects, + settings, + out messages, + parentTraceId); + } + + internal static string ImprovedFriendlyUrlWithMessages(TabInfo tab, + string path, + string pageName, + string httpAlias, + bool ignoreCustomRedirects, + FriendlyUrlSettings settings, + out List messages, + Guid parentTraceId) + { + messages = new List(); + bool cultureSpecificAlias; + + //Call GetFriendlyAlias to get the Alias part of the url + string friendlyPath = GetFriendlyAlias(path, + ref httpAlias, + tab.PortalID, + settings, + new PortalSettings(tab.PortalID), + out cultureSpecificAlias); + + //Call GetFriendlyQueryString to get the QueryString part of the url + friendlyPath = GetFriendlyQueryString(tab, friendlyPath, pageName, settings); + + //ImproveFriendlyUrl will attempt to remove tabid/nn and other information from the Url + //700 : avoid null alias if a tab.portalid / httpAlias mismatch + PortalAliasInfo alias = GetAliasForPortal(httpAlias, tab.PortalID, ref messages); + if (alias != null) + { + var portalSettings = new PortalSettings(tab.TabID, alias); + friendlyPath = ImproveFriendlyUrlWithMessages(tab, + friendlyPath, + pageName, + portalSettings, + ignoreCustomRedirects, + settings, + ref messages, + cultureSpecificAlias, + parentTraceId); + + friendlyPath = ForceLowerCaseIfAllowed(tab, friendlyPath, settings); + } + OutputFriendlyUrlMessages(tab, path, "base/messages", messages, friendlyPath, settings); + return friendlyPath; + } + #endregion + + #region Private Methods + + private static string AddPage(string path, string pageName) + { + string friendlyPath = path; + if (friendlyPath.EndsWith(pageName + "/")) + { + friendlyPath = friendlyPath.TrimEnd('/'); + } + else if (friendlyPath.EndsWith(pageName) == false) + { + if (friendlyPath.EndsWith("/")) + { + friendlyPath = friendlyPath + pageName; + } + else + { + friendlyPath = friendlyPath + "/" + pageName; + } + } + return friendlyPath; + } + + private static void CheckAndUpdatePortalSettingsForNewAlias(PortalSettings portalSettings, bool cultureSpecificAlias, string portalAlias) + { + if (cultureSpecificAlias && portalAlias != portalSettings.PortalAlias.HTTPAlias) + { + //was a change in alias, need to update the portalSettings with a new portal alias + var pac = new PortalAliasController(); + PortalAliasInfo pa = pac.GetPortalAlias(portalAlias, portalSettings.PortalId); + if (pa != null) + { + portalSettings.PortalAlias = pa; + } + } + } + + private static string CheckForDebug(HttpRequest request) + { + string debugValue = ""; + const string debugToken = "_fugdebug"; + //798 : change reference to debug parameters + if (request != null) + { + debugValue = (request.Params.Get("HTTP_" + debugToken.ToUpper())); + } + if (debugValue == null) + { + debugValue = "false"; + } + return debugValue.ToLower(); + } + + private static string CreateFriendlyUrl(string portalAlias, + string newTabPath, + string newPath, + string pageAndExtension, + string newPageName, + string qs, + string langParms, + ref List messages, + bool builtInUrl, + bool changeToSiteRoot, + bool dropLangParms, + bool isHomePage) + { + var finalPathBuilder = new StringBuilder(); + + if (changeToSiteRoot) //no page path if changing to site root because of parameter replacement rule (593) + { + if (newPath.StartsWith("/")) + { + newPath = newPath.Substring(1); + } + + finalPathBuilder.Append(Globals.AddHTTP(portalAlias + "/")); + //don't show lang parms for site-root set values + finalPathBuilder.Append(newPath); + finalPathBuilder.Append(newPageName); + finalPathBuilder.Append(pageAndExtension); + finalPathBuilder.Append(qs); + messages.Add("Using change to site root rule to remove path path: " + newTabPath); + } + else + { + finalPathBuilder.Append(dropLangParms == false + ? Globals.AddHTTP(portalAlias + langParms + "/") + : Globals.AddHTTP(portalAlias + "/")); + + //685 : When final value no longer includes a path, and it's for the home page, don't use the path + // this happens when items are removed from 'newPath' and shifted to 'qs' because of the 'doNotINcludeInPath' regex + // It's true this could be solved by taking the items from the path earlier in the chain (in the original routine that takes them + // from the querystring and includes them in the path), but the intention is to leave the primary friendly url generation similar + // to the original DNN logic, and have all the 'improved' logic in this routine. + if (newPath == "" //no path (no querystring when rewritten) + && (isHomePage && newTabPath == "/") //is the home page, and we're not using 'home' for it + && (langParms == "" || dropLangParms) + //doesn't have any language parms, or we're intentionally getting rid of them + && !builtInUrl) //builtin Url == login, terms, privacy, register + { + //Url is home page, and there's no friendly path to add, so we don't need the home page path (ie, /home is unneeded, just use the site root) + if (newPageName.Length == 0 && pageAndExtension.StartsWith(".")) + { + //when the newPageName isn't specified, and the pageAndExtension is just an extension + //just add the querystring on the end + finalPathBuilder.Append(qs); + } + else + { + finalPathBuilder.Append(newPageName); + finalPathBuilder.Append(pageAndExtension); + finalPathBuilder.Append(qs); + } + } + else + //this is the normal case + { + //finalPath += newTabPath.TrimStart('/') + newPath + newPageName + pageAndExtension + qs; + finalPathBuilder.Append(newTabPath.TrimStart('/')); + finalPathBuilder.Append(newPath); + finalPathBuilder.Append(newPageName); + finalPathBuilder.Append(pageAndExtension); + finalPathBuilder.Append(qs); + } + } + return finalPathBuilder.ToString(); + } + + private static string DetermineExtension(bool isHomePage, string pageName, FriendlyUrlSettings settings) + { + string extension = ""; + if (!isHomePage) //no pageAndExtension for the home page when no query string specified + { + //the ending of the url depends on the current page pageAndExtension settings + if (settings.PageExtensionUsageType == PageExtensionUsageType.AlwaysUse + || settings.PageExtensionUsageType == PageExtensionUsageType.PageOnly) + { + //check whether a 'custom' (other than default.aspx) page was supplied, and insert that as the pageAndExtension + if (String.Compare(pageName, Globals.glbDefaultPage, StringComparison.OrdinalIgnoreCase) != 0) + { + extension = "/" + pageName.Replace(".aspx", settings.PageExtension); + } + else + { + extension = settings.PageExtension; + //default page pageAndExtension + } + } + else + { + if (String.Compare(pageName, Globals.glbDefaultPage, StringComparison.OrdinalIgnoreCase) != 0) + { + //get rid of the .aspx on the page if it was there + extension = "/" + pageName.Replace(".aspx", ""); // +"/"; //610 : don't always end with / + } + else + { + //no pageAndExtension + extension = ""; //610 dont always end with "/"; + } + } + } + return extension; + } + + private static string DeterminePageNameAndExtension(ref string pageName, FriendlyUrlSettings settings) + { + string pageAndExtension; + if (settings.PageExtensionUsageType == PageExtensionUsageType.Never + || settings.PageExtensionUsageType == PageExtensionUsageType.PageOnly) + { + if (pageName != Globals.glbDefaultPage) + { + if (pageName == "Logoff.aspx") + { + pageAndExtension = "/" + pageName; + } + else if (settings.ProcessRequestList != null && + settings.ProcessRequestList.Contains(pageName.ToLower())) + { + pageAndExtension = "/" + pageName; + } + else + { + pageAndExtension = "/" + pageName.Replace(".aspx", ""); //610 + "/"; + //get rid of the .aspx on the page if it was there + } + } + else + { + pageAndExtension = ""; //610 don't end with "/"; + //no pageAndExtension + } + } + else + { + if (pageName != Globals.glbDefaultPage) + { + if (pageName == "Logoff.aspx") + { + pageAndExtension = "/" + pageName; + } + else if (settings.ProcessRequestList != null && + settings.ProcessRequestList.Contains(pageName.ToLower())) + { + pageAndExtension = "/" + pageName; + } + else + { + pageAndExtension = "/" + pageName.Replace(".aspx", settings.PageExtension); + } + } + else + { + pageAndExtension = settings.PageExtension; + //default page extension + } + } + return pageAndExtension; + } + + private string FriendlyUrlInternal(TabInfo tab, string path, string pageName, string portalAlias, PortalSettings portalSettings) + { + Guid parentTraceId = Guid.Empty; + int portalId = (portalSettings != null) ? portalSettings.PortalId : tab.PortalID; + bool cultureSpecificAlias; + var localSettings = Settings; + + //Call GetFriendlyAlias to get the Alias part of the url + if (String.IsNullOrEmpty(portalAlias) && portalSettings != null) + { + portalAlias = portalSettings.PortalAlias.HTTPAlias; + } + string friendlyPath = GetFriendlyAlias(path, + ref portalAlias, + portalId, + localSettings, + portalSettings, + out cultureSpecificAlias); + + if (portalSettings != null) + { + CheckAndUpdatePortalSettingsForNewAlias(portalSettings, cultureSpecificAlias, portalAlias); + } + + if (tab == null && path == "~/" && String.Compare(pageName, Globals.glbDefaultPage, StringComparison.OrdinalIgnoreCase) == 0) + { + //this is a request for the site root for he dnn logo skin object (642) + //do nothing, the friendly alias is already correct - we don't want to append 'default.aspx' on the end + } + else + { + //Get friendly path gets the standard dnn-style friendly path + friendlyPath = GetFriendlyQueryString(tab, friendlyPath, pageName, localSettings); + + if (portalSettings == null) + { + var pac = new PortalAliasController(); + PortalAliasInfo alias = pac.GetPortalAlias(portalAlias, tab.PortalID); + + portalSettings = new PortalSettings(tab.TabID, alias); + } + //ImproveFriendlyUrl will attempt to remove tabid/nn and other information from the Url + friendlyPath = ImproveFriendlyUrl(tab, + friendlyPath, + pageName, + portalSettings, + false, + cultureSpecificAlias, + localSettings, + parentTraceId); + } + //set it to lower case if so allowed by settings + friendlyPath = ForceLowerCaseIfAllowed(tab, friendlyPath, localSettings); + + return friendlyPath; + } + + private static PortalAliasInfo GetAliasForPortal(string httpAlias, int portalId, ref List messages) + { + //if no match found, then call database to find (don't rely on cache for this one, because it is an exception event, not an expected event) + var pac = new PortalAliasController(); + PortalAliasInfo alias = pac.GetPortalAlias(httpAlias, portalId); + if (alias == null) + { + //no match between alias and portal id + var aliasArray = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + if (aliasArray.Count > 0) + { + alias = aliasArray[0]; //nab the first one here + messages.Add("Portal Id " + portalId.ToString() + " does not match http alias " + httpAlias + + " - " + alias.HTTPAlias + " was used instead"); + } + else + { + messages.Add("Portal Id " + portalId.ToString() + + " does not match http alias and no usable alias could be found"); + } + } + return alias; + } + + internal static string GetCultureOfPath(string path) + { + string code = ""; + const string codeRegexPattern = @"(?:\&|\?)language=(?[A-Za-z]{2}-[A-Za-z]{2})"; + MatchCollection matches = Regex.Matches(path, codeRegexPattern); + if (matches.Count > 0) + { + foreach (Match langMatch in matches) + { + if (langMatch.Success) + { + Group langGroup = langMatch.Groups["cc"]; + if (langGroup.Success) + { + code = langGroup.Value; + break; + } + } + } + } + return code; + } + + private static string GetCultureOfSettings(PortalSettings portalSettings) + { + //note! should be replaced with compiled call to portalSettings.CultureCode property when base supported version is increased. + string cultureCode = ""; + PropertyInfo cultureCodePi = portalSettings.GetType().GetProperty("CultureCode"); + if (cultureCodePi != null) + { + cultureCode = (string)cultureCodePi.GetValue(portalSettings, null); + } + return cultureCode; + } + + private static string GetFriendlyAlias(string path, + ref string httpAlias, + int portalId, + FriendlyUrlSettings settings, + PortalSettings portalSettings, + out bool cultureSpecificAlias) + { + cultureSpecificAlias = false; + string friendlyPath = path; + bool done = false; + string httpAliasFull = null; + //this regex identifies if the correct http://portalAlias already is in the path + var portalMatchRegex = new Regex("^http[s]*://" + httpAlias, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + string cultureCode = GetCultureOfPath(path); + if (portalSettings != null) + { + if (portalMatchRegex.IsMatch(path) == false || !String.IsNullOrEmpty(cultureCode)) + { + //get the portal alias mapping for this portal, which tells whether to enforce a primary portal alias or not + PortalSettings.PortalAliasMapping aliasMapping = PortalSettings.GetPortalAliasMappingMode(portalId); + //check to see if we should be specifying this based on the culture code + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + + //799: if there was no culture code in the path and the portal settings culture was supplied, then use that + //essentially we are ignoring the portal alias of the portal settings object and driving the alias from the supplied portal settings culture code + //this is because the calling module cannot be guaranteed to be supplying the right culture Code / portal alias combination. + if (string.IsNullOrEmpty(cultureCode)) + { + cultureCode = GetCultureOfSettings(portalSettings); + //lookup the culture code of the portal settings object + } + var primaryAlias = primaryAliases.GetAliasByPortalIdAndSettings(portalId, null, cultureCode, settings); + + if (primaryAlias != null) + { + if ((aliasMapping == PortalSettings.PortalAliasMapping.Redirect || !String.IsNullOrEmpty(primaryAlias.CultureCode)) + && String.Compare(primaryAlias.HTTPAlias, httpAlias, StringComparison.OrdinalIgnoreCase) != 0) + { + //found the primary alias alias, and it's different from the supplied portal alias + //and the site is using a redirect portal alias mapping + //substitute in the primary Alias for the supplied alias + friendlyPath = friendlyPath.Replace(Globals.AddHTTP(httpAlias), String.Empty); + httpAlias = primaryAlias.HTTPAlias; + if (!string.IsNullOrEmpty(primaryAlias.CultureCode)) + { + cultureSpecificAlias = true; + } + else if (primaryAlias.CultureCode == "") + { + cultureSpecificAlias = true; + //770: hacking this so that a change is forced to portal settings when a non-chosen alias is requested. + } + } + else + { + //check to see if we matched for this alias - if so, it's a culture specific alias + if (String.Compare(primaryAlias.HTTPAlias, httpAlias, StringComparison.OrdinalIgnoreCase) == 0 && + !string.IsNullOrEmpty(primaryAlias.CultureCode)) + { + cultureSpecificAlias = true; + } + } + + //852 : check to see if the skinSrc is explicityl specified, which we don't want to duplicate if the alias also specifies this + if (path.ToLower().Contains("skinsrc=") && primaryAliases.ContainsSpecificSkins()) + { + //path has a skin specified and (at least one) alias has a skin specified + string[] parms = path.Split('&'); + foreach (string parmPair in parms) + { + if (parmPair.ToLower().Contains("skinsrc=")) + { + //splits the key/value pair into a two-element array + string[] keyValue = parmPair.Split('='); + //check to see if it was a full skinsrc=xyz pair + if (keyValue.GetUpperBound(0) >= 1) + { + friendlyPath = path.Replace("&" + parmPair, ""); + } + } + } + } + } + + //the portal alias is not in the path already, so we need to get it in there + if (friendlyPath.StartsWith("~/")) + { + friendlyPath = friendlyPath.Substring(1); + } + if (friendlyPath.StartsWith("/") == false) + { + friendlyPath = "/" + friendlyPath; + } + //should now have a standard /path/path/page.aspx?key=value style of Url + httpAliasFull = Globals.AddHTTP(httpAlias); + + if (HttpContext.Current.Items["UrlRewrite:OriginalUrl"] != null) + { + string originalUrl = HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString(); + //confirming this portal was the original one requested, making all the generated aliases + //for the same portal + Match portalMatch = Regex.Match(originalUrl, "^" + httpAliasFull, + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (portalMatch.Success == false) + { + //Manage the special case where original url contains the alias as + //http://www.domain.com/Default.aspx?alias=www.domain.com/child" + portalMatch = Regex.Match(originalUrl, "^?alias=" + httpAlias, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (portalMatch.Success) + { + friendlyPath = Globals.ResolveUrl(friendlyPath); + done = true; + } + } + } + } + } + else + { + done = true; // well, the friendly path passed in had the right portal alias + } + + if (!done) + { + if (httpAliasFull == null) + { + httpAliasFull = Globals.AddHTTP(httpAlias); + } + friendlyPath = httpAliasFull + friendlyPath; + } + return friendlyPath; + } + + private static string GetFriendlyQueryString(TabInfo tab, string path, string pageName, FriendlyUrlSettings settings) + { + string friendlyPath = path; + Match queryStringMatch = Regex.Match(friendlyPath, "(.[^\\\\?]*)\\\\?(.*)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + string queryStringSpecialChars = ""; + const string defaultPageName = Globals.glbDefaultPage; + if (!ReferenceEquals(queryStringMatch, Match.Empty)) + { + friendlyPath = queryStringMatch.Groups[1].Value; + friendlyPath = Regex.Replace(friendlyPath, defaultPageName, "", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (String.Compare(pageName, defaultPageName, StringComparison.OrdinalIgnoreCase) != 0) + //take out the end page name, it will get re-added + { + friendlyPath = Regex.Replace(friendlyPath, pageName, "", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + string queryString = queryStringMatch.Groups[2].Value.Replace("&", "&"); + if ((queryString.StartsWith("?"))) + { + queryString = queryString.TrimStart('?'); + } + + string[] nameValuePairs = queryString.Split('&'); + for (int i = 0; i <= nameValuePairs.Length - 1; i++) + { + string pathToAppend = ""; + string[] pair = nameValuePairs[i].Split('='); + + var illegalPageNames = new[]{"con", "aux", "nul", "prn"}; + + if (!illegalPageNames.Contains(pair[0].ToLowerInvariant()) && (pair.Length == 1 || !illegalPageNames.Contains(pair[1].ToLowerInvariant()))) + { + //Add name part of name/value pair + if (friendlyPath.EndsWith("/")) + { + if (pair[0].ToLower() == "tabid") //always lowercase the tabid part of the path + { + pathToAppend = pathToAppend + pair[0].ToLower(); + } + else + { + pathToAppend = pathToAppend + pair[0]; + } + } + else + { + pathToAppend = pathToAppend + "/" + pair[0]; + } + + if (pair.Length > 1) + { + if (pair[1].Length > 0) + { + if (Regex.IsMatch(pair[1], settings.RegexMatch) == false) + { + // Contains Non-AlphaNumeric Characters + if (pair[0].ToLower() == "tabid") + { + int tabId; + if (Int32.TryParse(pair[1], out tabId)) + { + if (tab != null && tab.TabID == tabId) + { + if (tab.TabPath != Null.NullString && settings.IncludePageName) + { + if (pathToAppend.StartsWith("/") == false) + { + pathToAppend = "/" + pathToAppend; + } + pathToAppend = tab.TabPath.Replace("//", "/").TrimStart('/').TrimEnd('/') + pathToAppend; + } + } + } + } + if (pair[1].Contains(" ")) + { + if (tab != null && (tab.IsSuperTab || RewriteController.IsAdminTab(tab.PortalID, tab.TabPath, settings))) + { + //741 : check admin paths to make sure they aren't using + encoding + pathToAppend = pathToAppend + "/" + pair[1].Replace(" ", "%20"); + } + else + { + pathToAppend = pathToAppend + "/" + + pair[1].Replace(" ", settings.SpaceEncodingValue); + //625 : replace space with specified url encoding value + } + } + else + { + pathToAppend = pathToAppend + "/" + pair[1]; + } + } + else + { + var valueBuilder = new StringBuilder(pair.GetUpperBound(0)); + string key = pair[0]; + //string value = pair[1]; + valueBuilder.Append(pair[1]); + //if the querystring has been decoded and has a '=' in it, the value will get split more times. Put those back together with a loop. + if (pair.GetUpperBound(0) > 1) + { + for (int j = 2; j <= pair.GetUpperBound(0); j++) + { + valueBuilder.Append("="); + valueBuilder.Append(pair[j]); + } + } + // Rewrite into URL, contains only alphanumeric and the % or space + if (queryStringSpecialChars.Length == 0) + { + queryStringSpecialChars = key + "=" + valueBuilder; + } + else + { + queryStringSpecialChars = queryStringSpecialChars + "&" + key + "=" + valueBuilder; + } + pathToAppend = ""; + } + } + else + { + pathToAppend = pathToAppend + "/" + settings.SpaceEncodingValue; + //625 : replace with specified space encoding value + } + } + } + else + { + if (pair.Length == 2) + { + if (queryStringSpecialChars.Length == 0) + { + queryStringSpecialChars = pair[0] + "=" + pair[1]; + } + else + { + queryStringSpecialChars = queryStringSpecialChars + "&" + pair[0] + "=" + pair[1]; + } + } + } + + friendlyPath = friendlyPath + pathToAppend; + } + } + + if ((queryStringSpecialChars.Length > 0)) + { + return AddPage(friendlyPath, pageName) + "?" + queryStringSpecialChars; + } + return AddPage(friendlyPath, pageName); + } + + private static string ImproveFriendlyUrl(TabInfo tab, + string friendlyPath, + string pageName, + PortalSettings portalSettings, + bool ignoreCustomRedirects, + bool cultureSpecificAlias, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + //older overload does not include informational/debug messages on return + List messages = null; + string url = ImproveFriendlyUrlWithMessages(tab, + friendlyPath, + pageName, + portalSettings, + ignoreCustomRedirects, + settings, + ref messages, + cultureSpecificAlias, + parentTraceId); + + OutputFriendlyUrlMessages(tab, friendlyPath, "base/private", messages, url, settings); + + return url; + } + + private static string ImproveFriendlyUrlWithMessages(TabInfo tab, + string friendlyPath, + string pageName, + PortalSettings portalSettings, + bool ignoreCustomRedirects, + FriendlyUrlSettings settings, + ref List messages, + bool cultureSpecificAlias, + Guid parentTraceId) + { + if (messages == null) + { + messages = new List(); + } + string httpAlias = portalSettings.PortalAlias.HTTPAlias; + //invalid call just return the path + if (tab == null) + { + return friendlyPath; + } + + //no improved friendly urls for super tabs, admin tabs + if ((tab.IsSuperTab || RewriteController.IsAdminTab(tab.PortalID, tab.TabPath, settings)) && settings.FriendlyAdminHostUrls == false) //811 : allow for friendly admin/host urls + { + return friendlyPath; + } + + //655 : no friendly url if matched with regex + if (!string.IsNullOrEmpty(settings.NoFriendlyUrlRegex)) + { + if (Regex.IsMatch(friendlyPath, settings.NoFriendlyUrlRegex, + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + return friendlyPath; + } + } + + string result = friendlyPath; + //821 : new 'CustomOnly' setting which allows keeping base Urls but also using Custom Urls. Basically keeps search friendly + //but allows for customised urls and redirects + bool customOnly = settings.UrlFormat.ToLower() == "customonly"; + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + //determine if an improved friendly Url is wanted at all + if ((settings.UrlFormat.ToLower() == "advanced" || customOnly) && !RewriteController.IsExcludedFromFriendlyUrls(tab, settings, false)) + { + string newTabPath; + string customHttpAlias; + bool isHomePage = TabPathHelper.IsTabHomePage(tab, portalSettings); + //do a regex check on the base friendly Path, to see if there is parameters on the end or not + var tabOnlyRegex = new Regex("[^?]*/tabId/(?\\d+)/" + pageName + @"($|\?(?.+$))", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + if (tabOnlyRegex.IsMatch(friendlyPath)) + { + MatchCollection tabOnlyMatches = tabOnlyRegex.Matches(friendlyPath); + string qs = ""; + if (tabOnlyMatches.Count > 0) + { + Match rgxMatch = tabOnlyMatches[0]; + if (rgxMatch.Groups["qs"] != null && rgxMatch.Groups["qs"].Success) + { + qs = "?" + rgxMatch.Groups["qs"].Value; + } + } + bool dropLangParms; + //736: observe the culture code of the tab + string cultureCode = tab.CultureCode; + bool isDefaultLanguage = false; + if (cultureCode == "") + { + cultureCode = portalSettings.DefaultLanguage; + isDefaultLanguage = true; + //751 when using the default culture code, the redirect doesn't need an explicit language + } + bool isCustomUrl; + newTabPath = TabPathHelper.GetTabPath(tab, + settings, + options, + ignoreCustomRedirects, + true, + isHomePage, + cultureCode, + isDefaultLanguage, + false, + out dropLangParms, + out customHttpAlias, + out isCustomUrl, + parentTraceId); + //770 : custom http alias found, merge into overall result + if (!string.IsNullOrEmpty(customHttpAlias)) + { + httpAlias = customHttpAlias; + messages.Add("Uses page-specific alias: " + customHttpAlias); + } + + //it is a straight page.aspx reference, with just the tabid to specify parameters, so get the extension that should be used (no pagename is used by design) + string extension = customHttpAlias != null && newTabPath == "" + ? "" + : DetermineExtension(isHomePage, pageName, settings); + + if (customOnly && isCustomUrl || customOnly == false) + { + result = Globals.AddHTTP(httpAlias + "/" + newTabPath.TrimStart('/') + extension) + qs; + } + } + else + { + //When the home page is requested with a querystring value, the path for the home page is included. This is because path items without the home page + //qualifier are incorrectly checked for as dnn pages, and will result in a 404. Ie domain.com/key/value will fail looking for a DNN path called 'key/value'. + //This gets around the problem because it places the path aas /home/key/value - which correctly identifies the tab as '/Home' and the key/value parameters as + // &key=value. + + //there are parameters on the base friendly url path, so split them off and process separately + //this regex splits the incoming friendly path pagename/tabid/56/default.aspx into the non-tabid path, and individual parms for each /parm/ in the friendly path + //550 : add in \. to allow '.' in the parameter path. + //667 : allow non-word characters (specifically %) in the path + var rgx = new Regex(@"[^?]*(?/tabId/(?\d+))(?(?(?:(?:/[^/?]+){1})+))(?:/" + pageName + @")(?:$|\?(?.+$))", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + MatchCollection matches = rgx.Matches(friendlyPath); + if (matches.Count > 0) + { + //it is a friendly url with other parameters in it + //format it up with the parameters in the end, keeping the same page name + //find the first param name in the params of the Url (the first path piece after the tabid/nn/ value) + Match rgxMatch = matches[0]; + bool hasParms = false; + string cultureCode = null; + string defaultCode = null; + string newPageName = ""; + string newPath = ""; + string qs = ""; + string langParms = ""; + //check we matched on some parms in the path + if (rgxMatch.Groups["parms"] != null && rgxMatch.Groups["parms"].Success) + { + if (rgxMatch.Groups["parms"].Captures.Count > 0) + { + hasParms = true; + newPath = rgxMatch.Groups["path"].Value; + qs = rgxMatch.Groups["qs"].Value; + Match langMatch = Regex.Match(newPath, "/language/(?.[^/]+)(?:/|$)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (langMatch.Success) + { + //a language specifier parameter is in the string + //this is always the last parameter in the list, which + //gives nasty pagename results, so shift the language query to before the page name + // ie home/tabid/66/language/en-us/default.aspx will give home/language/en-us.aspx + // we really want language/en-us/home.aspx + langParms = langMatch.Value; + langParms = langParms.TrimEnd('/'); + newPath = newPath.Replace(langParms, ""); + cultureCode = langMatch.Groups["code"].Value; + //obtain the culture code for this language + defaultCode = portalSettings.DefaultLanguage; + } + else + { + //no language settings, use default + cultureCode = portalSettings.DefaultLanguage; + defaultCode = cultureCode; + } + } + } + bool dropLangParms; + //determine if we allow the home page to be shown as the site root. This is if : + //cultureCode = default culture, newPath is blank after removing languageParms + //allow site root for home page if it is the default culture and no other path items, or there is a specific alias for this culture and there are no other path items + bool homePageSiteRoot = (cultureCode == defaultCode && newPath == "") || (cultureSpecificAlias && newPath == ""); + bool hasPath = (newPath != ""); + + //871 : case insensitive comparison for culture + bool isDefaultLanguage = (String.Compare(cultureCode, defaultCode, StringComparison.OrdinalIgnoreCase) == 0); + bool isCustomUrl; + newTabPath = TabPathHelper.GetTabPath(tab, + settings, + options, + ignoreCustomRedirects, + homePageSiteRoot, + isHomePage, + cultureCode, + isDefaultLanguage, + hasPath, + out dropLangParms, + out customHttpAlias, + out isCustomUrl, + parentTraceId); + if (hasParms) + { + bool changeToSiteRoot = false; + + //remove any parts of the path excluded by regex + RemoveExcludedPartsOfPath(settings, ref newPath, ref qs); + if (newPath == "" && isHomePage) + { + //956 : recheck the test for the homePagebeing a site root Url + homePageSiteRoot = (cultureCode == defaultCode && newPath == "") || (cultureSpecificAlias && newPath == ""); + hasPath = (newPath != ""); + if (homePageSiteRoot) + { + //special case - if the newPath is empty after removing the parameters, and it is the home page, and the home page is only to show the site root + //then re-get the home page Url with no params (hasPath=false) + //done like this to re-run all rules relating the url + newTabPath = TabPathHelper.GetTabPath(tab, + settings, + options, + ignoreCustomRedirects, + homePageSiteRoot, + isHomePage, + cultureCode, + isDefaultLanguage, + hasPath, + out dropLangParms, + out customHttpAlias, + out isCustomUrl, + parentTraceId); + } + } + + //check for parameter regex replacement + string changedPath = String.Empty; + bool allowOtherParameters = false; + if (FriendlyUrlPathController.CheckUserProfileReplacement(newPath, + tab, + portalSettings, + settings, + options, + out changedPath, + out changeToSiteRoot, + out allowOtherParameters, + ref messages, + parentTraceId)) + { + messages.Add("User Profile Replacement: Old Path=" + newPath + "; Changed Path=" + changedPath); + newPath = changedPath; + } + + //transform is ctl/privacy, ctl/login etc + bool builtInUrl = TransformStandardPath(ref newPath, ref newTabPath); + + //770 : custom http alias found, merge into overall result (except if builtin url, which don't get to use custom aliases) + //820 : allow for custom http aliases for builtin urls as well (reverses 770). Otherwise, can't log in to other aliases. + if (!string.IsNullOrEmpty(customHttpAlias)) + { + httpAlias = customHttpAlias; + messages.Add("Uses page-specific alias: " + customHttpAlias); + } + + if (allowOtherParameters) + { + //738 : check for transformation by module specific provider + //894 : allow module providers to be disabled + bool customModuleUrl = false; + if (settings.EnableCustomProviders) + { + customModuleUrl = ExtensionUrlProviderController.GetUrlFromExtensionUrlProviders(portalSettings.PortalId, + tab, + settings, + newPath, + cultureCode, + ref pageName, + out changedPath, + out changeToSiteRoot, + ref messages, + parentTraceId); + } + //when no custom module Urls, check for any regex replacements by way of the friendlyurlparms.config file + if (!customModuleUrl) + { + if (FriendlyUrlPathController.CheckParameterRegexReplacement(newPath, + tab, + settings, + portalSettings.PortalId, + out changedPath, + ref messages, + out changeToSiteRoot, + parentTraceId)) + { + newPath = changedPath; + } + } + else + { + //update path value with custom Url returned from module provider(s) + newPath = changedPath; + } + } + + //start constructing the url + //get the page and extension + //770 : when using a custom http alias, and there is no Url for that path, there's no extension regardless of settings + //because it's treated like a site root (quasi home page if you like) + string pageAndExtension = customHttpAlias != null && newTabPath == "" + ? "" + : DeterminePageNameAndExtension(ref pageName, settings); + //prepend querystring qualifier if necessary + qs = !string.IsNullOrEmpty(qs) ? "?" + qs : ""; + + //string it all together + if (!dropLangParms) + { + //871 : case insensitive culture comparisons + //drop the language parameters when the defaultCode is the cultureCode for this Url, or the portal alias defines the culture code + dropLangParms = isDefaultLanguage || cultureSpecificAlias; + // (defaultCode.ToLower() == cultureCode.ToLower()) || cultureSpecificAlias; + } + string finalPath = CreateFriendlyUrl(httpAlias, + newTabPath, + newPath, + pageAndExtension, + newPageName, + qs, + langParms, + ref messages, + builtInUrl, + changeToSiteRoot, + dropLangParms, + isHomePage); + + //702: look for _aumdebug=true|false and remove if so - never want it part of the output friendly url path + finalPath = Regex.Replace(finalPath, "/_aumdebug/(?:true|false)", ""); + + //'and we're done! + if (customOnly && isCustomUrl || customOnly == false || builtInUrl) + { + result = Globals.AddHTTP(finalPath); + } + } + } + else + { + var re = new Regex("[^?]*/tabId/(\\d+)/ctl/([A-Z][a-z]+)/" + pageName + "$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if ((re.IsMatch(friendlyPath))) + { + Match sesMatch = re.Match(friendlyPath); + if ((sesMatch.Groups.Count > 2)) + { + switch (sesMatch.Groups[2].Value.ToLower()) + { + case "terms": + result = Globals.AddHTTP(httpAlias + "/" + sesMatch.Groups[2].Value + ".aspx"); + break; + case "privacy": + result = Globals.AddHTTP(httpAlias + "/" + sesMatch.Groups[2].Value + ".aspx"); + break; + case "login": + result = Globals.AddHTTP(httpAlias + "/" + sesMatch.Groups[2].Value + ".aspx"); + break; + case "register": + result = Globals.AddHTTP(httpAlias + "/" + sesMatch.Groups[2].Value + ".aspx"); + break; + default: + result = friendlyPath; + break; + } + } + } + } + } + } + return result; + } + + private static void OutputFriendlyUrlMessages(TabInfo tab, + string path, + string method, + List messages, + string resultUrl, + FriendlyUrlSettings settings) + { + if (settings != null && settings.AllowDebugCode && HttpContext.Current != null) + { + HttpRequest request = HttpContext.Current.Request; + string debugCheck = CheckForDebug(request); + if (debugCheck != "" && debugCheck != "false") + { + int id = DateTime.Now.Millisecond; + //append the friendly url headers + HttpResponse response = HttpContext.Current.Response; + string msgId = id.ToString("000"); + int tabId = -1; + string tabName = "null"; + if (tab != null) + { + tabId = tab.TabID; + tabName = tab.TabName; + } + msgId += "-" + tabId.ToString("000"); + + if (messages != null && messages.Count > 0) + { + response.AppendHeader("X-Friendly-Url-" + msgId + ".00", + "Messages for Tab " + tabId.ToString() + ", " + tabName + ", " + path + " calltype:" + method); + + int i = 1; + foreach (string msg in messages) + { + response.AppendHeader("X-Friendly-Url-" + msgId + "." + i.ToString("00"), msg); + i++; + } + if (resultUrl != null) + { + response.AppendHeader("X-Friendly-Url-" + msgId + ".99", + "Path : " + path + " Generated Url : " + resultUrl); + } + } + else + { + if (debugCheck == "all") + { + response.AppendHeader("X-Friendly-Url-" + msgId + ".00", + "Path : " + path + " Generated Url: " + resultUrl); + } + } + } + } + } + + + private static void RemoveExcludedPartsOfPath(FriendlyUrlSettings settings, ref string newPath, ref string qs) + { + if (!string.IsNullOrEmpty(newPath)) //if no path, no point in checking + { + //661 : separate out querystring items if regex match is made + //string path = rgxMatch.Groups["path"].Value; //work with newPath, not path, in case of language parms + if (!string.IsNullOrEmpty(settings.DoNotIncludeInPathRegex)) + { + //inspect each path for an item which should be in the querystring, not in the path + var notInPath = new Regex(settings.DoNotIncludeInPathRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (notInPath.IsMatch(newPath)) + { + MatchCollection pathMatches = notInPath.Matches(newPath); + //remove the part from the path + string removedPath = notInPath.Replace(newPath, ""); + //new replace the removedPath in the main 'newPath' value + newPath = newPath.Replace(newPath, removedPath); + //this prior line replaces the original path (ie key/value/k2/v2) in the overall page path (ie tabid/56/key/value/k2/v2) with + //the original path less the items identified in the regex (ie, remove k2/v2) : leaving tabid/56/key/value + //then, those identified path items are returned to the querystring ?k2=v2 + var qsValueBuilder = new StringBuilder(); + foreach (Match pathMatch in pathMatches) + { + if (pathMatch.Value != "") + { + //return to querystring + string[] parts = pathMatch.Value.Split('/'); //split up the matching path + bool even = true; + foreach (string part in parts) + { + if (part != "") //ignore empty parts, generally caused by the split function + { + if (even) //if even, forms the key part of a querystring key/value pair + { + if (qsValueBuilder.Length == 0) //not yet started + { + qsValueBuilder.Append(part); + } + else + { + qsValueBuilder.Append("&"); + qsValueBuilder.Append(part); + } + } + else + { + //if odd, forms the value part + qsValueBuilder.Append("="); + qsValueBuilder.Append(part); + } + even = !even; + } + } + } + } + //now stick the querystring bit back onto the querystring part of this procedure + if (string.IsNullOrEmpty(qs)) + { + qs = qsValueBuilder.ToString(); + } + else + { + qsValueBuilder.Insert(0, "&"); //start with & character + //910: append rather than replace + qs += qsValueBuilder.ToString(); + } + } + } + } + } + + private static bool TransformStandardPath(ref string newPath, ref string newTabPath) + { + //615 : output simple urls for login, privacy, register and terms urls + bool builtInUrl = false; + if (newPath != "/" && newPath != "" && "/ctl/privacy|/ctl/login|/ctl/register|/ctl/terms".Contains(newPath.ToLower())) + { + builtInUrl = true; + switch (newPath.ToLower()) + { + case "/ctl/privacy": + newTabPath = "Privacy"; + newPath = newPath.ToLower().Replace("/ctl/privacy", ""); + break; + case "/ctl/login": + newTabPath = "Login"; + newPath = newPath.ToLower().Replace("/ctl/login", ""); + break; + case "/ctl/register": + newTabPath = "Register"; + newPath = newPath.ToLower().Replace("/ctl/register", ""); + break; + case "/ctl/terms": + newTabPath = "Terms"; + newPath = newPath.ToLower().Replace("/ctl/terms", ""); + break; + } + } + return builtInUrl; + } + + #endregion + + #region Internal Methods + + internal static string ForceLowerCaseIfAllowed(TabInfo tab, string url, FriendlyUrlSettings settings) + { + //606 : include regex to stop lower case in certain circumstances + //840 : change to re-introduce lower case restrictions on admin / host tabs + if (tab != null) + { + if (!RewriteController.IsAdminTab(tab.PortalID, tab.TabPath, settings)) + { + bool forceLowerCase = (settings.ForceLowerCase); + if (forceLowerCase) + { + if (!string.IsNullOrEmpty(settings.ForceLowerCaseRegex)) + { + forceLowerCase = !Regex.IsMatch(url, settings.ForceLowerCaseRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + } + if (forceLowerCase) + { + //don't force lower case for Urls excluded from being 'friendly' + forceLowerCase = (!RewriteController.IsExcludedFromFriendlyUrls(tab, settings, false)); + } + + if (forceLowerCase) + { + url = url.ToLower(); + } + } + } + return url; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/AdvancedUrlRewriter.cs b/DNN Platform/Library/Entities/Urls/AdvancedUrlRewriter.cs new file mode 100644 index 00000000000..dade7103d58 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/AdvancedUrlRewriter.cs @@ -0,0 +1,2794 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.Configuration; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Framework; +using DotNetNuke.Services.EventQueue; + +using Assembly = System.Reflection.Assembly; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class AdvancedUrlRewriter : UrlRewriterBase + { + #region Private Members + + private const string _productName = "AdvancedUrlRewriter"; + private FriendlyUrlSettings _settings; + internal static readonly Regex ServiceApi = new Regex(@"DesktopModules/.+/API", RegexOptions.Compiled); + + #endregion + + #region Overridden Methods + + internal override void RewriteUrl(object sender, EventArgs e) + { + Guid parentTraceId = Guid.Empty; + const bool debug = true; + bool failedInitialization = false; + bool ignoreForInstall = false; + var app = (HttpApplication) sender; + try + { + //875 : completely ignore install/upgrade requests immediately + ignoreForInstall = IgnoreRequestForInstall(app.Request); + + if (ignoreForInstall == false) + { + _settings = new FriendlyUrlSettings(-1); + + SecurityCheck(app); + } + + } + catch (Exception ex) + { + //exception handling for advanced Url Rewriting requests + failedInitialization = true; + DotNetNuke.Services.Exceptions.Exceptions.LogException(ex); + if (app.Context != null) + { + ShowDebugData(app.Context, app.Request.Url.AbsoluteUri, null, ex); + Handle404OrException(_settings, app.Context, ex, null, false, debug); + } + else + { + throw; + } + } + if (!failedInitialization && !ignoreForInstall) + { + //if made it through there and not installing, go to next call. Not in exception catch because it implements it's own top-level exception handling + var request = app.Context.Request; + + //829 : change constructor to stop using physical path + var result = new UrlAction(request) + { + IsSecureConnection = request.IsSecureConnection, + IsSSLOffloaded = IsSSLOffloadEnabled(request), + RawUrl = request.RawUrl + }; + ProcessRequest(app.Context, + app.Context.Request.Url, + Host.Host.UseFriendlyUrls, + result, + _settings, + true, + parentTraceId); + } + } + + #endregion + + #region Public Methods + + public void ProcessTestRequestWithContext(HttpContext context, + Uri requestUri, + bool useFriendlyUrls, + UrlAction result, + FriendlyUrlSettings settings) + { + Guid parentTraceId = Guid.Empty; + _settings = settings; + ProcessRequest(context, + requestUri, + useFriendlyUrls, + result, + settings, + false, + parentTraceId); + } + + #endregion + + #region Private Methods + + private PortalAliasInfo GetPortalAlias(FriendlyUrlSettings settings, string requestUrl, out bool redirectAlias, out bool isPrimaryAlias, out string wrongAlias) + { + PortalAliasInfo alias = null; + redirectAlias = false; + wrongAlias = null; + isPrimaryAlias = false; + OrderedDictionary portalRegexes = TabIndexController.GetPortalAliasRegexes(settings); + foreach (string regexPattern in portalRegexes.Keys) + { + //split out the portal alias from the regex pattern representing that alias + Match aliasMatch = Regex.Match(requestUrl, regexPattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (aliasMatch.Success) + { + //check for mobile browser and matching + var aliasEx = (PortalAliasInfo)portalRegexes[regexPattern]; + redirectAlias = aliasEx.Redirect; + if (redirectAlias) + { + wrongAlias = aliasMatch.Groups["alias"].Value; + } + isPrimaryAlias = aliasEx.IsPrimary; + alias = aliasEx; + break; + } + } + return alias; + } + + private void ProcessRequest(HttpContext context, + Uri requestUri, + bool useFriendlyUrls, + UrlAction result, + FriendlyUrlSettings settings, + bool allowSettingsChange, + Guid parentTraceId) + { + bool finished = false; + bool showDebug = false; + bool postRequest = false; + + HttpRequest request = context.Request; + HttpResponse response = context.Response; + string requestType = request.RequestType; + NameValueCollection queryStringCol = request.QueryString; + + try + { + + string fullUrl, querystring; + //699: get the full url based on the request and the quersytring, rather than the requestUri.ToString() + //there is a difference in encoding, which can corrupt results when an encoded value is in the querystring + RewriteController.GetUrlWithQuerystring(request, requestUri, out fullUrl, out querystring); + + showDebug = CheckForDebug(request, queryStringCol, settings.AllowDebugCode); + string ignoreRegex = settings.IgnoreRegex; + bool ignoreRequest = IgnoreRequest(result, fullUrl, ignoreRegex, request); + bool redirectAlias = false; + if (!ignoreRequest) + { + //set original path + context.Items["UrlRewrite:OriginalUrl"] = requestUri.AbsoluteUri; + + //set the path of the result object, and determine if a redirect is allowed on this request + result.SetOriginalPath(requestUri.ToString(), settings); + //737 : set the mobile browser + result.SetBrowserType(request, response, settings); + //add to context + context.Items["UrlRewrite:BrowserType"] = result.BrowserType.ToString(); + + //839 : split out this check + result.SetRedirectAllowed(result.OriginalPath, settings); + + //find the portal alias first + string wrongAlias; + bool isPrimaryAlias; + var requestedAlias = GetPortalAlias(settings, fullUrl, out redirectAlias, out isPrimaryAlias, out wrongAlias); + + if (requestedAlias != null) + { + //827 : now get the correct settings for this portal (if not a test request) + //839 : separate out redirect check as well and move above first redirect test (ConfigurePortalAliasRedirect) + if (allowSettingsChange) + { + settings = new FriendlyUrlSettings(requestedAlias.PortalID); + result.SetRedirectAllowed(result.OriginalPath, settings); + } + result.PortalAlias = requestedAlias; + result.PrimaryAlias = requestedAlias;//this is the primary alias + result.PortalId = requestedAlias.PortalID; + result.CultureCode = requestedAlias.CultureCode; + //get the portal alias mapping for this portal + result.PortalAliasMapping = PortalSettings.GetPortalAliasMappingMode(requestedAlias.PortalID); + + //if requested alias wasn't the primary, we have a replacement, redirects are allowed and the portal alias mapping mode is redirect + //then do a redirect based on the wrong portal + if ((redirectAlias && wrongAlias != null) && result.RedirectAllowed && result.PortalAliasMapping != PortalSettings.PortalAliasMapping.Redirect) + { + //this is the alias, we are going to enforce it as the primary alias + result.PortalAlias = requestedAlias; + result.PrimaryAlias = requestedAlias; + //going to redirect this alias because it is incorrect + //or do we just want to mark as 'check for 301??' + redirectAlias = ConfigurePortalAliasRedirect(ref result, + wrongAlias, + requestedAlias.HTTPAlias, + false, + settings.InternalAliasList, + settings); + } + else + { + //do not redirect the wrong alias, but set the primary alias value + if (wrongAlias != null) + { + //get the portal alias info for the requested alias (which is the wrong one) + //and set that as the alias, but also set the found alias as the primary + PortalAliasInfo wrongAliasInfo = PortalAliasController.GetPortalAliasInfo(wrongAlias); + if (wrongAliasInfo != null) + { + result.PortalAlias = wrongAliasInfo; + result.PrimaryAlias = requestedAlias; + } + + } + } + } + } + ignoreRegex = settings.IgnoreRegex; + ignoreRequest = IgnoreRequest(result, fullUrl, ignoreRegex, request); + if (!ignoreRequest) + { + //check to see if a post request + if (request.RequestType == "POST") + { + postRequest = true; + } + + //check the portal alias again. This time, in more depth now that the portal Id is known + //this check handles browser types/language specific aliases & mobile aliases + string primaryHttpAlias; + if (!redirectAlias && IsPortalAliasIncorrect(context, request, requestUri, result, queryStringCol, settings, parentTraceId, out primaryHttpAlias)) + { + //it was an incorrect alias + PortalAliasInfo primaryAlias = PortalAliasController.GetPortalAliasInfo(primaryHttpAlias); + if (primaryAlias != null) result.PrimaryAlias = primaryAlias; + //try and redirect the alias if the settings allow it + redirectAlias = RedirectPortalAlias(primaryHttpAlias, ref result, settings); + } + + if (redirectAlias) + { + //not correct alias for portal : will be redirected + //perform a 301 redirect if one has already been found + response.Status = "301 Moved Permanently"; + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.AddHeader("Location", result.FinalUrl); + finished = true; + } + if (!finished) + { + //Check to see if this to be rewritten into default.aspx?tabId=nn format + //this call is the main rewriting matching call. It makes the decision on whether it is a + //physical file, whether it is toe be rewritten or redirected by way of a stored rule + + //Check if we have a standard url + var uri = new Uri(fullUrl); + if (uri.PathAndQuery.ToLowerInvariant().StartsWith("/" + Globals.glbDefaultPage.ToLowerInvariant())) + { + result.DoRewrite = true; + result.Action = ActionType.CheckFor301; + result.RewritePath = Globals.glbDefaultPage + uri.Query; + } + else + { + bool isPhysicalResource; + CheckForRewrite(fullUrl, querystring, result, useFriendlyUrls, queryStringCol, settings, out isPhysicalResource, parentTraceId); + } + + //return 404 if there is no portal alias for a rewritten request + if (result.DoRewrite && result.PortalAlias == null) + { + //882 : move this logic in from where it was before to here + //so that non-rewritten requests don't trip over it + //no portal alias found for the request : that's a 404 error + result.Action = ActionType.Output404; + result.Reason = RedirectReason.No_Portal_Alias; + + Handle404OrException(settings, context, null, result, false, showDebug); + finished = true; //cannot fulfil request unless correct portal alias specified + } + } + + if (!finished && result.DoRewrite) + { + //check the identified portal alias details for any extra rewrite information required + //this includes the culture and the skin, which can be placed into the rewrite path + //This logic is here because it will catch any Urls which are excluded from rewriting + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + + if (result.PortalId > -1 && result.HttpAlias != null) + { + string culture; + string skin; + BrowserTypes browserType; + primaryAliases.GetSettingsByPortalIdAndAlias(result.PortalId, result.HttpAlias, + out culture, + out browserType, + out skin); + //add language code to path if it exists (not null) and if it's not already there + string rewritePath = result.RewritePath; + if (RewriteController.AddLanguageCodeToRewritePath(ref rewritePath, culture)) + { + result.CultureCode = culture; + } + + //852: add skinSrc to path if it exists and if it's not already there + string debugMessage; + RewriteController.AddSkinToRewritePath(result.TabId, result.PortalId, ref rewritePath, skin, out debugMessage); + result.RewritePath = rewritePath; //reset back from ref temp var + if (debugMessage != null) + { + result.DebugMessages.Add(debugMessage); + } + } + } + + if (!finished && result.DoRewrite) + { + //if so, do the rewrite + if (result.RewritePath.StartsWith(result.Scheme) || result.RewritePath.StartsWith(Globals.glbDefaultPage) == false) + { + if (result.RewritePath.Contains(Globals.glbDefaultPage) == false) + { + RewriterUtils.RewriteUrl(context, "~/" + result.RewritePath); + } + else + { + RewriterUtils.RewriteUrl(context, result.RewritePath); + } + } + else + { + RewriterUtils.RewriteUrl(context, "~/" + result.RewritePath); + } + } + + //confirm which portal the request is for + if (!finished) + { + IdentifyPortalAlias(context, request, requestUri, result, queryStringCol, settings, parentTraceId); + if (result.Action == ActionType.Redirect302Now) + { + //performs a 302 redirect if requested + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl, false); + finished = true; + } + else + { + if (result.Action == ActionType.Redirect301 && !string.IsNullOrEmpty(result.FinalUrl)) + { + finished = true; + //perform a 301 redirect if one has already been found + response.Status = "301 Moved Permanently"; + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.AddHeader("Location", result.FinalUrl); + } + } + } + //look for a 404 result from the rewrite, because of a deleted page or rule + if (!finished && result.Action == ActionType.Output404) + { + if (result.DomainName == result.HttpAlias && result.PortalAlias != null + && result.Reason != RedirectReason.Deleted_Page && result.Reason != RedirectReason.Disabled_Page) + { + //Request for domain with no page identified (and no home page set in Site Settings) + result.Action = ActionType.Continue; + } + else + { + finished = true; + response.AppendHeader("X-Result-Reason", result.Reason.ToString().Replace("_", " ")); + + if (showDebug) + { + ShowDebugData(context, requestUri.AbsoluteUri, result, null); + } + //show the 404 page if configured + result.Reason = RedirectReason.Requested_404; + Handle404OrException(settings, context, null, result, true, showDebug); + } + } + + if (!finished) + { + //check to see if this tab has an external url that should be forwared or not + finished = CheckForTabExternalForwardOrRedirect(context, ref result, response, settings, parentTraceId); + } + + //check for a parameter redirect (we had to do all the previous processing to know we are on the right portal and identify the tabid) + //if the CustomParmRewrite flag is set, it means we already rewrote these parameters, so they have to be correct, and aren't subject to + //redirection. The only reason to do a custom parm rewrite is to interpret already-friendly parameters + if (!finished + && !postRequest /* either request is null, or it's not a post - 551 */ + && result.HttpAlias != null /* must have a http alias */ + && !result.CustomParmRewrite && /* not custom rewritten parms */ + ((settings.EnableCustomProviders && + RedirectController.CheckForModuleProviderRedirect(requestUri, ref result, queryStringCol, settings, parentTraceId)) + //894 : allow disable of all custom providers + || + RedirectController.CheckForParameterRedirect(requestUri, ref result, queryStringCol, settings))) + { + //301 redirect to new location based on parameter match + if (response != null) + { + switch (result.Action) + { + case ActionType.Redirect301: + response.Status = "301 Moved Permanently"; + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.AddHeader("Location", result.FinalUrl); + break; + case ActionType.Redirect302: + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl); + break; + case ActionType.Output404: + response.AppendHeader("X-Result-Reason", result.Reason.ToString().Replace("_", " ")); + Handle404OrException(settings, context, null, result, true, showDebug); + break; + } + } + finished = true; + } + + if (!finished) + { + //add the portal settings to the app context if the portal alias has been found and is correct + if (result.PortalId != -1 && result.PortalAlias != null) + { + Globals.SetApplicationName(result.PortalId); + // load the PortalSettings into current context + var portalSettings = new PortalSettings(result.TabId, result.PortalAlias); + //set the primary alias if one was specified + if (result.PrimaryAlias != null) portalSettings.PrimaryAlias = result.PrimaryAlias; + + if (result.CultureCode != null && fullUrl.Contains(result.CultureCode) && + portalSettings.DefaultLanguage == result.CultureCode) + { + //when the request culture code is the same as the portal default, check for a 301 redirect, because we try and remove the language from the url where possible + result.Action = ActionType.CheckFor301; + } + + int portalHomeTabId = portalSettings.HomeTabId; + if (context != null && portalSettings != null && !context.Items.Contains("PortalSettings")) + { + context.Items.Add("PortalSettings", portalSettings); + } + //check if a secure redirection is needed + //this would be done earlier in the piece, but need to know the portal settings, tabid etc before processing it + bool redirectSecure = CheckForSecureRedirect(portalSettings, requestUri, result, queryStringCol, settings); + if (redirectSecure) + { + if (response != null) + { + //702 : don't check final url until checked for null reference first + if (result.FinalUrl != null) + { + if (result.FinalUrl.StartsWith("https://")) + { + if (showDebug) + { + /* + string debugMsg = "{0}, {1}, {2}, {3}, {4}"; + string productVer = System.Reflection.Assembly.GetExecutingAssembly().GetName(false).Version.ToString(); + response.AppendHeader("X-" + prodName + "-Debug", string.Format(debugMsg, requestUri.AbsoluteUri, result.FinalUrl, result.RewritePath, result.Action, productVer)); + */ + ShowDebugData(context, fullUrl, result, null); + } + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl, false); + finished = true; + } + else + { + if (settings.SSLClientRedirect) + { + //redirect back to http version, use client redirect + response.Clear(); + // add a refresh header to the response + response.AddHeader("Refresh", "0;URL=" + result.FinalUrl); + // add the clientside javascript redirection script + response.Write(""); + response.Write(@""); + response.Write(""); + if (showDebug) + { + /* + string debugMsg = "{0}, {1}, {2}, {3}, {4}"; + string productVer = System.Reflection.Assembly.GetExecutingAssembly().GetName(false).Version.ToString(); + response.AppendHeader("X-" + prodName + "-Debug", string.Format(debugMsg, requestUri.AbsoluteUri, result.FinalUrl, result.RewritePath, result.Action, productVer)); + */ + ShowDebugData(context, fullUrl, result, null); + } + // send the response + //891 : reinstate the response.end to stop the entire page loading + response.End(); + finished = true; + } + else + { + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl, false); + finished = true; + } + } + } + } + } + else + { + //check for, and do a 301 redirect if required + if (CheckForRedirects(requestUri, fullUrl, queryStringCol, result, requestType, settings, portalHomeTabId)) + { + if (response != null) + { + if (result.Action == ActionType.Redirect301) + { + response.Status = "301 Moved Permanently"; + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.AddHeader("Location", result.FinalUrl); + finished = true; + } + else if (result.Action == ActionType.Redirect302) + { + response.AppendHeader("X-Redirect-Reason", result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl, false); + finished = true; + } + } + } + else + { + //612 : Don't clear out a 302 redirect if set + if (result.Action != ActionType.Redirect302 && + result.Action != ActionType.Redirect302Now) + { + result.Reason = RedirectReason.Not_Redirected; + result.FinalUrl = null; + } + } + } + } + else + { + // alias does not exist in database + // and all attempts to find another have failed + //this should only happen if the HostPortal does not have any aliases + result.Action = ActionType.Output404; + if (response != null) + { + if (showDebug) + { + ShowDebugData(context, fullUrl, result, null); + } + result.Reason = RedirectReason.Requested_404; + //912 : change 404 type to transfer to allow transfer to main portal in single-portal installs + Handle404OrException(settings, context, null, result, true, showDebug); + finished = true; + } + } + } + + //404 page ?? + if (settings.TabId404 > 0 && settings.TabId404 == result.TabId) + { + string status = queryStringCol["status"]; + if (status == "404") + { + //respond with a 404 error + result.Action = ActionType.Output404; + result.Reason = RedirectReason.Requested_404_In_Url; + Handle404OrException(settings, context, null, result, true, showDebug); + } + } + else + { + if (result.DoRewrite == false && result.CanRewrite != StateBoolean.False && !finished && + result.Action == ActionType.Continue) + { + //739 : catch no-extension 404 errors + string pathWithNoQs = result.OriginalPath; + if (pathWithNoQs.Contains("?")) + { + pathWithNoQs = pathWithNoQs.Substring(0, pathWithNoQs.IndexOf("?", StringComparison.Ordinal)); + } + if (!pathWithNoQs.Substring(pathWithNoQs.Length - 5, 5).Contains(".")) + { + //no page extension, output a 404 if the Url is not found + //766 : check for physical path before passing off as a 404 error + //829 : change to use action physical path + //893 : filter by regex pattern to exclude urls which are valid, but show up as extensionless + if ((request != null && Directory.Exists(result.PhysicalPath)) + || + Regex.IsMatch(pathWithNoQs, settings.ValidExtensionlessUrlsRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + //do nothing : it's a request for a valid physical path, maybe including a default document + result.VirtualPath = StateBoolean.False; + } + else + { + if (!ServiceApi.IsMatch(context.Request.RawUrl)) + { + //no physical path, intercept the request and hand out a 404 error + result.Action = ActionType.Output404; + result.Reason = RedirectReason.Page_404; + result.VirtualPath = StateBoolean.True; + //add in a message to explain this 404, becaue it can be cryptic + result.DebugMessages.Add("404 Reason : Not found and no extension"); + Handle404OrException(settings, context, null, result, true, showDebug); + } + } + } + } + } + + // show debug messages after extensionless-url special 404 handling + if (showDebug) + { + ShowDebugData(context, fullUrl, result, null); + } + } + } + catch (ThreadAbortException) + { + //do nothing, a threadAbortException will have occured from using a server.transfer or response.redirect within the code block. This is the highest + //level try/catch block, so we handle it here. + } + catch (Exception ex) + { + if (showDebug) + { + Services.Exceptions.Exceptions.LogException(ex); + } + if (response != null) + { + if (showDebug) + { + ShowDebugData(context, requestUri.AbsoluteUri, result, ex); + } + if (result != null) + { + result.Ex = ex; + result.Reason = RedirectReason.Exception; + } + Handle404OrException(settings, context, ex, result, false, showDebug); + } + else + { + if (result != null && result.DebugMessages != null) + { + result.DebugMessages.Add("Exception: " + ex.Message); + result.DebugMessages.Add("Stack Trace: " + ex.StackTrace); + } + throw; + } + } + finally + { + //809 : add in new code copied from urlRewrite class in standard Url Rewrite module + if (context != null && context.Items["FirstRequest"] != null) + { + context.Items.Remove("FirstRequest"); + //process any messages in the eventQueue for the Application_Start_FIrstRequest event + EventQueueController.ProcessMessages("Application_Start_FirstRequest"); + } + } + } + + private static void ShowDebugData(HttpContext context, string requestUri, UrlAction result, Exception ex) + { + if (context != null) + { + HttpResponse response = context.Response; + + //handle null responses wherever they might be found - this routine must be tolerant to all kinds of invalid inputs + if (requestUri == null) + { + requestUri = "null Uri"; + } + string finalUrl = "null final Url"; + string rewritePath = "null rewrite path"; + string action = "null action"; + if (result != null) + { + finalUrl = result.FinalUrl; + action = result.Action.ToString(); + rewritePath = result.RewritePath; + } + //format up the error message to show + const string debugMsg = "{0}, {1}, {2}, {3}, {4}, {5}, {6}"; + string productVer = Assembly.GetExecutingAssembly().GetName(false).Version.ToString(); + string portalSettings = ""; + string browser = "Unknown"; + //949 : don't rely on 'result' being non-null + if (result != null) + { + browser = result.BrowserType.ToString(); + } + if (context.Items.Contains("PortalSettings")) + { + var ps = (PortalSettings) context.Items["PortalSettings"]; + if (ps != null) + { + portalSettings = ps.PortalId.ToString(); + if (ps.PortalAlias != null) + { + portalSettings += ":" + ps.PortalAlias.HTTPAlias; + } + } + } + response.AppendHeader("X-" + _productName + "-Debug", + string.Format(debugMsg, requestUri, finalUrl, rewritePath, action, productVer, + portalSettings, browser)); +#if (DEBUG) + var rawOutput = new StringWriter(); + rawOutput.WriteLine("
"); + rawOutput.WriteLine("

Advanced Url Rewriting Debug Output

"); + rawOutput.WriteLine("

" + + string.Format(debugMsg, requestUri, finalUrl, rewritePath, action, productVer, + portalSettings, browser) + "

"); +#endif + int msgNum = 1; + if (result != null) + { + foreach (string msg in result.DebugMessages) + { +#if (DEBUG) + rawOutput.WriteLine("
Debug Message " + msgNum.ToString("00") + ": " + msg + "
"); +#endif + response.AppendHeader("X-" + _productName + "-Debug-" + msgNum.ToString("00"), msg); + msgNum++; + } + } + if (ex != null) + { + response.AppendHeader("X-" + _productName + "-Ex", ex.Message); + } +#if (DEBUG) + if (ex != null) + { + rawOutput.WriteLine("Exception : " + ex.Message); + } + else + { + rawOutput.WriteLine("No Exception"); + } + + rawOutput.WriteLine("
"); + response.Write(rawOutput.ToString()); +#endif + } + } + + private static void Handle404OrException(FriendlyUrlSettings settings, HttpContext context, Exception ex, UrlAction result, bool transfer, bool showDebug) + { + //handle Auto-Add Alias + if (result.Action == ActionType.Output404 && CanAutoAddPortalAlias()) + { + //Need to determine if this is a real 404 or a possible new alias. + var portalId = Host.Host.HostPortalID; + if (portalId > Null.NullInteger) + { + //Get all the existing aliases + var aliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + + bool autoaddAlias; + bool isPrimary = false; + if (!aliases.Any()) + { + autoaddAlias = true; + isPrimary = true; + } + else + { + autoaddAlias = true; + foreach (var alias in aliases) + { + if (result.DomainName.ToLowerInvariant().IndexOf(alias.HTTPAlias, StringComparison.Ordinal) == 0 + && result.DomainName.Length >= alias.HTTPAlias.Length) + { + autoaddAlias = false; + break; + } + } + } + + if (autoaddAlias) + { + var portalAliasInfo = new PortalAliasInfo + { + PortalID = portalId, + HTTPAlias = result.RewritePath, + IsPrimary = isPrimary + }; + TestablePortalAliasController.Instance.AddPortalAlias(portalAliasInfo); + + context.Response.Redirect(context.Request.Url.ToString(), true); + } + } + } + + + if (context != null) + { + HttpRequest request = context.Request; + HttpResponse response = context.Response; + HttpServerUtility server = context.Server; + + const string errorPageHtmlHeader = @"{0}"; + const string errorPageHtmlFooter = @""; + var errorPageHtml = new StringWriter(); + CustomErrorsSection ceSection = null; + //876 : security catch for custom error reading + try + { + ceSection = (CustomErrorsSection) WebConfigurationManager.GetSection("system.web/customErrors"); + } +// ReSharper disable EmptyGeneralCatchClause + catch (Exception) +// ReSharper restore EmptyGeneralCatchClause + { + //on some medium trust environments, this will throw an exception for trying to read the custom Errors + //do nothing + } + + /* 454 new 404/500 error handling routine */ + bool useDNNTab = false; + int errTabId = -1; + string errUrl = null; + string status = ""; + bool isPostback = false; + if (settings != null) + { + if (request.RequestType == "POST") + { + isPostback = true; + } + if (result != null && ex != null) + { + result.DebugMessages.Add("Exception: " + ex.Message); + result.DebugMessages.Add("Stack Trace: " + ex.StackTrace); + if (ex.InnerException != null) + { + result.DebugMessages.Add("Inner Ex : " + ex.InnerException.Message); + result.DebugMessages.Add("Stack Trace: " + ex.InnerException.StackTrace); + } + else + { + result.DebugMessages.Add("Inner Ex : null"); + } + } + string errRH; + string errRV; + int statusCode; + if (result != null && result.Action != ActionType.Output404) + { + //output everything but 404 (usually 500) + if (settings.TabId500 > -1) //tabid specified for 500 error page, use that + { + useDNNTab = true; + errTabId = settings.TabId500; + } + errUrl = settings.Url500; + errRH = "X-UrlRewriter-500"; + errRV = "500 Rewritten to {0} : {1}"; + statusCode = 500; + status = "500 Internal Server Error"; + } + else //output 404 error + { + if (settings.TabId404 > -1) //if the tabid is specified for a 404 page, then use that + { + useDNNTab = true; + errTabId = settings.TabId404; + } + if (!String.IsNullOrEmpty(settings.Regex404)) + //with 404 errors, there's an option to catch certain urls and use an external url for extra processing. + { + try + { + //944 : check the original Url in case the requested Url has been rewritten before discovering it's a 404 error + string requestedUrl = request.Url.ToString(); + if (result != null && string.IsNullOrEmpty(result.OriginalPath) == false) + { + requestedUrl = result.OriginalPath; + } + if (Regex.IsMatch(requestedUrl, settings.Regex404, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + useDNNTab = false; + //if we have a match in the 404 regex value, then don't use the tabid + } + } + catch (Exception regexEx) + { + //.some type of exception : output in response header, and go back to using the tabid + response.AppendHeader("X-UrlRewriter-404Exception", regexEx.Message); + } + } + errUrl = settings.Url404; + errRH = "X-UrlRewriter-404"; + errRV = "404 Rewritten to {0} : {1} : Reason {2}"; + status = "404 Not Found"; + statusCode = 404; + } + + // check for 404 logging + if ((result == null || result.Action == ActionType.Output404)) + { + //Log 404 errors to Event Log + UrlRewriterUtils.Log404(request, settings, result); + } + //912 : use unhandled 404 switch + string reason404 = null; + bool unhandled404 = true; + if (useDNNTab && errTabId > -1) + { + unhandled404 = false; //we're handling it here + var tc = new TabController(); + TabInfo errTab = tc.GetTab(errTabId, result.PortalId, true); + if (errTab != null) + { + bool redirect = false; + //ok, valid tabid. what we're going to do is to load up this tab via a rewrite of the url, and then change the output status + string reason = "Not Found"; + if (result != null) + { + reason = result.Reason.ToString(); + } + response.AppendHeader(errRH, string.Format(errRV, "DNN Tab", + errTab.TabName + "(Tabid:" + errTabId.ToString() + ")", + reason)); + //show debug messages even if in debug mode + if (context != null && response != null && result != null && showDebug) + { + ShowDebugData(context, result.OriginalPath, result, null); + } + if (!isPostback) + { + response.ClearContent(); + response.StatusCode = statusCode; + response.Status = status; + } + else + { + redirect = true; + //redirect postbacks as you can't postback successfully to a server.transfer + } + errUrl = Globals.glbDefaultPage + TabIndexController.CreateRewritePath(errTab.TabID, ""); + //have to update the portal settings with the new tabid + PortalSettings ps = null; + if (context != null && context.Items != null) + { + if (context.Items.Contains("PortalSettings")) + { + ps = (PortalSettings) context.Items["PortalSettings"]; + context.Items.Remove("PortalSettings"); //nix it from the context + } + } + if (ps != null && ps.PortalAlias != null) + { + ps = new PortalSettings(errTabId, ps.PortalAlias); + } + else + { + if (result.HttpAlias != null && result.PortalId > -1) + { + var pac = new PortalAliasController(); + PortalAliasInfo pa = pac.GetPortalAlias(result.HttpAlias, result.PortalId); + ps = new PortalSettings(errTabId, pa); + } + else + { + //912 : handle 404 when no valid portal can be identified + //results when iis is configured to handle portal alias, but + //DNN isn't. This always returns 404 because a multi-portal site + //can't just show the 404 page of the host site. + var pc = new PortalController(); + ArrayList portals = pc.GetPortals(); + if (portals != null && portals.Count == 1) + { + //single portal install, load up portal settings for this portal + var singlePortal = (PortalInfo) portals[0]; + //list of aliases from database + var aliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(singlePortal.PortalID).ToList(); + //list of aliases from Advanced Url settings + List chosen = aliases.GetAliasesForPortalId(singlePortal.PortalID); + PortalAliasInfo useFor404 = null; + //go through all aliases and either get the first valid one, or the first + //as chosen in the advanced url management settings + foreach (var pa in aliases) + { + if (useFor404 == null) + { + useFor404 = pa; //first one by default + } + + //matching? + if (chosen != null && chosen.Count > 0) + { + if (chosen.Contains(pa.HTTPAlias)) + { + useFor404 = pa; + } + } + else + { + break; //no further checking + } + } + //now configure that as the portal settings + if (useFor404 != null) + { + //create portal settings context for identified portal alias in single portal install + ps = new PortalSettings(errTabId, useFor404); + } + } + else + { + reason404 = "Requested domain name is not configured as valid website"; + unhandled404 = true; + } + } + } + if (ps != null) + { + //re-add the context items portal settings back in + context.Items.Add("PortalSettings", ps); + } + if (redirect) + { + errUrl = Globals.NavigateURL(); + response.Redirect(errUrl, true); //redirect and end response. + //It will mean the user will have to postback again, but it will work the second time + } + else + { + if (transfer) + { + //execute a server transfer to the default.aspx?tabid=xx url + //767 : object not set error on extensionless 404 errors + if (context.User == null) + { + context.User = Thread.CurrentPrincipal; + } + response.TrySkipIisCustomErrors = true; + //881 : spoof the basePage object so that the client dependency framework + //is satisfied it's working with a page-based handler + IHttpHandler spoofPage = new CDefault(); + context.Handler = spoofPage; + server.Transfer("~/" + errUrl, true); + } + else + { + context.RewritePath("~/Default.aspx", false); + response.TrySkipIisCustomErrors = true; + response.Status = "404 Not Found"; + response.StatusCode = 404; + } + } + } + } + //912 : change to new if statement to handle cases where the TabId404 couldn't be handled correctly + if (unhandled404) + { + //proces the error on the external Url by rewriting to the external url + if (!String.IsNullOrEmpty(errUrl)) + { + response.ClearContent(); + response.TrySkipIisCustomErrors = true; + string reason = "Not Found"; + if (result != null) + { + reason = result.Reason.ToString(); + } + response.AppendHeader(errRH, string.Format(errRV, "Url", errUrl, reason)); + if (reason404 != null) + { + response.AppendHeader("X-Url-Master-404-Data", reason404); + } + response.StatusCode = statusCode; + response.Status = status; + server.Transfer("~/" + errUrl, true); + } + else + { +#if (DEBUG) + //955: xss vulnerability when outputting raw url back to the page + //only do so in debug mode, and sanitize the Url. + //sanitize output Url to prevent xss attacks on the default 404 page + string requestedUrl = request.Url.ToString(); + requestedUrl = HttpUtility.HtmlEncode(requestedUrl); + errorPageHtml.Write(status + "
The requested Url (" + requestedUrl + + ") does not return any valid content."); +#else + errorPageHtml.Write(status + "
The requested Url does not return any valid content."); +#endif + if (reason404 != null) + { + errorPageHtml.Write(status + "
" + reason404); + } + errorPageHtml.Write("
Administrators
"); + errorPageHtml.Write("
Change this message by configuring a specific 404 Error Page or Url for this website.
"); + + //output a reason for the 404 + string reason = ""; + if (result != null) + { + reason = result.Reason.ToString(); + } + if (!string.IsNullOrEmpty(errRH) && !string.IsNullOrEmpty(reason)) + { + response.AppendHeader(errRH, reason); + } + response.StatusCode = statusCode; + response.Status = status; + } + } + } + else + { + //fallback output if not valid settings + if (result != null && result.Action == ActionType.Output404) + { + //don't restate the requested Url to prevent cross site scripting + errorPageHtml.Write("404 Not Found
The requested Url does not return any valid content."); + response.StatusCode = 404; + response.Status = "404 Not Found"; + } + else + { + //error, especially if invalid result object + + errorPageHtml.Write("500 Server Error
An error occured during processing : if possible, check the event log of the server
"); + response.StatusCode = 500; + response.Status = "500 Internal Server Error"; + if (result != null) + { + result.Action = ActionType.Output500; + } + } + } + + if (ex != null) + { + if (context != null) + { + if (context.Items.Contains("UrlRewrite:Exception") == false) + { + context.Items.Add("UrlRewrite:Exception", ex.Message); + context.Items.Add("UrlRewrite:StackTrace", ex.StackTrace); + } + } + + if (ceSection != null && ceSection.Mode == CustomErrorsMode.Off) + { + errorPageHtml.Write(errorPageHtmlHeader); + errorPageHtml.Write("
Exception:
" + ex.Message + "
"); + errorPageHtml.Write("
Stack Trace:
" + ex.StackTrace + "
"); + errorPageHtml.Write("
Administrators
"); + errorPageHtml.Write("
You can see this exception because the customErrors attribute in the web.config is set to 'off'. Change this value to 'on' or 'RemoteOnly' to show Error Handling
"); + try + { + if (errUrl != null && errUrl.StartsWith("~")) + { + errUrl = VirtualPathUtility.ToAbsolute(errUrl); + } + } + finally + { + if (errUrl != null) + { + errorPageHtml.Write("
The error handling would have shown this page : " + errUrl + "
"); + } + else + { + errorPageHtml.Write("
The error handling could not determine the correct page to show.
"); + } + } + } + } + + string errorPageHtmlBody = errorPageHtml.ToString(); + if (errorPageHtmlBody.Length > 0) + { + response.Write(errorPageHtmlHeader); + response.Write(errorPageHtmlBody); + response.Write(errorPageHtmlFooter); + } + if (ex != null) + { + UrlRewriterUtils.LogExceptionInRequest(ex, status, result); + } + } + } + + private static bool CheckForDebug(HttpRequest request, NameValueCollection queryStringCol, bool debugEnabled) + { + string debugValue = ""; + bool retVal = false; + + if (debugEnabled) + { + const string debugToken = "_aumdebug"; + if (queryStringCol != null && queryStringCol[debugToken] != null) + { + debugValue = queryStringCol[debugToken]; + } + else + { + if (request != null) + { + debugValue = (request.Params.Get("HTTP_" + debugToken.ToUpper())); + } + if (debugValue == null) + { + debugValue = "false"; + } + } + } + + switch (debugValue.ToLower()) + { + case "true": + retVal = true; + break; + } + return retVal; + } + + private static bool CheckForTabExternalForwardOrRedirect(HttpContext context, + ref UrlAction result, + HttpResponse response, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + bool finished = false; + HttpRequest request = null; + if (context != null) + { + request = context.Request; + } + //check for external forwarding or a permanent redirect request + //592 : check for permanent redirect (823 : moved location from 'checkForRedirects') + if (result.TabId > -1 && result.PortalId > -1 && + (settings.ForwardExternalUrlsType != DNNPageForwardType.NoForward || + result.Reason == RedirectReason.Tab_Permanent_Redirect)) + { + bool allowRedirect = !(result.RewritePath != null && result.RewritePath.ToLower().Contains("&ctl=tab")); + //594 : do not redirect settings pages for external urls + if (allowRedirect) + { + TabInfo tab; + allowRedirect = CheckFor301RedirectExclusion(result.TabId, result.PortalId, false, out tab, settings); + if (allowRedirect) + { + //772 : not redirecting file type Urls when requested. + bool permanentRedirect = false; + string redirectUrl = null; + string cleanPath = null; + bool doRedirect = false; + switch (tab.TabType) + { + case TabType.File: + //have to fudge in a portal settings object for this to work - shortcoming of LinkClick URl generation + var portalSettings = new PortalSettings(result.TabId, result.PortalAlias); + if (context != null) + { + context.Items.Add("PortalSettings", portalSettings); + result.Reason = RedirectReason.File_Url; + string fileUrl = Globals.LinkClick(tab.Url, tab.TabID, -1); + context.Items.Remove("PortalSettings"); + //take back out again, because it will be done further downstream + //do a check to make sure we're not repeating the Url again, because the tabid is set but we don't want to touch + //a linkclick url + if (!result.OriginalPathNoAlias.EndsWith(HttpUtility.UrlDecode(fileUrl), true, CultureInfo.InvariantCulture)) + { + redirectUrl = fileUrl; + } + } + if (redirectUrl != null) + { + doRedirect = true; + } + break; + case TabType.Url: + result.Reason = RedirectReason.Tab_External_Url; + redirectUrl = tab.Url; + if (redirectUrl != null) + { + doRedirect = true; + if (settings.ForwardExternalUrlsType == DNNPageForwardType.Redirect301) + { + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Tab_External_Url; + } + else if (settings.ForwardExternalUrlsType == DNNPageForwardType.Redirect302) + { + result.Action = ActionType.Redirect302; + result.Reason = RedirectReason.Tab_External_Url; + } + } + break; + case TabType.Tab: + // if a tabType.tab is specified, it's either an external url or a permanent redirect + + //get the redirect path of the specific tab, as long as we have a valid request to work from + if (request != null) + { + //get the rewrite or requested path in a clean format, suitable for input to the friendly url provider + cleanPath = RewriteController.GetRewriteOrRequestedPath(result, request.Url); + //727 prevent redirectLoop with do301 in querystring + if (result.Action == ActionType.Redirect301 || + result.Action == ActionType.Redirect302) + { + cleanPath = RedirectTokens.RemoveAnyRedirectTokens(cleanPath, + request.QueryString); + } + //get the redirect Url from the friendly url provider using the tab, path and settings + redirectUrl = RedirectController.GetTabRedirectUrl(tab, settings, cleanPath, result, + out permanentRedirect, + parentTraceId); + } + //check to make sure there isn't a blank redirect Url + if (redirectUrl == null) + { + //problem : no redirect Url to redirect to + //solution : cancel the redirect + string message = "Permanent Redirect chosen for Tab " + + tab.TabPath.Replace("//", "/") + + " but forwarding Url was not valid"; + RedirectController.CancelRedirect(ref result, context, settings, message); + } + else + { + //if there was a redirect Url, set the redirect action and set the type of redirect going to use + doRedirect = true; + if (permanentRedirect) + { + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Tab_Permanent_Redirect; + //should be already set, anyway + result.RewritePath = cleanPath; + } + else + { + //not a permanent redirect, check if the page forwarding is set + if (settings.ForwardExternalUrlsType == DNNPageForwardType.Redirect301) + { + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Tab_External_Url; + } + else if (settings.ForwardExternalUrlsType == DNNPageForwardType.Redirect302) + { + result.Action = ActionType.Redirect302; + result.Reason = RedirectReason.Tab_External_Url; + } + } + } + break; + default: + //only concern here is if permanent redirect is requested, but there is no external url specified + if (result.Reason == RedirectReason.Tab_Permanent_Redirect) + { + bool permRedirect = tab.PermanentRedirect; + if (permRedirect) + { + //problem : permanent redirect marked, but no forwarding url supplied + //solution : cancel redirect + string message = "Permanent Redirect chosen for Tab " + + tab.TabPath.Replace("//", "/") + + " but no forwarding Url Supplied"; + RedirectController.CancelRedirect(ref result, context, settings, message); + } + } + break; + } + + //do the redirect we have specified + if (doRedirect && + (result.Action == ActionType.Redirect301 || result.Action == ActionType.Redirect302)) + { + result.FinalUrl = redirectUrl; + if (result.Action == ActionType.Redirect301) + { + if (response != null) + { + //perform a 301 redirect to the external url of the tab + response.Status = "301 Moved Permanently"; + response.AppendHeader("X-Redirect-Reason", + result.Reason.ToString().Replace("_", " ") + " Requested"); + response.AddHeader("Location", result.FinalUrl); + } + } + else + { + if (result.Action == ActionType.Redirect302) + { + if (response != null) + { + //perform a 301 redirect to the external url of the tab + response.AppendHeader("X-Redirect-Reason", + result.Reason.ToString().Replace("_", " ") + " Requested"); + response.Redirect(result.FinalUrl); + } + } + } + finished = true; + } + } + } + } + return finished; + } + + private bool CheckForSecureRedirect(PortalSettings portalSettings, + Uri requestUri, + UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings) + { + bool redirectSecure = false; + string url = requestUri.ToString(); + //889 : don't run secure redirect code for physical resources or requests that aren't a rewritten Url + if (result.IsPhysicalResource == false && result.TabId >= 0) + // no secure redirection for physical resources, only tab-specific requests can be redirected for ssl connections + { + if (portalSettings.ActiveTab != null) + { + result.DebugMessages.Add("ActiveTab: " + portalSettings.ActiveTab.TabID.ToString() + "/" + + portalSettings.ActiveTab.TabName + " IsSecure: " + + portalSettings.ActiveTab.IsSecure.ToString()); + + //check ssl enabled + if (portalSettings.SSLEnabled) + { + //717 : check page is secure, connection is not secure + //952 : support SSl Offloading in DNN 6.2+ + if (portalSettings.ActiveTab.IsSecure && !result.IsSecureConnection && !result.IsSSLOffloaded) + { + redirectSecure = true; + string stdUrl = portalSettings.STDURL; + string sslUrl = portalSettings.SSLURL; + if (string.IsNullOrEmpty(result.HttpAlias) == false) + { + stdUrl = result.HttpAlias; + } + url = url.Replace("http://", "https://"); + url = ReplaceDomainName(url, stdUrl, sslUrl); + } + } + //check ssl enforced + if (portalSettings.SSLEnforced) + { + //check page is not secure, connection is secure + if (!portalSettings.ActiveTab.IsSecure && result.IsSecureConnection) + { + //has connection already been forced to secure? + if (queryStringCol["ssl"] == null) + { + //no? well this page shouldn't be secure + string stdUrl = portalSettings.STDURL; + string sslUrl = portalSettings.SSLURL; + url = url.Replace("https://", "http://"); + url = ReplaceDomainName(url, sslUrl, stdUrl); + redirectSecure = true; + } + } + } + } + + + if (redirectSecure) + { + //now check to see if excluded. Why now? because less requests are made to redirect secure, + //so we don't have to check the exclusion as often. + bool exclude = false; + string doNotRedirectSecureRegex = settings.DoNotRedirectSecureRegex; + if (!string.IsNullOrEmpty(doNotRedirectSecureRegex)) + { + //match the raw url + exclude = (Regex.IsMatch(result.RawUrl, doNotRedirectSecureRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)); + } + if (!exclude) + { + result.Action = ActionType.Redirect302Now; + result.Reason = RedirectReason.Secure_Page_Requested; + //760 : get the culture specific home page tabid for a redirect comparison + int homePageTabId = portalSettings.HomeTabId; + homePageTabId = TabPathHelper.GetHomePageTabIdForCulture(portalSettings.DefaultLanguage, + portalSettings.PortalId, + result.CultureCode, homePageTabId); + if (result.TabId == homePageTabId) + { + //replace the /default.aspx in the Url if it was found + url = Regex.Replace(url, @"(? -1) + if (result.PortalId > -1) //portal has been identified + { + var portalAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + + if (queryStringCol != null && queryStringCol["forceAlias"] != "true") + { + if (portalAliases.Count > 0) + { + string checkAlias = result.HttpAlias; + bool continueLoop = true; + bool triedWWW = false; + while (httpAlias == null && continueLoop) + { + if (portalAliases.ContainsAlias(result.PortalId, checkAlias)) + { + if (portalAliases.Count > 0) + { + var cpa = portalAliases.GetAliasByPortalIdAndSettings(result); + if (cpa != null) + { + httpAlias = cpa.HTTPAlias; + continueLoop = false; + } + if (String.IsNullOrEmpty(result.CultureCode) && cpa == null) + { + //if there is a specific culture for this portal alias, then check that + string culture = portalAliases.GetCultureByPortalIdAndAlias(result.PortalId, result.HttpAlias); + //if this matches the alias of the request, then we know we have the correct alias because it is a specific culture + if (!string.IsNullOrEmpty(culture)) + { + continueLoop = false; + } + } + } + } + //check whether to still go on or not + if (continueLoop) + { + //this alias doesn't exist in the list + //check if it has a www on it - if not, try adding, if it does, try removing + if (!triedWWW) + { + triedWWW = true; //now tried adding/removing www + if (checkAlias.ToLower().StartsWith("www.")) + { + checkAlias = checkAlias.Substring(4); + } + else + { + checkAlias = "www." + checkAlias; + } + } + else + { + //last thing to try, get the default language and see if there is a portal alias for that + //thus, any aliases not identified as belonging to a language are redirected back to the + //alias named for the default language + continueLoop = false; + //735 : switch to custom method for getting portal + PortalInfo pi = CacheController.GetPortal(result.PortalId, false); + if (pi != null) + { + string cultureCode = pi.DefaultLanguage; + if (!string.IsNullOrEmpty(cultureCode)) + { + var primaryPortalAlias = portalAliases.GetAliasByPortalIdAndSettings(result.PortalId, result,cultureCode,settings); + if (primaryPortalAlias != null) + { + httpAlias = primaryPortalAlias.HTTPAlias; + } + } + } + } + } + } + } + + + //check to see if it is a custom tab alais - in that case, it is allowed to be requested for the tab + if (CheckIfAliasIsCustomTabAlias(ref result, httpAlias, settings)) + { + //change the primary alias to the custom tab alias that has been requested. + result.PrimaryAlias = result.PortalAlias; + } + else + if (httpAlias != null && String.Compare(httpAlias, result.HttpAlias, StringComparison.OrdinalIgnoreCase) != 0) + { + incorrectAlias = true; + } + } + } + return incorrectAlias; + } + /// + /// Redirects an alias if that is allowed by the settings + /// + /// + /// + /// + /// + + private static bool RedirectPortalAlias(string httpAlias, ref UrlAction result, FriendlyUrlSettings settings) + { + bool redirected = false; + //redirect to primary alias + if (result.PortalAliasMapping == PortalSettings.PortalAliasMapping.Redirect && result.RedirectAllowed) + { + if (result.Reason == RedirectReason.Wrong_Portal_Alias_For_Browser_Type || result.Reason == RedirectReason.Wrong_Portal_Alias_For_Culture || + result.Reason == RedirectReason.Wrong_Portal_Alias_For_Culture_And_Browser) + { + redirected = ConfigurePortalAliasRedirect(ref result, result.HttpAlias, httpAlias, false, result.Reason, settings.InternalAliasList, settings); + } + else + { + redirected = ConfigurePortalAliasRedirect(ref result, result.HttpAlias, httpAlias, false, settings.InternalAliasList, settings); + } + } + + return redirected; + } + + private static bool ConfigurePortalAliasRedirect(ref UrlAction result, + string wrongAlias, + string rightAlias, + bool ignoreCustomAliasTabs, + List internalAliases, + FriendlyUrlSettings settings) + { + return ConfigurePortalAliasRedirect(ref result, + wrongAlias, + rightAlias, + ignoreCustomAliasTabs, + RedirectReason.Wrong_Portal_Alias, + internalAliases, + settings); + } + /// + /// Checks to see whether the specified alias is a customTabAlias + /// + /// + /// + /// + /// + private static bool CheckIfAliasIsCustomTabAlias(ref UrlAction result, string httpAlias, FriendlyUrlSettings settings) + { + List customAliasesForTabs = TabIndexController.GetCustomPortalAliases(settings); + bool isACustomTabAlias = false; + if (customAliasesForTabs != null && customAliasesForTabs.Count > 0) + { + //remove any customAliases that are also primary aliases. + foreach (var cpa in TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId)) + { + if (cpa.IsPrimary == true && customAliasesForTabs.Contains(cpa.HTTPAlias)) + { + customAliasesForTabs.Remove(cpa.HTTPAlias); + } + } + isACustomTabAlias = customAliasesForTabs.Contains(httpAlias.ToLower()); + } + return isACustomTabAlias; + } + /// + /// Configures the result object to set the correct Alias redirect + /// parameters and destination URL + /// + /// + /// + /// + /// + /// + /// + /// + /// + private static bool ConfigurePortalAliasRedirect(ref UrlAction result, + string wrongAlias, + string rightAlias, + bool ignoreCustomAliasTabs, + RedirectReason redirectReason, + List internalAliases, + FriendlyUrlSettings settings) + { + //wrong alias for the portal + //check to see if the wrong portal alias could be a custom alias for a tab + bool doRedirect; + if (ignoreCustomAliasTabs == false) //check out custom alias tabs collection + { + //if an alias is a custom tab alias for a specific tab, then don't redirect + if (CheckIfAliasIsCustomTabAlias(ref result, wrongAlias, settings)) + doRedirect = false; + else + { + doRedirect = true; + } + } + else + { + doRedirect = true; //do redirect, ignore custom alias entries for tabs + } + //check to see if it is an internal alias. These are used to block redirects + //to allow for reverse proxy requests, which must change the rewritten alias + //while leaving the requested alias + bool internalAliasFound = false; + if (doRedirect && internalAliases != null && internalAliases.Count > 0) + { + if (internalAliases.Any(ia => String.Compare(ia.HttpAlias, wrongAlias, StringComparison.OrdinalIgnoreCase) == 0)) + { + internalAliasFound = true; + doRedirect = false; + } + } + //if still need to do redirect, then set the settings that will cause the redirect (redirect not done here) + if (doRedirect) + { + result.Action = ActionType.Redirect301; + result.Reason = redirectReason; + string destUrl = result.OriginalPath.Replace(wrongAlias, rightAlias); + if (redirectReason == RedirectReason.Wrong_Portal_Alias_For_Culture || + redirectReason == RedirectReason.Wrong_Portal_Alias_For_Culture_And_Browser) + { + destUrl = destUrl.Replace("/language/" + result.CultureCode, ""); + } + destUrl = CheckForSiteRootRedirect(rightAlias, destUrl); + result.FinalUrl = destUrl; + } + else + { + //838 : don't overwrite the reason if already have checkfor301 + // and don't do a check on the basis that an internal alias was found + if (result.Action != ActionType.CheckFor301 && internalAliasFound == false) + { + //set status to 'check for redirect' + result.Action = ActionType.CheckFor301; + result.Reason = RedirectReason.Custom_Tab_Alias; + } + } + return doRedirect; + } + + private void IdentifyPortalAlias(HttpContext context, + HttpRequest request, + Uri requestUri, UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + //get the domain name of the request, if it isn't already supplied + if (request != null && string.IsNullOrEmpty(result.DomainName)) + { + result.DomainName = Globals.GetDomainName(request); //parse the domain name out of the request + } + + // get tabId from querystring ( this is mandatory for maintaining portal context for child portals ) + if (queryStringCol["tabid"] != null) + { + string raw = queryStringCol["tabid"]; + int tabId; + if (Int32.TryParse(raw, out tabId)) + { + result.TabId = tabId; + } + else + { + //couldn't parse tab id + //split in two? + string[] tabids = raw.Split(','); + if (tabids.GetUpperBound(0) > 0) + { + //hmm more than one tabid + if (Int32.TryParse(tabids[0], out tabId)) + { + result.TabId = tabId; + //but we want to warn against this! + var ex = + new Exception( + "Illegal request exception : Two TabId parameters provided in a single request: " + + requestUri); + UrlRewriterUtils.LogExceptionInRequest(ex, "Not Set", result); + + result.Ex = ex; + } + else + { + //yeah, nothing, divert to 404 + result.Action = ActionType.Output404; + var ex = + new Exception( + "Illegal request exception : TabId parameters in query string, but invalid TabId requested : " + + requestUri); + UrlRewriterUtils.LogExceptionInRequest(ex, "Not Set", result); + result.Ex = ex; + } + } + } + } + // get PortalId from querystring ( this is used for host menu options as well as child portal navigation ) + if (queryStringCol["portalid"] != null) + { + string raw = queryStringCol["portalid"]; + int portalId; + if (Int32.TryParse(raw, out portalId)) + { + //848 : if portal already found is different to portal id in querystring, then load up different alias + //this is so the portal settings will be loaded correctly. + if (result.PortalId != portalId) + { + //portal id different to what we expected + result.PortalId = portalId; + //check the loaded portal alias, because it might be wrong + if (result.PortalAlias != null && result.PortalAlias.PortalID != portalId) + { + //yes, the identified portal alias is wrong. Find the correct alias for this portal + PortalAliasInfo pa = TabIndexController.GetPortalAliasByPortal(portalId, result.DomainName); + if (pa != null) + { + //note: sets portal id and portal alias + result.PortalAlias = pa; + } + } + } + } + } + else + { + //check for a portal alias if there's no portal Id in the query string + //check for absence of captcha value, because the captcha string re-uses the alias querystring value + if (queryStringCol["alias"] != null && queryStringCol["captcha"] == null) + { + string alias = queryStringCol["alias"]; + PortalAliasInfo portalAlias = PortalAliasController.GetPortalAliasInfo(alias); + if (portalAlias != null) + { + //ok the portal alias was found by the alias name + // check if the alias contains the domain name + if (alias.Contains(result.DomainName) == false) + { + // replaced to the domain defined in the alias + if (request != null) + { + string redirectDomain = Globals.GetPortalDomainName(alias, request, true); + //retVal.Url = redirectDomain; + result.FinalUrl = redirectDomain; + result.Action = ActionType.Redirect302Now; + result.Reason = RedirectReason.Alias_In_Url; + } + } + else + { + // the alias is the same as the current domain + result.HttpAlias = portalAlias.HTTPAlias; + result.PortalAlias = portalAlias; + result.PortalId = portalAlias.PortalID; + //don't use this crap though - we don't want ?alias=portalAlias in our Url + if (result.RedirectAllowed) + { + string redirect = requestUri.Scheme + Uri.SchemeDelimiter + result.PortalAlias.HTTPAlias + + "/"; + result.Action = ActionType.Redirect301; + result.FinalUrl = redirect; + result.Reason = RedirectReason.Unfriendly_Url_Child_Portal; + } + } + } + } + } + //first try and identify the portal using the tabId, but only if we identified this tab by looking up the tabid + //from the original url + //668 : error in child portal redirects to child portal home page because of mismatch in tab/domain name + if (result.TabId != -1 && result.FriendlyRewrite == false) + { + // get the alias from the tabid, but only if it is for a tab in that domain + // 2.0 : change to compare retrieved alias to the already-set httpAlias + string httpAliasFromTab = PortalAliasController.GetPortalAliasByTab(result.TabId, result.DomainName); + if (httpAliasFromTab != null) + { + //882 : account for situation when portalAlias is null. + if (result.PortalAlias != null && String.Compare(result.PortalAlias.HTTPAlias, httpAliasFromTab, StringComparison.OrdinalIgnoreCase) != 0 + || result.PortalAlias == null) + { + //691 : change logic to force change in portal alias context rather than force back. + //This is because the tabid in the query string should take precedence over the portal alias + //to handle parent.com/default.aspx?tabid=xx where xx lives in parent.com/child/ + var tc = new TabController(); +#pragma warning disable 612,618 + TabInfo tab = tc.GetTab(result.TabId); +#pragma warning restore 612,618 + //when result alias is null or result alias is different from tab-identified portalAlias + if (tab != null && (result.PortalAlias == null || tab.PortalID != result.PortalAlias.PortalID)) + { + //the tabid is different to the identified portalid from the original alias identified + //so get a new alias + var pac = new PortalAliasController(); + PortalAliasInfo tabPortalAlias = pac.GetPortalAlias(httpAliasFromTab, tab.PortalID); + if (tabPortalAlias != null) + { + result.PortalId = tabPortalAlias.PortalID; + result.PortalAlias = tabPortalAlias; + result.Action = ActionType.CheckFor301; + result.Reason = RedirectReason.Wrong_Portal; + } + } + } + } + } + //if no alias, try and set by using the identified http alias or domain name + if (result.PortalAlias == null) + { + if (!string.IsNullOrEmpty(result.HttpAlias)) + { + result.PortalAlias = PortalAliasController.GetPortalAliasInfo(result.HttpAlias); + } + else + { + result.PortalAlias = PortalAliasController.GetPortalAliasInfo(result.DomainName); + if (result.PortalAlias == null && result.DomainName.EndsWith("/")) + { + result.DomainName = result.DomainName.TrimEnd('/'); + result.PortalAlias = PortalAliasController.GetPortalAliasInfo(result.DomainName); + } + } + } + + if (result.PortalId == -1) + { + if (!requestUri.LocalPath.ToLower().EndsWith(Globals.glbDefaultPage.ToLower())) + { + // allows requests for aspx pages in custom folder locations to be processed + return; + } + //the domain name was not found so try using the host portal's first alias + if (Host.Host.HostPortalID != -1) + { + result.PortalId = Host.Host.HostPortalID; + // use the host portal, but replaced to the host portal home page + var aliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + if (aliases.Count > 0) + { + string alias = null; + + //get the alias as the chosen portal alias for the host portal based on the result culture code + var cpa = aliases.GetAliasByPortalIdAndSettings(result.PortalId, result, result.CultureCode, settings); + if (cpa != null) + { + alias = cpa.HTTPAlias; + } + + if (alias != null) + { + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Host_Portal_Used; + string destUrl = MakeUrlWithAlias(requestUri, alias); + destUrl = CheckForSiteRootRedirect(alias, destUrl); + result.FinalUrl = destUrl; + } + else + { + //Get the first Alias for the host portal + result.PortalAlias = aliases[result.PortalId]; + string url = MakeUrlWithAlias(requestUri, result.PortalAlias); + if (result.TabId != -1) + { + url += requestUri.Query; + } + result.FinalUrl = url; + result.Reason = RedirectReason.Host_Portal_Used; + result.Action = ActionType.Redirect302Now; + } + } + } + } + + //double check to make sure we still have the correct alias now that all other information is known (ie tab, portal, culture) + //770 : redirect alias based on tab id when custom alias used + if (result.TabId == -1 && result.Action == ActionType.CheckFor301 && + result.Reason == RedirectReason.Custom_Tab_Alias) + { + //here because the portal alias matched, but no tab was found, and because there are custom tab aliases used for this portal + //need to redirect back to the chosen portal alias and keep the current path. + string wrongAlias = result.HttpAlias; //it's a valid alias, but only for certain tabs + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + if (primaryAliases != null && result.PortalId > -1) + { + //going to look for the correct alias based on the culture of the request + string requestCultureCode = result.CultureCode; + //if that didn't work use the default language of the portal + if (requestCultureCode == null) + { + //this might end up in a double redirect if the path of the Url is for a specific language as opposed + //to a path belonging to the default language domain + var pc = new PortalController(); + PortalInfo portal = pc.GetPortal(result.PortalId); + if (portal != null) + { + requestCultureCode = portal.DefaultLanguage; + } + } + //now that the culture code is known, look up the correct portal alias for this portalid/culture code + var cpa = primaryAliases.GetAliasByPortalIdAndSettings(result.PortalId, result, requestCultureCode, settings); + if (cpa != null) + { + //if an alias was found that matches the request and the culture code, then run with that + string rightAlias = cpa.HTTPAlias; + //will cause a redirect to the primary portal alias - we know now that there was no custom alias tab + //found, so it's just a plain wrong alias + ConfigurePortalAliasRedirect(ref result, wrongAlias, rightAlias, true, + settings.InternalAliasList, settings); + } + } + } + else + { + //then check to make sure it's the chosen portal alias for this portal + //627 : don't do it if we're redirecting to the host portal + if (result.RedirectAllowed && result.Reason != RedirectReason.Host_Portal_Used) + { + string primaryAlias; + //checking again in case the rewriting operation changed the values for the valid portal alias + bool incorrectAlias = IsPortalAliasIncorrect(context, request, requestUri, result, queryStringCol, settings, parentTraceId, out primaryAlias); + if (incorrectAlias) RedirectPortalAlias(primaryAlias, ref result, settings); + } + } + + //check to see if we have to avoid the core 302 redirect for the portal alias that is in the /defualt.aspx + //for child portals + //exception to that is when a custom alias is used but no rewrite has taken place + if (result.DoRewrite == false && (result.Action == ActionType.Continue + || + (result.Action == ActionType.CheckFor301 && + result.Reason == RedirectReason.Custom_Tab_Alias))) + { + string aliasQuerystring; + bool isChildAliasRootUrl = CheckForChildPortalRootUrl(requestUri.AbsoluteUri, result, out aliasQuerystring); + if (isChildAliasRootUrl) + { + RewriteAsChildAliasRoot(context, result, aliasQuerystring, settings); + } + } + } + + internal static void RewriteAsChildAliasRoot(HttpContext context, + UrlAction result, + string aliasQueryString, + FriendlyUrlSettings settings) + { + string culture = null; + //look for specific alias to rewrite language parameter + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + if (result.PortalId > -1 && result.HttpAlias != null) + { + culture = primaryAliases.GetCultureByPortalIdAndAlias(result.PortalId, result.HttpAlias); + } + if (string.IsNullOrEmpty(culture)) + //732 : when no culture returned can be "" as well as null : no culture causes no rewrite, which results in redirect to parent alias + { + //set the default culture code here + //735 : switch to custom method for getting portal + PortalInfo pi = CacheController.GetPortal(result.PortalId, false); + if (pi != null) + { + culture = pi.DefaultLanguage; + } + } + if (!string.IsNullOrEmpty(culture)) //a culture was identified for the alias root + { + if (RewriteController.AddLanguageCodeToRewritePath(ref aliasQueryString, culture)) + { + result.CultureCode = culture; + } + result.DoRewrite = true; + result.RewritePath = "~/" + Globals.glbDefaultPage + aliasQueryString; + //the expected /default.aspx path (defaultPageUrl) matches the requested Url (/default.aspx) + if (context != null) + { + //only do if not testing + RewriterUtils.RewriteUrl(context, result.RewritePath); + } + } + } + + internal static bool CheckForChildPortalRootUrl(string requestUrl, UrlAction result, out string aliasQueryString) + { + bool isChildPortalRootUrl = false; + //what we are going to test for here is that if this is a child portal request, for the /default.aspx of the child portal + //then we are going to avoid the core 302 redirect to ?alias=portalALias by rewriting to the /default.aspx of the site root + //684 : don't convert querystring items to lower case + //do the check by constructing what a child alias url would look like and compare it with the requested urls + //912 : when requested without a valid portal alias, portalALias is null. Refuse and return false. + aliasQueryString = null; + if (result.PortalAlias != null && result.PortalAlias.HTTPAlias != null) + { + string defaultPageUrl = result.Scheme + result.PortalAlias.HTTPAlias + "/" + + Globals.glbDefaultPage.ToLower(); //child alias Url with /default.aspx + //660 : look for a querystring on the site root for a child portal, and handle it if so + if (String.CompareOrdinal(requestUrl.ToLower(), defaultPageUrl) == 0) + { + //exact match : that's the alias root + isChildPortalRootUrl = true; + aliasQueryString = ""; + } + if (!isChildPortalRootUrl && requestUrl.Contains("?")) + { + //is we didn't get an exact match but there is a querystring, then investigate + string[] requestUrlParts = requestUrl.Split('?'); + if (requestUrlParts.GetUpperBound(0) > 0) + { + string rootPart = requestUrlParts[0]; + string queryString = requestUrlParts[1]; + if (String.Compare(rootPart, defaultPageUrl, StringComparison.OrdinalIgnoreCase) == 0) + { + //rewrite, but put in the querystring on the rewrite path + isChildPortalRootUrl = true; + aliasQueryString = "?" + queryString; + //674: check for 301 if this value is a tabid/xx - otherwise the url will just evaluate as is + if (queryString.ToLower().StartsWith("tabid=")) + { + result.Action = ActionType.CheckFor301; + } + } + } + } + } + return isChildPortalRootUrl; + } + + private static string MakeUrlWithAlias(Uri requestUri, string httpAlias) + { + return requestUri.AbsoluteUri.ToLower().StartsWith("https://") + ? "https://" + httpAlias.Replace("*.", "") + "/" + : "http://" + httpAlias.Replace("*.", "") + "/"; + } + + private static string MakeUrlWithAlias(Uri requestUri, PortalAliasInfo alias) + { + return MakeUrlWithAlias(requestUri, alias.HTTPAlias); + } + + /// + /// Determines if this is a request from an install / upgrade url + /// + /// + /// + /// + /// + /// + /// + /// //875 : cater for the upgradewizard.aspx Url that is new to DNN 6.1 + /// + private static bool IgnoreRequestForInstall(string physicalPath, string refererPath, string requestedDomain, string refererDomain) + { + if (physicalPath.EndsWith("install.aspx", true, CultureInfo.InvariantCulture) + || physicalPath.EndsWith("installwizard.aspx", true, CultureInfo.InvariantCulture) + || physicalPath.EndsWith("upgradewizard.aspx", true, CultureInfo.InvariantCulture) + || Globals.Status == Globals.UpgradeStatus.Install + || Globals.Status == Globals.UpgradeStatus.Upgrade) + return true; + //954 : DNN 7.0 compatibility + //check for /default.aspx which is default Url launched from the Upgrade/Install wizard page + //961 : check domain as well as path for the referer + if (physicalPath.EndsWith(Globals.glbDefaultPage, true, CultureInfo.InvariantCulture) == false + && refererPath != null + && String.Compare(requestedDomain, refererDomain, StringComparison.OrdinalIgnoreCase) == 0 + && (refererPath.EndsWith("install.aspx", true, CultureInfo.InvariantCulture) + || refererPath.EndsWith("installwizard.aspx", true, CultureInfo.InvariantCulture) + || refererPath.EndsWith("upgradewizard.aspx", true, CultureInfo.InvariantCulture) + )) + { + return true; + } + return false; + } + + private static bool IgnoreRequestForInstall(HttpRequest request) + { + try + { + //string physicalPath = request.PhysicalPath; + //return IgnoreRequestForInstall(physicalPath); + string physicalPath = request.PhysicalPath; + string requestedDomain = request.Url.Host; + string refererPath = null, refererDomain = null; + if (request.UrlReferrer != null) + { + refererDomain = request.UrlReferrer.Host; + refererPath = request.UrlReferrer.LocalPath; + } + return IgnoreRequestForInstall(physicalPath, refererPath, requestedDomain, refererDomain); + } + catch (PathTooLongException) + { + //catch and handle this exception, caused by an excessively long file path based on the + //mapped virtual url + return false; + } + } + + private static bool IgnoreRequest(UrlAction result, string requestedPath, string ignoreRegex, HttpRequest request) + { + bool retVal = false; + //check if we are upgrading/installing + //829 : use result physical path instead of requset physical path + //875 : cater for the upgradewizard.aspx Url that is new to DNN 6.1 + if (request != null && (IgnoreRequestForInstall(request))) + { + //ignore all install requests + retVal = true; + } + else if (request != null && request.Path.EndsWith("SetGettingStartedPageAsShown")) + { + //ignore request to the Getting Started Web Method + retVal = true; + } + else + { + try + { + if ((ignoreRegex.Length > 0)) + { + if (Regex.IsMatch(requestedPath, ignoreRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + retVal = true; + } + } + } + catch (Exception ex) + { + UrlRewriterUtils.LogExceptionInRequest(ex, "Not Set", result); + result.Ex = ex; + } + } + return retVal; + } + + private static void CheckForRewrite(string fullUrl, + string querystring, + UrlAction result, + bool useFriendlyUrls, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings, + out bool isPhysicalResource, + Guid parentTraceId) + { + bool checkForRewrites; + //just check to make sure it isn't a physical resource on the server + RewriteController.IdentifyByPhysicalResource(result.PhysicalPath, + fullUrl, + queryStringCol, + ref result, + useFriendlyUrls, + settings, + out isPhysicalResource, + out checkForRewrites, + parentTraceId); + + if (checkForRewrites && RewriteController.CanRewriteRequest(result, fullUrl, settings)) + { + bool doSiteUrlProcessing = false; + //728 new regex expression to pass values straight onto the siteurls.config file + if (!string.IsNullOrEmpty(settings.UseSiteUrlsRegex)) + { + doSiteUrlProcessing = Regex.IsMatch(fullUrl, settings.UseSiteUrlsRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + + if (!doSiteUrlProcessing) + //if a virtual request, and not starting with the siteUrls.config file, go on to find the rewritten path + { + //looks up the page index to find the correct Url + bool doRewrite = RewriteController.IdentifyByTabPathEx(fullUrl, querystring, result, queryStringCol, settings, parentTraceId); + if (!doRewrite) + { + doSiteUrlProcessing = true; + } + } + if (doSiteUrlProcessing) + { + //728 : compare requests against the siteurls.config file, either if no other match was found, or if we want to skip the rest of the processing + // the standard DNN way of rewriting, using expressions found in the siteurls.config file + RewriteController.IdentifyByRegEx(fullUrl, querystring, result.ApplicationPath, ref result, settings, parentTraceId); + } + } + } + + private void SecurityCheck(HttpApplication app) + { + HttpRequest request = app.Request; + HttpServerUtility server = app.Server; + + //675 : unnecessarily strict url validation + // URL validation + // check for ".." escape characters commonly used by hackers to traverse the folder tree on the server + // the application should always use the exact relative location of the resource it is requesting + string strURL = request.Url.AbsolutePath; + string strDoubleDecodeURL = server.UrlDecode(server.UrlDecode(request.RawUrl)); + if (Regex.Match(strURL, "[\\\\/]\\.\\.[\\\\/]").Success | + Regex.Match(strDoubleDecodeURL, "[\\\\/]\\.\\.[\\\\/]").Success) + { + throw new HttpException(404, "Not Found"); + } + } + + private static bool CheckForRedirects(Uri requestUri, + string fullUrl, + NameValueCollection queryStringCol, + UrlAction result, + string requestType, + FriendlyUrlSettings settings, + int portalHomeTabId) + { + bool redirected = false; + if (queryStringCol["error"] == null && queryStringCol["message"] == null && requestType != "POST") + { + //if the / is missing from an extension-less request, then check for a 301 redirect + if (settings.PageExtensionUsageType == PageExtensionUsageType.Never) + { + //575 check on absolutePath instead of absoluteUri : this ignores query strings and fragments like # + //610 don't always end with '/' - reverses previous setting + //687 don't double-check 301 redirects. 'CheckFor301' is less concise than 'Redirect301' + if (requestUri.AbsolutePath.EndsWith("/") && result.Action != ActionType.Redirect301) + { + result.Action = ActionType.CheckFor301; + } + } + if (settings.RedirectWrongCase && result.Action == ActionType.Continue) + { + result.Action = ActionType.CheckFor301; + } + string scheme = requestUri.Scheme + Uri.SchemeDelimiter; + bool queryStringHas301Parm = (queryStringCol["do301"] != null); + //727 : keep a bool value if there is a do301 request in the querystring + //check for a 301 request in the query string, or an explicit 301 or 302 request + //2.0 - check for explicit do301=true instead of just do301 key + string do301Val = queryStringCol["do301"]; + if (result.TabId > -1 //valid tab + && (result.Action == ActionType.Redirect301 //specific 301 redirect + || (do301Val != null && do301Val == "true") //or rewrite hint for specific 301 redirect + || result.Action == ActionType.Redirect302)) //or specific 302 redirect + { + //we have ordered a 301 redirect earlier in the code + var tc = new TabController(); + + //get the url for redirection by re-submitting the path into the Friendly Url Provider + string pathOnly = RewriteController.GetRewriteOrRequestedPath(result, requestUri); + //727 prevent redirectLoop with do301 in querystring + if (result.Action == ActionType.Redirect301 || queryStringHas301Parm || result.Action == ActionType.Redirect302) + { + pathOnly = RedirectTokens.RemoveAnyRedirectTokens(pathOnly, queryStringCol); + } + + //check for exclusion by regex for this url + if (result.RedirectAllowed) + { + //get the tab so we know where to go + TabInfo tab; + bool checkRedirect = CheckFor301RedirectExclusion(result.TabId, result.PortalId, true, out tab, settings); + + if (checkRedirect) + { + if ((result.Reason == RedirectReason.Deleted_Page || result.Reason == RedirectReason.Disabled_Page) + && portalHomeTabId > 0 + && settings.DeletedTabHandlingType == DeletedTabHandlingType.Do301RedirectToPortalHome) + { + //redirecting to home page + TabInfo homeTab = tc.GetTab(portalHomeTabId, result.PortalId, false); + if (homeTab != null) + { + string homePageUrl = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(homeTab, + pathOnly, + Globals.glbDefaultPage, + result.HttpAlias, + false, + settings, + Guid.Empty); + result.Action = ActionType.Redirect301; + result.FinalUrl = homePageUrl; + result.RewritePath = pathOnly; + redirected = true; + } + } + else + { + //get the rewrite or requested path in a clean format, suitable for input to the friendly url provider + string cleanPath = RewriteController.GetRewriteOrRequestedPath(result, requestUri); + + //727 prevent redirectLoop with do301 in querystring + //also check for existing in path of do301 token + if (result.Action == ActionType.Redirect301 || do301Val != null || result.Action == ActionType.Redirect302) + { + cleanPath = RedirectTokens.RemoveAnyRedirectTokens(cleanPath, queryStringCol); + } + + //get best friendly url from friendly url provider + string bestFriendlyUrl = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(tab, + cleanPath, + Globals.glbDefaultPage, + result.HttpAlias, + false, + settings, + Guid.Empty); + + //get what the friendly Url for this tab should be and stick it in as the redirect + //727 : using boolean because we wanted to get rid of the do301 before calculating the correct url + if (queryStringHas301Parm) + { + result.Action = ActionType.Redirect301; + if (result.Reason == RedirectReason.Not_Redirected) + { + result.Reason = RedirectReason.Unfriendly_Url_1; + } + } + result.FinalUrl = bestFriendlyUrl; + result.RewritePath = pathOnly; + redirected = true; //mark as redirected + } + } + else + { + //redirect disallowed + //618: dont' clear if 302 redirect selected + if (result.Action != ActionType.Redirect302Now || result.Action != ActionType.Redirect302) + { + RedirectController.CancelRedirect(ref result, null, settings, "Redirect requested but cancelled because disallowed"); + } + } + } + } + else if (result.TabId > -1 && result.RedirectAllowed && result.Action == ActionType.CheckFor301) + { + //301 check was requested in earlier processing + //get the tab controller and retrieve the tab the request is for + //don't redirect unless allowed, the tab is valid, and it's not an admin or super tab + if (settings.RedirectUnfriendly) + { + TabInfo tab; + bool allowRedirect = CheckFor301RedirectExclusion(result.TabId, result.PortalId, true, out tab, settings); + if (allowRedirect && tab != null) + { + //remove the http alias from the url. Do this by putting the url back together from the request and removing the alias + string rewritePathOnly; + if (result.DoRewrite) + { + rewritePathOnly = result.RewritePath; + var pos = rewritePathOnly.IndexOf("default.aspx", StringComparison.OrdinalIgnoreCase); + if (pos > -1) + { + rewritePathOnly = rewritePathOnly.Substring(pos); + } + } + else + { + rewritePathOnly = requestUri.Host + requestUri.PathAndQuery; + } + + //remove the http alias from the path + int pathAliasEnd = rewritePathOnly.IndexOf(result.PortalAlias.HTTPAlias, StringComparison.InvariantCultureIgnoreCase); + if (pathAliasEnd > -1) + { + rewritePathOnly = rewritePathOnly.Substring(pathAliasEnd + result.PortalAlias.HTTPAlias.Length); + } + + rewritePathOnly = HttpUtility.UrlDecode(rewritePathOnly, Encoding.UTF8); + //now check to see if need to remove /default.aspx from the end of the requested Url + string requestedUrl = fullUrl; + int requestedUrlAliasEnd = requestedUrl.IndexOf(result.PortalAlias.HTTPAlias, StringComparison.InvariantCultureIgnoreCase) + + (result.PortalAlias.HTTPAlias + "/").Length; + if (requestedUrlAliasEnd > -1) + { + //818 : when a site root is used for a custom page Url, then check for max length within bounds + if ((requestedUrl.Length - requestedUrlAliasEnd) >= 12 && requestedUrl.Substring(requestedUrlAliasEnd).ToLower() == "default.aspx") + { + requestedUrl = requestedUrl.Substring(0, requestedUrl.Length - 12); + //12 = default.aspx length + } + } + + //what happens here is that the request is reverse-engineered to see if it matches what the friendly Url shoudl have been + //get what the friendly Url for this tab should be + string bestFriendlyUrl; + //819 : leaving /do301/check in Url because not using cleanPath to remove from + + string cleanPath = RedirectTokens.RemoveAnyRedirectTokensAndReasons(rewritePathOnly); + //string cleanPath = rewritePathOnly.Replace("&do301=check","");//remove check parameter if it exists + //cleanPath = cleanPath.Replace("&do301=true", "");//don't pass through internal redirect check parameter + cleanPath = cleanPath.Replace("&_aumdebug=true", ""); //remove debug parameter if it exists + + Match match = Regex.Match(rewritePathOnly, "(?:&(?.[^&]+)=$)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (match.Success) + { + //when the pathOnly value ends with '=' it means there is a query string pair with a key and no value + //make the assumption that this was passed in as a page name OTHER than default page + string pageName = match.Groups["parm"].Value; //get the last parameter in the list + + cleanPath = cleanPath.Replace(match.Value, ""); + //remove the last parameter from the path + + //generate teh friendly URl name with the last parameter as the page name, not a query string parameter + bestFriendlyUrl = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(tab, + cleanPath, + pageName + settings.PageExtension, + result.HttpAlias, + false, + settings, + Guid.Empty); + } + else + { + bestFriendlyUrl = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(tab, + cleanPath, + Globals.glbDefaultPage, + result.HttpAlias, + false, + settings, + Guid.Empty); + } + + //if the incomign request doesn't match the 'most friendly' url, a 301 Moved Permanently status is returned, along with the friendly url + //check the bestFriendlyUrl against either the url, or rawUrl (with and without host) + //in each case, the aumdebug parameter will be searched for and replaced + var urlDecode = HttpUtility.UrlDecode(requestedUrl); + if (urlDecode != null) + { + string rawUrlWithHost = StripDebugParameter(urlDecode.ToLower()); + //string rawUrlWithHost = StripDebugParameter(System.Web.HttpUtility.UrlDecode(scheme + requestUri.Host + requestUri.PathAndQuery).ToLower()); + string rawUrlWithHostNoScheme = StripDebugParameter(rawUrlWithHost.Replace(scheme, "")); + string bestFriendlyNoScheme = StripDebugParameter(bestFriendlyUrl.ToLower().Replace(scheme, "")); + string requestedPathNoScheme = StripDebugParameter(requestUri.AbsoluteUri.Replace(scheme, "").ToLower()); + string rawUrlLowerCase = StripDebugParameter(requestUri.AbsoluteUri.ToLower()); + + //check to see if just an alias redirect of an internal alias + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + + if (settings.InternalAliasList != null && settings.InternalAliasList.Count > 0 && primaryAliases.Count > 0) + { + var cpa = primaryAliases.GetAliasByPortalIdAndSettings(result); + if (cpa != null) + { + string chosenAlias = cpa.HTTPAlias.ToLower(); + foreach (InternalAlias ia in settings.InternalAliasList) + { + string internalAlias = ia.HttpAlias.ToLower(); + if (requestedPathNoScheme.Contains(internalAlias)) + { + //an internal alias has been used. + //replace this in the comparison charts to do a 'fair' comparison + requestedPathNoScheme = requestedPathNoScheme.Replace(internalAlias,chosenAlias); + rawUrlWithHost = rawUrlWithHost.Replace(scheme + internalAlias,scheme + chosenAlias); + rawUrlWithHostNoScheme = rawUrlWithHostNoScheme.Replace(internalAlias,chosenAlias); + rawUrlLowerCase = rawUrlLowerCase.Replace(internalAlias, chosenAlias); + break; + } + } + } + } + if (!(bestFriendlyNoScheme == requestedPathNoScheme + || bestFriendlyNoScheme == rawUrlWithHost + || bestFriendlyNoScheme == rawUrlWithHostNoScheme + || bestFriendlyNoScheme == HttpUtility.UrlDecode(requestedPathNoScheme) + || bestFriendlyNoScheme == rawUrlLowerCase)) + { + redirected = true; + result.Action = ActionType.Redirect301; + result.FinalUrl = bestFriendlyUrl; + if (result.Reason != RedirectReason.Custom_Tab_Alias && + result.Reason != RedirectReason.Deleted_Page && + result.Reason != RedirectReason.Disabled_Page) + { + result.Reason = RedirectReason.Unfriendly_Url_2; + } + result.DebugMessages.Add("Compared :" + bestFriendlyNoScheme + " [generated] -> " + requestedPathNoScheme + " [requested with no scheme]"); + result.DebugMessages.Add("Compared :" + bestFriendlyNoScheme + " [generated] -> " + rawUrlWithHost + " [requested with host and scheme]"); + result.DebugMessages.Add("Compared :" + bestFriendlyNoScheme + " [generated] -> " + rawUrlWithHostNoScheme + " [requested with host, no scheme]"); + result.DebugMessages.Add("Compared :" + bestFriendlyNoScheme + " [generated] -> " + HttpUtility.UrlDecode(requestedPathNoScheme) + " [requested and decoded]"); + result.DebugMessages.Add("Compared :" + bestFriendlyNoScheme + " [generated] -> " + rawUrlLowerCase + " [requested raw Url]"); + } + } + } + } + } + + if (result.RedirectAllowed && settings.RedirectWrongCase) + { + //check for redirects where a redirectToSubDomain is specified, + //redirect for Wrong case is specified, and there is a valid tab and it's not already redirected somewhere else + bool doRedirect = false; + string redirectPath = redirected ? result.FinalUrl : requestUri.AbsoluteUri; + string redirectPathOnly = redirectPath; + if (redirectPathOnly.Contains("?")) + { + redirectPathOnly = redirectPathOnly.Substring(0, redirectPathOnly.IndexOf("?", StringComparison.Ordinal)); + } + // Thanks Etienne for the fix for Diacritic Characters Terminal Loop! + // if the url contains url encoded characters, they appear here uppercase -> %C3%83%C2 + // decode the url to get back the original character and do proper casing comparison + string urlDecodedRedirectPath = HttpUtility.UrlDecode(redirectPathOnly); + + //check for wrong case redirection + if (urlDecodedRedirectPath != null && (settings.RedirectWrongCase && String.CompareOrdinal(urlDecodedRedirectPath, urlDecodedRedirectPath.ToLower()) != 0)) + { + TabInfo tab; + bool allowRedirect = CheckFor301RedirectExclusion(result.TabId, result.PortalId, true, out tab, settings); + + if (allowRedirect && !string.IsNullOrEmpty(settings.ForceLowerCaseRegex)) + { + //don't allow redirect if excluded from redirecting in the force lower case regex pattern (606) + allowRedirect = !Regex.IsMatch(redirectPath, settings.ForceLowerCaseRegex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + + if (allowRedirect) + { + //special case : when IIS automatically places /default.aspx on the end of the string, + //then don't try and redirect to the lower case /default.aspx, just let it through. + //we don't know whether IIS appended /Default.aspx on the end, however, we can guess + //if the redirectDefault.aspx is turned on (511) + if (settings.RedirectDefaultPage == false && redirectPathOnly.EndsWith(Globals.glbDefaultPage, StringComparison.InvariantCultureIgnoreCase)) + { + //ignore this, because it's just a redirect of the /Default.aspx to /default.aspx + } + else + { + redirectPath = redirectPath.Replace(redirectPathOnly, redirectPathOnly.ToLower()); + doRedirect = true; + result.Reason = RedirectReason.Not_Lower_Case; + } + } + } + if (doRedirect) + { + result.Action = ActionType.Redirect301; + result.FinalUrl = CheckForSiteRootRedirect(result.PortalAlias.HTTPAlias, redirectPath); + redirected = true; + } + } + } + return redirected; + } + + private static string StripDebugParameter(string url) + { + string result = Regex.Replace(url, @"(&|\?)_aumdebug=[a-zA-Z]+(?:&|$)", ""); + return result; + } + + private static bool CheckFor301RedirectExclusion(int tabId, int portalId, bool checkBaseUrls, out TabInfo tab, FriendlyUrlSettings settings) + { + bool doRedirect = false; + var tc = new TabController(); + tab = tc.GetTab(tabId, portalId, false); + //don't redirect unless allowed, the tab is valid, and it's not an admin or super tab + if (tab != null && tab.IsSuperTab == false) + { + if (checkBaseUrls && !tab.DoNotRedirect) + { + //no redirect for friendly url purposes if the tab is in the 'base friendly urls' section + doRedirect = !RewriteController.IsExcludedFromFriendlyUrls(tab, settings, true); + } + else + { + doRedirect = true; + } + } + return doRedirect; + } + + /// + /// Make sure any redirect to the site root doesn't append the nasty /default.aspx on the end + /// + /// + /// + /// + internal static string CheckForSiteRootRedirect(string alias, string destUrl) + { + //540 - don't append /default.aspx onto the end of a site root redirect. + if (destUrl.EndsWith(alias + "/" + Globals.glbDefaultPage, StringComparison.InvariantCultureIgnoreCase)) + { + //this is just the portal alias root + /defualt.aspx. + //we don't want that, just the portalAliasRoot + "/" + string aliasPlusSlash = alias + "/"; + //get everything up to the end of the portal alias + destUrl = destUrl.Substring(0, destUrl.IndexOf(aliasPlusSlash, StringComparison.Ordinal) + aliasPlusSlash.Length); + } + return destUrl; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/BasicFriendlyUrlProvider.cs b/DNN Platform/Library/Entities/Urls/BasicFriendlyUrlProvider.cs new file mode 100644 index 00000000000..5cb48c0948a --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/BasicFriendlyUrlProvider.cs @@ -0,0 +1,417 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal class BasicFriendlyUrlProvider : FriendlyUrlProviderBase + { + private const string RegexMatchExpression = "[^a-zA-Z0-9 ]"; + private readonly string _fileExtension; + private readonly bool _includePageName; + private readonly string _regexMatch; + + internal BasicFriendlyUrlProvider(NameValueCollection attributes) + : base(attributes) + { + //Read the attributes for this provider + _includePageName = String.IsNullOrEmpty(attributes["includePageName"]) || bool.Parse(attributes["includePageName"]); + _regexMatch = !String.IsNullOrEmpty(attributes["regexMatch"]) ? attributes["regexMatch"] : RegexMatchExpression; + _fileExtension = !String.IsNullOrEmpty(attributes["fileExtension"]) ? attributes["fileExtension"] : ".aspx"; + } + + #region Public Properties + + public string FileExtension + { + get { return _fileExtension; } + } + + public bool IncludePageName + { + get { return _includePageName; } + } + + public string RegexMatch + { + get { return _regexMatch; } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// AddPage adds the page to the friendly url + /// + /// + /// + /// The path to format. + /// The page name. + /// The formatted url + /// + /// [cnurse] 12/16/2004 created + /// + /// ----------------------------------------------------------------------------- + private string AddPage(string path, string pageName) + { + string friendlyPath = path; + if ((friendlyPath.EndsWith("/"))) + { + friendlyPath = friendlyPath + pageName; + } + else + { + friendlyPath = friendlyPath + "/" + pageName; + } + return friendlyPath; + } + + private string CheckPathLength(string friendlyPath, string originalpath) + { + if (friendlyPath.Length >= 260) + { + return Globals.ResolveUrl(originalpath); + } + return friendlyPath; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFriendlyAlias gets the Alias root of the friendly url + /// + /// + /// + /// The path to format. + /// The portal alias of the site. + /// Whether is a relative page path. + /// The formatted url + /// + /// [cnurse] 12/16/2004 created + /// + /// ----------------------------------------------------------------------------- + private string GetFriendlyAlias(string path, string portalAlias, bool isPagePath) + { + string friendlyPath = path; + string matchString = ""; + if (string.IsNullOrEmpty(portalAlias) == false) + { + if (HttpContext.Current.Items["UrlRewrite:OriginalUrl"] != null) + { + string httpAlias = Globals.AddHTTP(portalAlias).ToLowerInvariant(); + string originalUrl = + HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString().ToLowerInvariant(); + httpAlias = Globals.AddPort(httpAlias, originalUrl); + if (originalUrl.StartsWith(httpAlias)) + { + matchString = httpAlias; + } + if ((String.IsNullOrEmpty(matchString))) + { + //Manage the special case where original url contains the alias as + //http://www.domain.com/Default.aspx?alias=www.domain.com/child" + Match portalMatch = Regex.Match(originalUrl, "^?alias=" + portalAlias, RegexOptions.IgnoreCase); + if (!ReferenceEquals(portalMatch, Match.Empty)) + { + matchString = httpAlias; + } + } + + if ((String.IsNullOrEmpty(matchString))) + { + //Manage the special case of child portals + //http://www.domain.com/child/default.aspx + string tempurl = HttpContext.Current.Request.Url.Host + Globals.ResolveUrl(friendlyPath); + if (!tempurl.Contains(portalAlias)) + { + matchString = httpAlias; + } + } + + if ((String.IsNullOrEmpty(matchString))) + { + // manage the case where the current hostname is www.domain.com and the portalalias is domain.com + // (this occurs when www.domain.com is not listed as portal alias for the portal, but domain.com is) + string wwwHttpAlias = Globals.AddHTTP("www." + portalAlias); + if (originalUrl.StartsWith(wwwHttpAlias)) + { + matchString = wwwHttpAlias; + } + } + } + } + if ((!String.IsNullOrEmpty(matchString))) + { + if ((path.IndexOf("~", StringComparison.Ordinal) != -1)) + { + friendlyPath = friendlyPath.Replace(matchString.EndsWith("/") ? "~/" : "~", matchString); + } + else + { + friendlyPath = matchString + friendlyPath; + } + } + else + { + friendlyPath = Globals.ResolveUrl(friendlyPath); + } + if (friendlyPath.StartsWith("//") && isPagePath) + { + friendlyPath = friendlyPath.Substring(1); + } + return friendlyPath; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFriendlyQueryString gets the Querystring part of the friendly url + /// + /// + /// + /// The tab whose url is being formatted. + /// The path to format. + /// The Page name. + /// The formatted url + /// + /// [cnurse] 12/16/2004 created + /// [smcculloch]10/10/2005 Regex update for rewritten characters + /// + /// ----------------------------------------------------------------------------- + private string GetFriendlyQueryString(TabInfo tab, string path, string pageName) + { + string friendlyPath = path; + Match queryStringMatch = Regex.Match(friendlyPath, "(.[^\\\\?]*)\\\\?(.*)", RegexOptions.IgnoreCase); + string queryStringSpecialChars = ""; + if (!ReferenceEquals(queryStringMatch, Match.Empty)) + { + friendlyPath = queryStringMatch.Groups[1].Value; + friendlyPath = Regex.Replace(friendlyPath, Globals.glbDefaultPage, "", RegexOptions.IgnoreCase); + string queryString = queryStringMatch.Groups[2].Value.Replace("&", "&"); + if ((queryString.StartsWith("?"))) + { + queryString = queryString.TrimStart(Convert.ToChar("?")); + } + string[] nameValuePairs = queryString.Split(Convert.ToChar("&")); + for (int i = 0; i <= nameValuePairs.Length - 1; i++) + { + string pathToAppend = ""; + string[] pair = nameValuePairs[i].Split(Convert.ToChar("=")); + + //Add name part of name/value pair + if ((friendlyPath.EndsWith("/"))) + { + pathToAppend = pathToAppend + pair[0]; + } + else + { + pathToAppend = pathToAppend + "/" + pair[0]; + } + if ((pair.Length > 1)) + { + if ((!String.IsNullOrEmpty(pair[1]))) + { + if ((Regex.IsMatch(pair[1], _regexMatch) == false)) + { + //Contains Non-AlphaNumeric Characters + if ((pair[0].ToLower() == "tabid")) + { + if ((Regex.IsMatch(pair[1], "^\\d+$"))) + { + if (tab != null) + { + int tabId = Convert.ToInt32(pair[1]); + if ((tab.TabID == tabId)) + { + if ((string.IsNullOrEmpty(tab.TabPath) == false) && IncludePageName) + { + pathToAppend = tab.TabPath.Replace("//", "/").TrimStart('/') + "/" + pathToAppend; + } + } + } + } + } + pathToAppend = pathToAppend + "/" + HttpUtility.UrlPathEncode(pair[1]); + } + else + { + //Rewrite into URL, contains only alphanumeric and the % or space + if (String.IsNullOrEmpty(queryStringSpecialChars)) + { + queryStringSpecialChars = pair[0] + "=" + pair[1]; + } + else + { + queryStringSpecialChars = queryStringSpecialChars + "&" + pair[0] + "=" + pair[1]; + } + pathToAppend = ""; + } + } + else + { + pathToAppend = pathToAppend + "/" + HttpUtility.UrlPathEncode((' ').ToString()); + } + } + friendlyPath = friendlyPath + pathToAppend; + } + } + if ((!String.IsNullOrEmpty(queryStringSpecialChars))) + { + return AddPage(friendlyPath, pageName) + "?" + queryStringSpecialChars; + } + return AddPage(friendlyPath, pageName); + } + + private Dictionary GetQueryStringDictionary(string path) + { + string[] parts = path.Split('?'); + var results = new Dictionary(StringComparer.OrdinalIgnoreCase); + if ((parts.Length == 2)) + { + foreach (string part in parts[1].Split('&')) + { + string[] keyvalue = part.Split('='); + if ((keyvalue.Length == 2)) + { + results[keyvalue[0]] = keyvalue[1]; + } + } + } + + return results; + } + + #endregion + + #region Internal Methods + + internal override string FriendlyUrl(TabInfo tab, string path) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return FriendlyUrl(tab, path, Globals.glbDefaultPage, _portalSettings); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + return FriendlyUrl(tab, path, pageName, _portalSettings); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings settings) + { + return FriendlyUrl(tab, path, pageName, settings.PortalAlias.HTTPAlias); + } + + internal override string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias) + { + string friendlyPath = path; + bool isPagePath = (tab != null); + + if ((UrlFormat == UrlFormatType.HumanFriendly)) + { + if ((tab != null)) + { + Dictionary queryStringDic = GetQueryStringDictionary(path); + if ((queryStringDic.Count == 0 || (queryStringDic.Count == 1 && queryStringDic.ContainsKey("tabid")))) + { + friendlyPath = GetFriendlyAlias("~/" + tab.TabPath.Replace("//", "/").TrimStart('/') + ".aspx", portalAlias, true); + } + else if ((queryStringDic.Count == 2 && queryStringDic.ContainsKey("tabid") && queryStringDic.ContainsKey("language"))) + { + if (!tab.IsNeutralCulture) + { + friendlyPath = GetFriendlyAlias("~/" + tab.CultureCode + "/" + tab.TabPath.Replace("//", "/").TrimStart('/') + ".aspx", + portalAlias, + true) + .ToLower(); + } + else + { + friendlyPath = GetFriendlyAlias("~/" + queryStringDic["language"] + "/" + tab.TabPath.Replace("//", "/").TrimStart('/') + ".aspx", + portalAlias, + true) + .ToLower(); + } + } + else + { + if (queryStringDic.ContainsKey("ctl") && !queryStringDic.ContainsKey("language")) + { + switch (queryStringDic["ctl"].ToLowerInvariant()) + { + case "terms": + friendlyPath = GetFriendlyAlias("~/terms.aspx", portalAlias, true); + break; + case "privacy": + friendlyPath = GetFriendlyAlias("~/privacy.aspx", portalAlias, true); + break; + case "login": + friendlyPath = (queryStringDic.ContainsKey("returnurl")) + ? GetFriendlyAlias("~/login.aspx?ReturnUrl=" + queryStringDic["returnurl"], portalAlias, true) + : GetFriendlyAlias("~/login.aspx", portalAlias, true); + break; + case "register": + friendlyPath = (queryStringDic.ContainsKey("returnurl")) + ? GetFriendlyAlias("~/register.aspx?returnurl=" + queryStringDic["returnurl"], portalAlias, true) + : GetFriendlyAlias("~/register.aspx", portalAlias, true); + break; + default: + //Return Search engine friendly version + return GetFriendlyQueryString(tab, GetFriendlyAlias(path, portalAlias, true), pageName); + } + } + else + { + //Return Search engine friendly version + return GetFriendlyQueryString(tab, GetFriendlyAlias(path, portalAlias, true), pageName); + } + } + } + } + else + { + //Return Search engine friendly version + friendlyPath = GetFriendlyQueryString(tab, GetFriendlyAlias(path, portalAlias, isPagePath), pageName); + } + + friendlyPath = CheckPathLength(Globals.ResolveUrl(friendlyPath), path); + + return friendlyPath; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/BrowserTypes.cs b/DNN Platform/Library/Entities/Urls/BrowserTypes.cs new file mode 100644 index 00000000000..744f072a340 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/BrowserTypes.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum BrowserTypes + { + Normal, + Mobile + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/CacheController.cs b/DNN Platform/Library/Entities/Urls/CacheController.cs new file mode 100644 index 00000000000..fec32131ee5 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/CacheController.cs @@ -0,0 +1,962 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.IO; +using System.Threading; +using System.Web.Caching; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class CacheController + { + private static CacheItemRemovedReason cacheItemRemovedReason; + private static bool LogRemovedReason; + private CacheItemRemovedCallback onRemovePageIndex; + + #region Cache Keys + + private const string PageIndexKey = "url_PageIndex"; + private const string PageIndexDepthKey = "url_PageIndexDepth"; + private const string UrlDictKey = "url_UrlDict"; + private const string UrlPortalsKey = "url_UrlPortals"; + private const string CustomAliasTabsKey = "url_CustomAliasTabsKey"; + private const string PortalAliasListKey = "url_PortalAliasList"; + private const string PortalsKey = "url_Portals"; + private const string CustomPortalAliasesKey = "url_CustomAliasList"; + private const string FriendlyUrlSettingsKey = "url_FriendlyUrlSettings"; + private const string RedirectActionsKey = "url_ParameterRedirectActions_{0}"; + private const string RewriteActionsKey = "url_ParameterRewriteActions_{0}"; + private const string PortalAliasRegexesKey = "url_PortalAliasRegex"; + private const string UserProfileActionsKey = "url_UserProfileActions"; + private const string PortalModuleProvidersForTabKey = "url_ModuleProvidersForTab_{0}_{1}"; + private const string PortalModuleProvidersAllTabsKey = "url_ModuleProvidersAllTabs_{0}"; + private const string PortalModuleProviderTabsKey = "url_PortalModuleProviderTabs_{0}"; + private const string AlwaysCallProviderTabsKey = "url_AlwaysCallProviderTabs_{0}"; + private const string HomePageSkinsKey = "url_HomePageSkins_{0}"; + private const string TabPathsKey = "url_TabPathsKey_{0}"; + + internal const string VanityUrlLookupKey = "url_VanityUrlLookup_{0}"; + + #endregion + + #region Private Methods + + private static CacheDependency GetPortalsCacheDependency() + { + var keys = new List {"DNN_PortalDictionary"}; + var portalsDepedency = new CacheDependency(null, keys.ToArray()); + return portalsDepedency; + } + + private CacheDependency GetTabsCacheDependency(IEnumerable portalIds) + { + var keys = new List(); + foreach (int portalId in portalIds) + { + const string cacheKey = DataCache.TabCacheKey; + string key = string.Format(cacheKey, portalId); + key = "DNN_" + key; //add on the DNN_ prefix + keys.Add(key); + } + //get the portals list dependency + var portalKeys = new List(); + if (portalKeys.Count > 0) + { + keys.AddRange(portalKeys); + } + var tabsDependency = new CacheDependency(null, keys.ToArray()); + return tabsDependency; + } + + private static void SetPageCache(string key, object value, FriendlyUrlSettings settings) + { + SetPageCache(key, value, null, settings, null); + } + + private static void SetPageCache(string key, object value, DNNCacheDependency dependency, FriendlyUrlSettings settings, CacheItemRemovedCallback callback) + { + DateTime absoluteExpiration = DateTime.Now.Add(settings.CacheTime); + DataCache.SetCache(key, + value, + dependency, + absoluteExpiration, + Cache.NoSlidingExpiration, + CacheItemPriority.AboveNormal, + callback); + } + + private static void SetPortalCache(string key, object value, FriendlyUrlSettings settings) + { + var absoluteExpiration = DateTime.Now.Add(new TimeSpan(24, 0, 0)); + if (settings != null) + { + absoluteExpiration = DateTime.Now.Add(settings.CacheTime); + } + //857 : use cache dependency for portal alias cache + if (settings != null) + { + DataCache.SetCache(key, + value, + new DNNCacheDependency(GetPortalsCacheDependency()), + absoluteExpiration, + Cache.NoSlidingExpiration); + } + else + { + DataCache.SetCache(key, value, absoluteExpiration); + } + } + + #endregion + + #region Internal Methods + + /// + /// Finds the best match friendlyurlparms.config file path + /// + /// The portalId to search for. -1 if all portals required. + /// + /// If a non-zero length string, a valid file path. If a zero length string, no file was found. + /// + /// First priority is a file called n.friendlyurlparms.config, in the root path + /// Next priority is a file called portals\n\friendlyurlparms.config, in the portal path + /// Last priority is the friendlyurlparms.config file, in the root path + /// Task no 807 + /// + internal static string FindFriendlyUrlParmsConfigFilePath(int portalId, out bool portalSpecificFound) + { + string result = ""; + portalSpecificFound = false; + const string fileName = "friendlyUrlParms.config"; + string rootPath = Globals.ApplicationMapPath + "\\"; + + string filePath; + if (portalId > -1) //specific portal + { + //first look in the root folder with the portalid as a prefix + filePath = rootPath + portalId.ToString() + "." + fileName; + } + else //no specific portal + { + filePath = rootPath + fileName; // just the pathname + } + if (File.Exists(filePath)) + { + result = filePath; + if (portalId > -1) //if there was a portal specified, this was a portal specific path + { + portalSpecificFound = true; + } + } + else + { + //no portal specific name in the root folder + if (portalId > -1) // at this point, only interested if a specific portal is requested + { + var pc = new PortalController(); + PortalInfo portal = pc.GetPortal(portalId); + if (portal != null) + { + //looking for the file in the portal folder + string portalPath = portal.HomeDirectoryMapPath; + filePath = portalPath + fileName; // just the pathname + if (File.Exists(filePath)) + { + result = filePath; + portalSpecificFound = true; + } + } + } + if (String.IsNullOrEmpty(result)) + { + //nothing matching found : now just looking for the root path + filePath = rootPath + fileName; + if (File.Exists(filePath)) + { + result = filePath; + portalSpecificFound = false; + } + } + } + return result; + } + + internal static List GetAlwaysCallProviderTabs(int portalId) + { + List result = null; + string key = string.Format(AlwaysCallProviderTabsKey, portalId); + var tabIdsToAlwaysCall = (int[])DataCache.GetCache(key); + if (tabIdsToAlwaysCall != null) + { + result = new List(tabIdsToAlwaysCall); + } + return result; + } + + //770 : customised portal alias per-tab + internal static List GetCustomAliasesFromCache() + { + object raw = DataCache.GetCache(CustomPortalAliasesKey); + return (raw != null) ? (List)raw : null; + } + + /// + /// Retrieve the Url Dictionary for the installation. + /// + /// + /// + /// + /// + /// + internal void GetFriendlyUrlIndexFromCache(out SharedDictionary> urlDict, + out List urlPortals, + out SharedDictionary customAliasTabs) + { + urlDict = null; + urlPortals = null; + customAliasTabs = null; + object rawDict = DataCache.GetCache(UrlDictKey); //contains a dictionary of tabs for all portals + object rawPortals = DataCache.GetCache(UrlPortalsKey); + //contas a list of portals for which we have retrieved the tabs + object rawCustomAliasTabs = DataCache.GetCache(CustomAliasTabsKey); + //contains a dictionary of tabs with custom aliases, for all portals + if (rawDict != null) + { + urlDict = (SharedDictionary>)rawDict; + } + if (rawPortals != null) + { + urlPortals = (List)rawPortals; + } + if (rawCustomAliasTabs != null) + { + customAliasTabs = (SharedDictionary)rawCustomAliasTabs; + } + } + + internal static Hashtable GetHomePageSkinsFromCache(int portalId) + { + string key = string.Format(HomePageSkinsKey, portalId); + var result = (Hashtable)DataCache.GetCache(key); + return result; + } + + internal static List GetListOfTabsWithProviders(int portalId, FriendlyUrlSettings settings) + { + List result = null; + string key = string.Format(PortalModuleProviderTabsKey, portalId); + var tabIdsForPortal = (int[])DataCache.GetCache(key); + if (tabIdsForPortal != null) + { + result = new List(tabIdsForPortal); + } + return result; + } + + internal void GetPageIndexFromCache(out SharedDictionary dict, + out SharedDictionary portalDepthInfo, + FriendlyUrlSettings settings) + { + object raw = DataCache.GetCache(PageIndexKey); + if (raw != null) + { + dict = (SharedDictionary)raw; + raw = DataCache.GetCache(PageIndexDepthKey); + portalDepthInfo = (SharedDictionary)raw; + } + else + { + dict = null; + portalDepthInfo = null; + } + } + + internal static Dictionary> GetParameterRedirects(FriendlyUrlSettings settings, int portalId, ref List messages) + { + string redirectActionKey = string.Format(RedirectActionsKey, portalId); //cached one portal at a time + if (messages == null) + { + messages = new List(); + } + var redirectActions = (Dictionary>)DataCache.GetCache(redirectActionKey); + if (redirectActions == null) + { + try + { + redirectActions = new Dictionary>(); + //807 : look for portal specific files + bool portalSpecific; + string fileName = FindFriendlyUrlParmsConfigFilePath(portalId, out portalSpecific); + if (fileName != "") + { + redirectActions.LoadFromXmlFile(fileName, portalId, portalSpecific, ref messages); + } + CacheDependency fileDependency = null; + if (File.Exists(fileName)) + { + fileDependency = new CacheDependency(fileName); + } + + if (settings != null) + { + DateTime absoluteExpiration = DateTime.Now.Add(settings.CacheTime); + DataCache.SetCache(redirectActionKey, redirectActions, new DNNCacheDependency(fileDependency), absoluteExpiration, Cache.NoSlidingExpiration); + } + else + { + DataCache.SetCache(redirectActionKey, redirectActions, new DNNCacheDependency(fileDependency)); + } + } + catch (Exception ex) + { + //log the exception + Services.Exceptions.Exceptions.LogException(ex); + messages.Add("Exception: " + ex.Message + "\n" + ex.StackTrace); + } + } + return redirectActions; + } + + internal static Dictionary> GetParameterReplacements(FriendlyUrlSettings settings, int portalId, ref List messages) + { + string replaceActionKey = "replaceActions:" + portalId.ToString(); + var replaceActions = (Dictionary>)DataCache.GetCache(replaceActionKey); + if (messages == null) + { + messages = new List(); + } + if (replaceActions == null) + { + replaceActions = new Dictionary>(); + try + { + bool portalSpecific; + string fileName = FindFriendlyUrlParmsConfigFilePath(portalId, out portalSpecific); + if (!string.IsNullOrEmpty(fileName)) + { + replaceActions.LoadFromXmlFile(fileName, portalId, portalSpecific, ref messages); + } + CacheDependency cacheDependency = null; + if (replaceActions.Count > 0) + { + //only set filename dependency if file exists + cacheDependency = new CacheDependency(fileName); + } + + DateTime expiration = DateTime.MaxValue; + DataCache.SetCache(replaceActionKey, replaceActions, new DNNCacheDependency(cacheDependency), expiration, settings.CacheTime); + } + catch (Exception ex) + { + Services.Exceptions.Exceptions.LogException(ex); + messages.Add("Exception: " + ex.Message + "\n" + ex.StackTrace); + } + } + return replaceActions; + } + + internal static Dictionary> GetParameterRewrites(int portalId, ref List messages, Guid parentTraceId) + { + string rewriteActionKey = string.Format(RewriteActionsKey, portalId.ToString()); + if (messages == null) + { + messages = new List(); + } + var rewriteActions = (Dictionary>)DataCache.GetCache(rewriteActionKey); + if (rewriteActions == null) + { + try + { + rewriteActions = new Dictionary>(); + bool portalSpecific; + //807 : new change to look for portal rule files in portal specific locations + string filename = FindFriendlyUrlParmsConfigFilePath(portalId, out portalSpecific); + if (!string.IsNullOrEmpty(filename)) + { + rewriteActions.LoadFromXmlFile(filename, portalId, portalSpecific, ref messages); + } + CacheDependency fileDependency = null; + if (File.Exists(filename)) + { + fileDependency = new CacheDependency(filename); + } + + DataCache.SetCache(rewriteActionKey, rewriteActions, new DNNCacheDependency(fileDependency)); + } + catch (Exception ex) + { + Services.Exceptions.Exceptions.LogException(ex); + messages.Add("Exception: " + ex.Message + "\n" + ex.StackTrace); + } + } + return rewriteActions; + } + + internal static OrderedDictionary GetPortalAliasesRegexesFromCache() + { + object raw = DataCache.GetCache(PortalAliasRegexesKey); + return (raw != null) ? (OrderedDictionary)raw : null; + } + + internal static List GetProvidersForTabAndPortal(int tabId, + int portalId, + FriendlyUrlSettings settings, + out bool noSuchProvider, + Guid parentTraceId) + { + //get list of tabids in this portal that have providers + noSuchProvider = false; + List allCachedProviders = null; + + List tabsWithProviders = GetListOfTabsWithProviders(portalId, settings); + bool checkThisTab = true, checkAllTabs = true; //going to check all tabs, unless find otherwise in the cache + if (tabsWithProviders != null) + { + checkAllTabs = tabsWithProviders.Contains(RewriteController.AllTabsRewrite); + + checkThisTab = tabsWithProviders.Contains(tabId); + + if (!checkThisTab && !checkAllTabs) + { + noSuchProvider = true; //we got the list of tabs, there is no provider for this tab + } + } + + if (checkAllTabs) + { + //the portal has an 'all tabs' provider in it + string allTabsKey = string.Format(PortalModuleProvidersAllTabsKey, portalId); + var cachedAllTabsProviders = (List)DataCache.GetCache(allTabsKey); + if (cachedAllTabsProviders != null) + { + allCachedProviders = new List(); + allCachedProviders.AddRange(cachedAllTabsProviders); + } + } + + if (checkThisTab) //the specified tab + { + //tab exists, get the providers for this tab + string key = string.Format(PortalModuleProvidersForTabKey, portalId, tabId); + var cachedTabProviders = (List)DataCache.GetCache(key); + if (cachedTabProviders != null) + { + if (allCachedProviders == null) + { + allCachedProviders = new List(); + } + allCachedProviders.AddRange(cachedTabProviders); + } + } + return allCachedProviders; + } + + internal static SharedDictionary GetTabPathsFromCache(int portalId) + { + return (SharedDictionary)DataCache.GetCache(string.Format(TabPathsKey, portalId)); + } + + internal static void StoreAlwaysCallProviderTabs(int portalId, List alwaysCallTabids, FriendlyUrlSettings settings) + { + if (alwaysCallTabids != null) + { + SetPageCache(string.Format(AlwaysCallProviderTabsKey, portalId), alwaysCallTabids.ToArray(), settings); + } + } + + internal static void StoreCustomAliasesInCache(List aliases, FriendlyUrlSettings settings) + { + DateTime absoluteExpiration = DateTime.Now.Add(new TimeSpan(24, 0, 0)); + if (settings != null) + { + absoluteExpiration = DateTime.Now.Add(settings.CacheTime); + } + + DataCache.SetCache(CustomPortalAliasesKey, aliases, absoluteExpiration); + } + + /// + /// Store the Url Dictionary (all tab urls / tabids) for the installation + /// + /// + /// + /// + /// + /// + /// + /// + internal void StoreFriendlyUrlIndexInCache(SharedDictionary> urlDict, + List urlPortals, + SharedDictionary customAliasTabs, + FriendlyUrlSettings settings, + string reason) + { + if (settings.LogCacheMessages) + { + onRemovePageIndex = RemovedPageIndexCallBack; + } + else + { + onRemovePageIndex = null; + } + + LogRemovedReason = settings.LogCacheMessages; + + SetPageCache(UrlDictKey, urlDict, new DNNCacheDependency(GetTabsCacheDependency(urlPortals)), settings, onRemovePageIndex); + + SetPageCache(UrlPortalsKey, urlPortals, settings); + SetPageCache(CustomAliasTabsKey, customAliasTabs, settings); + + if (settings.LogCacheMessages) + { + var elc = new EventLogController(); + + var logValue = new LogInfo { LogTypeKey = "HOST_ALERT" }; + logValue.AddProperty("Url Rewriting Caching Message", "Friendly Url Index built and Stored in Cache."); + logValue.AddProperty("Build Reason", reason); + logValue.AddProperty("Cache Key", UrlDictKey); + using (urlDict.GetReadLock()) + { + logValue.AddProperty("Item Count", urlDict.Values.Count.ToString()); + } + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + logValue.AddProperty("Item added to cache", "Url Portals object added to cache. Key:" + UrlPortalsKey + " Items: " + urlPortals.Count.ToString()); + logValue.AddProperty("Item added to cache", "Custom Alias Tabs added to cache. Key:" + CustomAliasTabsKey + " Items: " + customAliasTabs.Count.ToString()); + elc.AddLog(logValue); + } + } + + internal static void StoreHomePageSkinsInCache(int portalId, Hashtable homePageSkins) + { + if (homePageSkins != null && homePageSkins.Count > 0) + { + DataCache.SetCache(string.Format(HomePageSkinsKey, portalId), homePageSkins); + } + } + + /// + /// This method stores a list of tabIds for the specific portal in the cache + /// This is used to lookup and see if there are any providers to load for a tab, + /// without having to store individual tabid/portaldId provider lists for every tab + /// If a tab doesn't appear on this cached list, then the cache isn't checked + /// for that particular tabid/portalId combination + /// + /// + /// + /// + internal static void StoreListOfTabsWithProviders(List providers, int portalId, FriendlyUrlSettings settings) + { + //go through the list of providers and store all the tabs that they are configured for + var providersWithTabs = new List(); + var providersWithTabsStr = new List(); + foreach (ExtensionUrlProvider provider in providers) + { + if (provider.ProviderConfig.AllTabs) + { + if (providersWithTabs.Contains(RewriteController.AllTabsRewrite) == false) + { + providersWithTabs.Add(RewriteController.AllTabsRewrite); + providersWithTabsStr.Add("AllTabs"); + } + } + if (provider.AlwaysUsesDnnPagePath(portalId) == false) + { + if (providersWithTabs.Contains(RewriteController.SiteRootRewrite) == false) + { + providersWithTabs.Add(RewriteController.SiteRootRewrite); + providersWithTabsStr.Add("NoPath"); + } + } + foreach (int providerTabId in provider.ProviderConfig.TabIds) + { + if (providersWithTabs.Contains(providerTabId) == false) + { + providersWithTabs.Add(providerTabId); + providersWithTabsStr.Add(providerTabId.ToString()); + } + } + } + + //store list as array in cache + string key = string.Format(PortalModuleProviderTabsKey, portalId); + SetPageCache(key, providersWithTabs.ToArray(), settings); + if (settings.LogCacheMessages) + { + var elc = new EventLogController(); + var logValue = new LogInfo { LogTypeKey = "HOST_ALERT" }; + logValue.AddProperty("Url Rewriting Caching Message", "Portal Module Providers Tab List stored in cache"); + logValue.AddProperty("Cache Item Key", key); + logValue.AddProperty("PortalId", portalId.ToString()); + logValue.AddProperty("Provider With Tabs", string.Join(",", providersWithTabsStr.ToArray())); + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + elc.AddLog(logValue); + } + } + + internal static void StoreModuleProvidersForPortal(int portalId, FriendlyUrlSettings settings, List providers) + { + //get the key for the portal module providers + string allTabsKey = string.Format(PortalModuleProvidersAllTabsKey, portalId); + //get the providers that are on all tabs + var allTabsProviders = new List(); + //holds all providers, indexed by tabId + var tabsProviders = new Dictionary>(); + var tabIdStr = new List(); + int providerCount = 0; + foreach (ExtensionUrlProvider provider in providers) + { + if (provider.ProviderConfig.AllTabs) + { + allTabsProviders.Add(provider); + } + else + { + foreach (int tabId in provider.ProviderConfig.TabIds) + { + List thisTabProviders; + if (tabsProviders.ContainsKey(tabId)) + { + thisTabProviders = tabsProviders[tabId]; + thisTabProviders.Add(provider); + tabsProviders[tabId] = thisTabProviders; //assign back to position in tabs + } + else + { + thisTabProviders = new List { provider }; + tabsProviders.Add(tabId, thisTabProviders); + tabIdStr.Add(tabId.ToString()); + } + } + providerCount++; + } + //store the list of providers where the provider might be called with no valid TabId, because + //the provider allows for Urls with no DNN Page path, which means the TabId can't be identified + //by the Url Rewriter. This identifies the Provider as using a 'siteRootRewrite' + if (provider.AlwaysUsesDnnPagePath(portalId) == false) + { + List noPathProviders; + //add this one + if (tabsProviders.ContainsKey(RewriteController.SiteRootRewrite)) + { + noPathProviders = tabsProviders[RewriteController.SiteRootRewrite]; + noPathProviders.Add(provider); + tabsProviders[RewriteController.SiteRootRewrite] = noPathProviders; + //assign back to position in tabs + } + else + { + noPathProviders = new List { provider }; + tabsProviders.Add(RewriteController.SiteRootRewrite, noPathProviders); + tabIdStr.Add("NoPath"); + } + } + } + //now add the two collections to the cache + if (allTabsProviders.Count > 0) + { + SetPageCache(allTabsKey, allTabsProviders, settings); + } + if (tabsProviders.Count > 0) + { + foreach (int tabId in tabsProviders.Keys) + { + SetPageCache(string.Format(PortalModuleProvidersForTabKey, portalId, tabId), tabsProviders[tabId], settings); + } + } + + if (settings.LogCacheMessages) + { + var elc = new EventLogController(); + var logValue = new LogInfo { LogTypeKey = "HOST_ALERT" }; + logValue.AddProperty("Url Rewriting Caching Message", "Extension Url Providers stored in cache"); + logValue.AddProperty("PortalId/TabIds", portalId.ToString() + "/" + string.Join(",", tabIdStr.ToArray())); + logValue.AddProperty("All Tabs Providers Count", allTabsProviders.Count.ToString()); + logValue.AddProperty("Portal Tabs Providers Count", providerCount.ToString()); + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + elc.AddLog(logValue); + } + } + + + internal void StorePageIndexInCache(SharedDictionary tabDictionary, + SharedDictionary portalDepthInfo, + FriendlyUrlSettings settings, + string reason) + { + onRemovePageIndex = settings.LogCacheMessages ? (CacheItemRemovedCallback) RemovedPageIndexCallBack : null; + + //get list of portal ids for the portals we are storing in the page index + var portalIds = new List(); + using (portalDepthInfo.GetReadLock()) + { + portalIds.AddRange(portalDepthInfo.Keys); + } + + //783 : use cache dependency to manage page index instead of triggerDictionaryRebuild regex. + SetPageCache(PageIndexKey, tabDictionary, new DNNCacheDependency(GetTabsCacheDependency(portalIds)), settings, onRemovePageIndex); + + SetPageCache(PageIndexDepthKey, portalDepthInfo, settings); + + LogRemovedReason = settings.LogCacheMessages; + + if (settings.LogCacheMessages) + { + var elc = new EventLogController(); + var logValue = new LogInfo {LogTypeKey = "HOST_ALERT"}; + + logValue.AddProperty("Url Rewriting Caching Message", "Page Index built and Stored in Cache"); + logValue.AddProperty("Reason", reason); + logValue.AddProperty("Cache Item Key", PageIndexKey); + using (tabDictionary.GetReadLock()) + { + logValue.AddProperty("Item Count", tabDictionary.Count.ToString()); + } + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + elc.AddLog(logValue); + } + } + + internal static void StorePortalAliasesInCache(SharedDictionary aliases, FriendlyUrlSettings settings) + { + SetPortalCache(PortalAliasListKey, aliases, settings); + } + + internal static void StorePortalAliasesRegexesInCache(OrderedDictionary regexList, FriendlyUrlSettings settings) + { + SetPortalCache(PortalAliasRegexesKey, regexList, settings); + } + + internal void StoreTabPathsInCache(int portalId, SharedDictionary tabPathDictionary, FriendlyUrlSettings settings) + { + SetPageCache(string.Format(TabPathsKey, portalId), + tabPathDictionary, + new DNNCacheDependency(GetTabsCacheDependency(new List { portalId })), + settings, + null); + } + + #endregion + + #region Public Methods + + public static void FlushFriendlyUrlSettingsFromCache() + { + DataCache.RemoveCache(FriendlyUrlSettingsKey); + } + + public static void FlushPageIndexFromCache() + { + DataCache.RemoveCache(UrlDictKey); + DataCache.RemoveCache(PageIndexKey); + DataCache.RemoveCache(PageIndexDepthKey); + DataCache.RemoveCache(UrlPortalsKey); + DataCache.RemoveCache(UserProfileActionsKey); + DataCache.RemoveCache(PortalAliasListKey); + DataCache.RemoveCache(PortalAliasRegexesKey); + DataCache.RemoveCache(TabPathsKey); + } + + /// + /// Returns a portal info object for the portal + /// + /// + /// + /// This method wraps the PortalController.GetPortal method, and adds a check if the reuslt is null.. + /// + public static PortalInfo GetPortal(int portalId, bool exceptionOnNull) + { + PortalInfo pi = null; + //775 : change to use threadsafe dictionary + SharedDictionary portals = (SharedDictionary)DataCache.GetCache(PortalsKey) ?? + new SharedDictionary(); + + using (portals.GetWriteLock()) + { + if (portals.ContainsKey(portalId)) + { + //portal found, return + pi = portals[portalId]; + } + else + { + try + { + //if not found, get from database + var pc = new PortalController(); + pi = pc.GetPortal(portalId); + + if (pi == null) + { + // Home page redirect loop when using default language not en-US and first request with secondary language + //calls get portal using culture code to support + string cultureCode = PortalController.GetActivePortalLanguage(portalId); + pi = pc.GetPortal(portalId, cultureCode); + } + if (pi != null) + { + // Home page redirect loop when using default language not en-US and first request with secondary language + //check for correct, default language code in portal object + string portalCultureCode = pi.CultureCode; + if (portalCultureCode != null && + String.CompareOrdinal(portalCultureCode, pi.DefaultLanguage) != 0) + { + //portal culture code and default culture code are not the same. + //this means we will get the incorrect home page tab id + //call back and get the correct one as per the default language + PortalInfo defaultLangPortal = pc.GetPortal(portalId, pi.DefaultLanguage); + if (defaultLangPortal != null) + { + pi = defaultLangPortal; + } + } + } + if (pi != null) + { + //add to dictionary and re-store in cache + portals.Add(pi.PortalID, pi); + DataCache.SetCache(PortalsKey, portals); //store back in dictionary + } + } +// ReSharper disable EmptyGeneralCatchClause + catch +// ReSharper restore EmptyGeneralCatchClause + { + //912: capture as fall back any exception resulting from doing a portal lookup in 6.x + //this happens when portalId = -1 + //no long, no handling, just passonwards with null portal + } + } + } + + if (exceptionOnNull && pi == null) + { + throw new NullReferenceException("No Portal Found for portalid : " + portalId.ToString()); + } + return pi; + } + + public void RemovedPageIndexCallBack(string k, object v, CacheItemRemovedReason r) + { + cacheItemRemovedReason = r; +#if (DEBUG) + if (LogRemovedReason) + { + var elc = new EventLogController(); + var logValue = new LogInfo { LogTypeKey = "HOST_ALERT" }; + + string itemName; + string count; + List portalCounts = null; + switch (k) + { + case "DNN_" + PageIndexKey: + itemName = "Page Index"; + //user profile actions + try + { + DataCache.RemoveCache(UserProfileActionsKey); + } + catch (ConfigurationErrorsException) + { + //do nothing, this means the web.config file was overwritten, and thus the cache + //was cleared. + } + if (v != null && v.GetType() == typeof(SharedDictionary)) + { + count = "Item Count: " + ((SharedDictionary)v).Values.Count.ToString(); + } + else + { + count = "N/a"; + } + + break; + case "DNN_" + UrlDictKey: + itemName = "Friendly Url List"; + if (v != null && + v.GetType() == typeof(SharedDictionary>)) + { + var friendlyUrls = (SharedDictionary>)v; + portalCounts = new List(); + using (friendlyUrls.GetReadLock()) + { + count = "Portal Count: " + friendlyUrls.Count.ToString(); + foreach (int key in friendlyUrls.Keys) + { + SharedDictionary portalUrls = friendlyUrls[key]; + using (portalUrls.GetReadLock()) + { + portalCounts.Add("Portal " + key.ToString() + " Item Count :" + portalUrls.Count.ToString()); + } + } + } + } + else + { + count = "N/a"; + } + break; + default: + itemName = "Url Rewriter Cache Item"; + count = ""; + break; + } + //add log values + logValue.AddProperty("Url Rewriting Caching Message", itemName + " Cache item Removed."); + logValue.AddProperty("Reason", cacheItemRemovedReason.ToString()); + logValue.AddProperty("Cache Item Key", k); + logValue.AddProperty("Item Count", count); + if (portalCounts != null) + { + int i = 0; + foreach (string item in portalCounts) + { + logValue.AddProperty("Item " + i.ToString(), item); + i++; + } + } + //System.Diagnostics.Trace.Assert(k != null, "k == " + k); + elc.AddLog(logValue); + } +#endif + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/CollectionExtensions.cs b/DNN Platform/Library/Entities/Urls/CollectionExtensions.cs new file mode 100644 index 00000000000..933e6669633 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/CollectionExtensions.cs @@ -0,0 +1,333 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +using DotNetNuke.Collections.Internal; + +namespace DotNetNuke.Entities.Urls +{ + public static class CollectionExtensions + { + public static void LoadFromXmlFile(this Dictionary> actions, string fileName, int portalId, bool portalSpecific, ref List messages) + { + if (messages == null) + { + throw new ArgumentNullException("messages"); + } + messages = new List(); + if (File.Exists(fileName)) + { + var rdr = new XmlTextReader(fileName); + while (rdr.Read()) + { + switch (rdr.NodeType) + { + case XmlNodeType.Element: + if (rdr.Name == "parameterReplace") + { + //now set up the action + string portalIdRaw = rdr.GetAttribute("portalId"); + int rulePortalId = -1; + if (portalIdRaw != null) + { + Int32.TryParse(portalIdRaw, out rulePortalId); + } + //807 : if portal specific then import all regardless of portal id specified + if (rulePortalId == portalId || rulePortalId == -1 || portalSpecific) + { + int actionCount = 0; + string tabIdRaw = rdr.GetAttribute("tabIds") ?? rdr.GetAttribute("tabId"); + string tabNames = rdr.GetAttribute("tabNames"); + string name = rdr.GetAttribute("name"); + List tabIds = XmlHelpers.TabIdsFromAttributes(tabIdRaw, tabNames, portalId, + ref messages); + foreach (int tabId in tabIds) + { + var action = new ParameterReplaceAction + { + LookFor = rdr.GetAttribute("lookFor"), + ReplaceWith = rdr.GetAttribute("replaceWith"), + PortalId = portalId, + Name = name, + TabId = tabId + }; + string changeToSiteRootRaw = rdr.GetAttribute("changeToSiteRoot"); + bool changeToSiteRoot; + bool.TryParse(changeToSiteRootRaw, out changeToSiteRoot); + action.ChangeToSiteRoot = changeToSiteRoot; + + List tabActionCol; + if (actions.ContainsKey(action.TabId)) + { + tabActionCol = actions[action.TabId]; + } + else + { + tabActionCol = new List(); + actions.Add(action.TabId, tabActionCol); + } + tabActionCol.Add(action); + + actionCount++; + messages.Add(name + " replace actions added:" + actionCount.ToString()); + } + } + } + break; + + case XmlNodeType.EndElement: + break; + } + } + rdr.Close(); + } + else + { + messages.Add("File not Found: " + fileName); + } + } + + /// + /// Returns all the redirect rules for the specified portal + /// + /// + /// + /// + /// If true, all rules belong to supplied portalId, even if not specified. + /// + /// 807 : change to allow specificatoin of assumption that all rules belong to the supplied portal + public static void LoadFromXmlFile(this Dictionary> actions, string fileName, int portalId, bool portalSpecific, ref List messages) + { + if (messages == null) + { + messages = new List(); + } + if (File.Exists(fileName)) + { + var rdr = new XmlTextReader(fileName); + while (rdr.Read()) + { + switch (rdr.NodeType) + { + case XmlNodeType.Element: + if (rdr.Name == "parameterRedirect") + { + var tabMessages = new List(); + int actionCount = 0; + //now set up the action + string portalIdRaw = rdr.GetAttribute("rulePortalId"); + if (string.IsNullOrEmpty(portalIdRaw)) + { + portalIdRaw = rdr.GetAttribute("portalId"); + } + int rulePortalId = -1; + if (portalIdRaw != null) + { + Int32.TryParse(portalIdRaw, out rulePortalId); + } + if (rulePortalId == portalId || rulePortalId == -1 || portalSpecific) + //if portal specific, all rules are assumed to belong to the portal + { + string tabIdRaw = rdr.GetAttribute("tabIds"); + string tabNames = rdr.GetAttribute("tabNames"); + string name = rdr.GetAttribute("name"); + string fromSiteRootRaw = rdr.GetAttribute("fromSiteRoot"); + string fromDefaultRaw = rdr.GetAttribute("fromDefault"); + string changeToSiteRootRaw = rdr.GetAttribute("changeToSiteRoot"); + bool fromDefault; + bool fromSiteRoot; + bool changeToSiteRoot; + bool.TryParse(fromDefaultRaw, out fromDefault); + bool.TryParse(fromSiteRootRaw, out fromSiteRoot); + bool.TryParse(changeToSiteRootRaw, out changeToSiteRoot); + List tabIds = XmlHelpers.TabIdsFromAttributes(tabIdRaw, tabNames, portalId, + ref tabMessages); + foreach (int tabId in tabIds) + { + var action = new ParameterRedirectAction + { + PortalId = portalId, + LookFor = rdr.GetAttribute("lookFor"), + RedirectTo = rdr.GetAttribute("redirectTo"), + Name = name, + Action = rdr.GetAttribute("action"), + ChangeToSiteRoot = changeToSiteRoot, + TabId = tabId + }; + if (fromDefault) + { + //check for 'fromDefault' attribute + action.ForDefaultPage = true; + action.TabId = -2; + } + else + { + //or support the older convention, which was to include a tabid of -2 + action.ForDefaultPage = tabId == -2; + } + if (fromSiteRoot) + { + action.TabId = -3; //site root marker + } + List tabActionCol; + if (actions.ContainsKey(action.TabId)) + { + tabActionCol = actions[action.TabId]; + } + else + { + tabActionCol = new List(); + actions.Add(action.TabId, tabActionCol); + } + tabActionCol.Add(action); + actionCount++; + } + messages.Add(name + " redirect actions added:" + actionCount.ToString()); + } + if (tabMessages.Count > 0) + { + messages.AddRange(tabMessages); + } + } + break; + + case XmlNodeType.EndElement: + break; + } + } + rdr.Close(); + } + } + + public static void LoadFromXmlFile(this Dictionary> actions, string fileName, int portalId, bool portalSpecific, ref List messages) + { + if (messages == null) + { + messages = new List(); + } + if (File.Exists(fileName)) + { + var rdr = new XmlTextReader(fileName); + while (rdr.Read()) + { + switch (rdr.NodeType) + { + case XmlNodeType.Element: + if (rdr.Name == "parameterRewrite") + { + string portalIdRaw = rdr.GetAttribute("portalId"); + int rulePortalId = -1; + int actionCount = 0; + if (portalIdRaw != null) + { + Int32.TryParse(portalIdRaw, out rulePortalId); + } + if (rulePortalId == portalId || rulePortalId == -1 || portalId == -1 || portalSpecific) + { + //now set up the action + string tabIdRaw = rdr.GetAttribute("tabIds"); + string tabNames = rdr.GetAttribute("tabNames"); + string name = rdr.GetAttribute("name"); + string fromSiteRootRaw = rdr.GetAttribute("fromSiteRoot"); + bool fromSiteRoot; + bool.TryParse(fromSiteRootRaw, out fromSiteRoot); + List tabIds = XmlHelpers.TabIdsFromAttributes(tabIdRaw, tabNames, portalId, + ref messages); + foreach (int tabId in tabIds) + { + var action = new ParameterRewriteAction + { + LookFor = rdr.GetAttribute("lookFor"), + RewriteTo = rdr.GetAttribute("rewriteTo"), + Name = name, + TabId = tabId + }; + if (fromSiteRoot) + { + action.ForSiteRoot = true; + action.TabId = -3; + } + else + { + //older rule specified tabid -3 meant site root + action.ForSiteRoot = tabId == -3; + } + + action.PortalId = portalId; + SharedList tabActionCol; + if (actions.ContainsKey(action.TabId)) + { + tabActionCol = actions[action.TabId]; + } + else + { + tabActionCol = new SharedList(); + actions.Add(action.TabId, tabActionCol); + } + tabActionCol.Add(action); + actionCount++; + } + messages.Add(name + " rewrite actions added:" + actionCount.ToString()); + } + } + + + break; + + case XmlNodeType.EndElement: + break; + } + } + rdr.Close(); + } + else + { + messages.Add("Filename does not exist:" + fileName); + } + } + + public static Dictionary CreateDictionaryFromString(string delimitedString, char pairSeparator, char separator) + { + var dictionary = new Dictionary(); + + if(!String.IsNullOrEmpty(delimitedString)) + { + var pairs = delimitedString.Split(pairSeparator); + foreach (string pair in pairs) + { + if (!String.IsNullOrEmpty(pair)) + { + var chars = pair.Split(separator); + dictionary[chars[0]] = chars[1]; + } + } + } + + return dictionary; + } + } +} diff --git a/DNN Platform/Library/Entities/Urls/Config/RewriterConfiguration.cs b/DNN Platform/Library/Entities/Urls/Config/RewriterConfiguration.cs new file mode 100644 index 00000000000..4159c0551b8 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/Config/RewriterConfiguration.cs @@ -0,0 +1,141 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml.Serialization; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Urls.Config +{ + [Serializable, XmlRoot("RewriterConfig")] + public class RewriterConfiguration + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (RewriterConfiguration)); + private RewriterRuleCollection _rules; + + public RewriterRuleCollection Rules + { + get + { + return _rules; + } + set + { + _rules = value; + } + } + + public static RewriterConfiguration GetConfig() + { + var config = new RewriterConfiguration {Rules = new RewriterRuleCollection()}; + FileStream fileReader = null; + string filePath = ""; + try + { + config = (RewriterConfiguration) DataCache.GetCache("RewriterConfig"); + if ((config == null)) + { + filePath = Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.SiteUrls); + + //Create a FileStream for the Config file + fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var doc = new XPathDocument(fileReader); + config = new RewriterConfiguration {Rules = new RewriterRuleCollection()}; + foreach (XPathNavigator nav in doc.CreateNavigator().Select("RewriterConfig/Rules/RewriterRule")) + { + var rule = new RewriterRule {LookFor = nav.SelectSingleNode("LookFor").Value, SendTo = nav.SelectSingleNode("SendTo").Value}; + config.Rules.Add(rule); + } + if (File.Exists(filePath)) + { + //Set back into Cache + DataCache.SetCache("RewriterConfig", config, new DNNCacheDependency(filePath)); + } + } + } + catch (Exception ex) + { + //log it + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("UrlRewriter.RewriterConfiguration", "GetConfig Failed"); + objEventLogInfo.AddProperty("FilePath", filePath); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(objEventLogInfo); + + } + finally + { + if (fileReader != null) + { + //Close the Reader + fileReader.Close(); + } + } + return config; + } + + public static void SaveConfig(RewriterRuleCollection rules) + { + if (rules != null) + { + var config = new RewriterConfiguration {Rules = rules}; + + //Create a new Xml Serializer + var ser = new XmlSerializer(typeof (RewriterConfiguration)); + + //Create a FileStream for the Config file + string filePath = Globals.ApplicationMapPath + "\\SiteUrls.config"; + if (File.Exists(filePath)) + { + //make sure file is not read-only + File.SetAttributes(filePath, FileAttributes.Normal); + } + var fileWriter = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write); + + //Open up the file to serialize + var writer = new StreamWriter(fileWriter); + + //Serialize the RewriterConfiguration + ser.Serialize(writer, config); + + //Close the Writers + writer.Close(); + fileWriter.Close(); + + //Set Cache + DataCache.SetCache("RewriterConfig", config, new DNNCacheDependency(filePath)); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/Config/RewriterRule.cs b/DNN Platform/Library/Entities/Urls/Config/RewriterRule.cs new file mode 100644 index 00000000000..ce99cc2e6e7 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/Config/RewriterRule.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Urls.Config +{ + [Serializable] + public class RewriterRule + { + private string _lookFor; + private string _sendTo; + + public string LookFor + { + get + { + return _lookFor; + } + set + { + _lookFor = value; + } + } + + public string SendTo + { + get + { + return _sendTo; + } + set + { + _sendTo = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/Config/RewriterRuleCollection.cs b/DNN Platform/Library/Entities/Urls/Config/RewriterRuleCollection.cs new file mode 100644 index 00000000000..29be821e099 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/Config/RewriterRuleCollection.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Entities.Urls.Config +{ + [Serializable] + public class RewriterRuleCollection : CollectionBase + { + public virtual RewriterRule this[int index] + { + get + { + return (RewriterRule) List[index]; + } + set + { + List[index] = value; + } + } + + public void Add(RewriterRule r) + { + InnerList.Add(r); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/CustomUrlDictController.cs b/DNN Platform/Library/Entities/Urls/CustomUrlDictController.cs new file mode 100644 index 00000000000..865b2f177ad --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/CustomUrlDictController.cs @@ -0,0 +1,217 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal static class CustomUrlDictController + { + #region Private Methods + + /// + /// Returns a list of tab and redirects from the database, for the specified portal + /// Assumes that the dictionary should have any existing items replaced if the portalid is specified + /// and the portal tabs already exist in the dictionary. + /// + /// + /// + /// + /// + /// + /// Each dictionary entry in the return value is a complex data type of another dictionary that is indexed by the url culture. If there is + /// only one culture for the Url, it will be that culture. + /// + /// + private static SharedDictionary> BuildUrlDictionary(SharedDictionary> existingTabs, + int portalId, + FriendlyUrlSettings settings, + ref SharedDictionary customAliasTabs) + { + //fetch tabs with redirects + var tabs = FriendlyUrlController.GetTabs(portalId, false, null, settings); + if (existingTabs == null) + { + existingTabs = new SharedDictionary>(); + } + if (customAliasTabs == null) + { + customAliasTabs = new SharedDictionary(); + } + + + //go through each tab in the found list + foreach (TabInfo tab in tabs.Values) + { + //check the custom alias tabs collection and add to the dictionary where necessary + foreach (var customAlias in tab.CustomAliases) + { + string key = tab.TabID.ToString() + ":" + customAlias.Key; + using (customAliasTabs.GetWriteLock()) //obtain write lock on custom alias Tabs + { + if (customAliasTabs.ContainsKey(key) == false) + { + customAliasTabs.Add(key, customAlias.Value); + } + } + } + + foreach (TabUrlInfo redirect in tab.TabUrls) + { + if (redirect.HttpStatus == "200") + { + string url = redirect.Url; + //770 : add in custom alias into the tab path for the custom Urls + if (redirect.PortalAliasUsage != PortalAliasUsageType.Default && redirect.PortalAliasId > 0) + { + //there is a custom http alias specified for this portal alias + var pac = new PortalAliasController(); + PortalAliasInfo alias = pac.GetPortalAliasByPortalAliasID(redirect.PortalAliasId); + if (alias != null) + { + string customHttpAlias = alias.HTTPAlias; + url = customHttpAlias + "::" + url; + } + } + string cultureKey = redirect.CultureCode.ToLower(); + int tabid = tab.TabID; + using (existingTabs.GetWriteLock()) + { + if (existingTabs.ContainsKey(tabid) == false) + { + var entry = new SharedDictionary(); + using (entry.GetWriteLock()) + { + entry.Add(cultureKey, url); + } + //871 : use lower case culture code as key + existingTabs.Add(tab.TabID, entry); + } + else + { + SharedDictionary entry = existingTabs[tabid]; + //replace tab if existing but was retreieved from tabs call + if (tab.PortalID == portalId || portalId == -1) + { + using (entry.GetWriteLock()) + { + if (entry.ContainsKey(cultureKey) == false) + { + //add the culture and set in parent dictionary + //871 : use lower case culture code as key + entry.Add(cultureKey, url); + existingTabs[tabid] = entry; + } + } + } + } + } + } + } + } + return existingTabs; + } + + #endregion + + #region Internal Methods + + /// + /// returns a tabId indexed dictionary of Friendly Urls + /// + /// + /// + /// + /// + /// + /// + /// + internal static SharedDictionary> FetchCustomUrlDictionary(int portalId, + bool forceRebuild, + bool bypassCache, + FriendlyUrlSettings settings, + out SharedDictionary customAliasForTabs, + Guid parentTraceId) + { + SharedDictionary> urlDict; + //this contains a list of all tabs for all the portals that have been retrieved + List urlPortals; //this contains a list of the portals that have been retrieved + //get the objects from the cache + var cc = new CacheController(); + cc.GetFriendlyUrlIndexFromCache(out urlDict, out urlPortals, out customAliasForTabs); + + if (urlDict != null && forceRebuild == false && bypassCache == false) + { + if (urlPortals == null) + //no portals retrieved from cache, but was a dictionary. Bit weird, but we'll run with it + { + urlPortals = new List(); + } + + //check to see if this portal has been included in the dict + if (urlPortals.Contains(portalId) == false) + { + //ok, there is a url dictionary, but this portal isn't in it, so + //put it in and get the urls for this portal + //this call appends extra portals to the list + urlDict = BuildUrlDictionary(urlDict, portalId, settings, ref customAliasForTabs); + urlPortals.Add(portalId); + + cc.StoreFriendlyUrlIndexInCache(urlDict, + urlPortals, + customAliasForTabs, settings, + "Portal Id " + portalId.ToString() + " added to index."); + } + } + else //either values are null (Not in cache) or we want to force the rebuild, or we want to bypass the cache + { + //rebuild the dictionary for this portal + urlDict = BuildUrlDictionary(urlDict, portalId, settings, ref customAliasForTabs); + urlPortals = new List { portalId }; //always rebuild the portal list + if (bypassCache == false) //if we are to cache this item (byPassCache = false) + { + //cache these items + string reason = forceRebuild ? "Force Rebuild of Index" : "Index not in cache"; + cc.StoreFriendlyUrlIndexInCache(urlDict, urlPortals, customAliasForTabs, settings, reason); + } + } + return urlDict; + } + + internal static void InvalidateDictionary() + { + CacheController.FlushPageIndexFromCache(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/DNNPageForwardType.cs b/DNN Platform/Library/Entities/Urls/DNNPageForwardType.cs new file mode 100644 index 00000000000..f85d35bd853 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/DNNPageForwardType.cs @@ -0,0 +1,32 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum DNNPageForwardType + { + NoForward, + Redirect302, + Redirect301 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/DeletedTabHandlingType.cs b/DNN Platform/Library/Entities/Urls/DeletedTabHandlingType.cs new file mode 100644 index 00000000000..3a4528398a2 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/DeletedTabHandlingType.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum DeletedTabHandlingType + { + Do301RedirectToPortalHome, + Do404Error + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/DupKeyCheck.cs b/DNN Platform/Library/Entities/Urls/DupKeyCheck.cs new file mode 100644 index 00000000000..fd94c7490b9 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/DupKeyCheck.cs @@ -0,0 +1,44 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The DupKeyCheck class is a small helper class used to maintain state of what to do with a duplicate Url when building the Url Index. + /// + internal class DupKeyCheck + { + public DupKeyCheck(string tabKey, string tabIdOriginal, string tabPath, bool isDeleted) + { + TabKey = tabKey; + TabIdOriginal = tabIdOriginal; + TabPath = tabPath; + IsDeleted = isDeleted; + } + + public string TabKey { get; set; } + public string TabIdOriginal { get; set; } + public string TabPath { get; set; } + public bool IsDeleted { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ExtensionUrlProvider.cs b/DNN Platform/Library/Entities/Urls/ExtensionUrlProvider.cs new file mode 100644 index 00000000000..06d010d46b5 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ExtensionUrlProvider.cs @@ -0,0 +1,209 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Data; +using System.Text; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// This abstract class is to provide a inherited base class for a custom module friendly url provider. All public methods must be overridden to provide the basis for a custom module provider. + /// + [Serializable] + public abstract class ExtensionUrlProvider + { + public ExtensionUrlProviderInfo ProviderConfig { get; internal set; } + + #region Protected Methods + + protected string CleanNameForUrl(string urlValue, FriendlyUrlOptions options) + { + bool changed; + string result = options != null + ? FriendlyUrlController.CleanNameForUrl(urlValue, options, out changed) + : FriendlyUrlController.CleanNameForUrl(urlValue, null, out changed); + + return result; + } + + protected string CleanNameForUrl(string urlValue, FriendlyUrlOptions options, out bool replacedUnwantedChars) + { + return FriendlyUrlController.CleanNameForUrl(urlValue, options, out replacedUnwantedChars); + } + + protected string CreateQueryStringFromParameters(string[] urlParms, int skipUpToPosition) + { + string result = ""; + int i = 0; + bool odd = true; + int size = urlParms.GetUpperBound(0) - skipUpToPosition; + if (size >= 0 && urlParms.GetUpperBound(0) >= 0) + { + var qs = new StringBuilder(urlParms.GetUpperBound(0)); + foreach (string urlPathPart in urlParms) + { + if (i > skipUpToPosition) //skip over the parts we don't want + { + if (odd) + { + qs.Append("&" + urlPathPart); + } + else + { + qs.Append("=" + urlPathPart); + } + //switch odd/even + odd = !odd; + } + i++; + } + result = qs.ToString(); + } + return result; + } + + protected string EnsureLeadingChar(string leading, string path) + { + return FriendlyUrlController.EnsureLeadingChar(leading, path); + } + + #endregion + + #region Abstract Methods + + /// + /// When true, output Urls from the provider for the specified portalId always include the current DotNetNuke page path (ie example.com/pagename/friendlyUrl) + /// When false, output Urls from the provider for the specified portalId may sometimes not include the current DotNetNUke page path (ie example.com/friendlyUrl) + /// + /// + /// Defaults to true. Must be set to false by the provider if any call to the 'ChangeFriendlyUrl' method results in the output + /// parameter 'useDnnPagePath' is false. If 'false' is possible, then 'false' must be returned in this method. + /// + public abstract bool AlwaysUsesDnnPagePath(int portalId); + + /// + /// Generates a new friendly Url based on the parameters supplied + /// + /// The current Tab the Friendly Url is for + /// The current friendly Url Path (minus alias) as generated by the Advanced Friendly Url provider + /// The current friendly Url options that apply to the current portal, as configured within the Extension Url Provider settings. These include space replacement values and other settings which should be incorporated into the Friendly Url generation. + /// The 'pageName' value that comes from the FriendlyUrl API of DNN. Normally this is the 'default.aspx' value (DotNetNuke.Common.Globals.glbDefaultPage). A value of 'default.aspx' is discarded. However, it may be a different value for other modules and if not default.aspx will be appended to the end of the Url. + /// This is a ref parameter, so it can either be left as-is, or changed to default.aspx or "" if no specific value is required. + /// Output parameter, must be set by module Friendly Url Provider. If true, the /pagename/ part of the Url will be removed, and the Url path will be relative from the site root (example.com/custom-module-path instead of example.com/pagename/custom-module-path) + /// A list of information messages used for both debug output and UI information. Add any informational message to this collection if desired. + /// Note using 'useDnnPagePath' = true requires having a specific tab returned from the TransformFriendlyUrlToQueryString below. Usage of the 'useDnnPagePath' implies the TransformFriendlyUrlToQueryString method returns a ?tabid=xx value in the querystring. + /// It also means the provider level property 'AlwaysUsesDnnPagePath' must return 'false' + /// Friendly Url for specified values. Return friendlyUrlPath if no change is made. + public abstract string ChangeFriendlyUrl(TabInfo tab, + string friendlyUrlPath, + FriendlyUrlOptions options, + string cultureCode, + ref string endingPageName, + out bool useDnnPagePath, + ref List messages); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public abstract bool CheckForRedirect(int tabId, + int portalid, + string httpAlias, + Uri requestUri, + NameValueCollection queryStringCol, + FriendlyUrlOptions options, + out string redirectLocation, + ref List messages); + + /// + /// This module returns any custom settings for the provider in a key/value pair. This is used when any customised settings are saved to the web.config file. + /// + /// A dictionary of key/value pairs, where the key represents the web.config attribute name, and the value is the value to be stored in the web.config file + /// Note: the key values are case sensitive, and should match any values read from the attributes collection in the provider constructor. If the provider has no custom attributes, return null or an empty dictionary. To remove a setting, add the value as a null. Null values in the dictionary are removed as attributes. + public abstract Dictionary GetProviderPortalSettings(); + + /// + /// Transforms a friendly Url into a querystring. Used as input into the rewriting process, after the Url Rewriting process has identified the correct DNN Page. + /// + /// string array of the friendly Url Path elements, separated by / + /// TabId of page the Friendly Url + /// PortalId of the Friendly Url + /// This method will be only called if there is no match between the Page Index entries this Provider supplies via the 'CreatePageIndex' method. This method is called + /// when a DNN page match is found in the requested path, and there are other parameters behind the page path. You should only return a TabId in the querystring, when the ChangeFriendlyUrl function is returning 'true' for the output value of 'useDnnPagePath'. + /// + /// Given a Url of example.com/pagename/key/value - this method will be called with key,value in the urlParms array with a page match on 'pagename'. The method should return 'key=value'. + /// Or, if given a Url of example.com/pagename/my-friendly-module-url, it should transform 'my-friendly-module-url' into whatever the module actually uses to build content. This might mean returning 'article=2354' derived from doing a specific lookup on 'my-friendly-module-url'. + /// Warning: It's unwise to do a specific database lookup for each call of this method. This method needs to be high-performance so should use a stateless method (ie, regex parse) or, if looking up database values, cached hashtables or thread-safe dictionaries. + /// + /// Querystring value in key=value format, which will be used as an input to the rewriting function. + public abstract string TransformFriendlyUrlToQueryString(string[] urlParms, + int tabId, int portalId, + FriendlyUrlOptions options, + string cultureCode, + PortalAliasInfo portalAlias, + ref List messages, + out int status, + out string location); + + #endregion + + #region Public Methods + + /// + /// This method is called to check whether to do a Url Rewrite on all Tabs specified by the provider + /// + /// The current portalId + /// True if the rewriter should be called, even if there are no Url parameters (ie, just plain DNN page Url). False if not. + /// Does not affect the calling of this provider when there are parameters supplied in the Url - that is determined by the tabIds property + /// of the provider. + public virtual bool AlwaysCallForRewrite(int portalId) + { + return false; + } + + public string EnsureNotLeadingChar(string leading, string path) + { + return FriendlyUrlController.EnsureNotLeadingChar(leading, path); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderController.cs b/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderController.cs new file mode 100644 index 00000000000..07fa9be1f75 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderController.cs @@ -0,0 +1,712 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Framework; +using DotNetNuke.Services.Log.EventLog; + +using Assembly = System.Reflection.Assembly; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class ExtensionUrlProviderController + { + private static readonly object providersBuildLock = new object(); + + #region Private Methods + + private static void ClearCache() + { + var portalController = new PortalController(); + foreach (PortalAliasInfo portal in portalController.GetPortals()) + { + ClearCache(portal.PortalID); + } + } + + private static void ClearCache(int portalId) + { + var cacheKey = String.Format("ExtensionUrlProviders_{0}", portalId); + DataCache.RemoveCache(cacheKey); + } + + + /// + /// Returns the providers to call. Returns tabid matches first, and any portal id matches after that. + /// + /// + /// + /// + /// + /// + private static List GetProvidersToCall(int tabId, + int portalId, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + List providers; + + //887 : introduce lockable code to prevent caching race errors + lock (providersBuildLock) + { + bool definitelyNoProvider; + //887 : use cached list of tabs instead of per-tab cache of provider + //get the list of providers to call based on the tab and the portal + var providersToCall = CacheController.GetProvidersForTabAndPortal(tabId, + portalId, + settings, + out definitelyNoProvider, + parentTraceId); + if (definitelyNoProvider == false && providersToCall == null) + //nothing in the cache, and we don't have a definitive 'no' that there isn't a provider + { + //get all providers for the portal + var allProviders = GetModuleProviders(portalId).Where(p => p.ProviderConfig.IsActive).ToList(); + + //store the list of tabs for this portal that have a provider attached + CacheController.StoreListOfTabsWithProviders(allProviders, portalId, settings); + + //stash the provider portals in the cache + CacheController.StoreModuleProvidersForPortal(portalId, settings, allProviders); + + //now check if there is a provider for this tab/portal combination + if (allProviders.Count > 0) + { + //find if a module is specific to a tab + providersToCall = new List(); + providersToCall.AddRange(allProviders); + } + } + //always return an instantiated provider collection + providers = providersToCall ?? (new List()); + } + + //return the collection of module providers + return providers; + } + + #endregion + + #region Internal Methods + + /// + /// Checks to see if any providers are marked as 'always call for rewrites' + /// + /// + /// + /// + /// + /// + internal static bool CheckForAlwaysCallProviders(int portalId, int tabId, FriendlyUrlSettings settings, Guid parentTraceId) + { + List alwaysCallTabids = CacheController.GetAlwaysCallProviderTabs(portalId); + bool checkForAlwaysCallResult = false; + if (alwaysCallTabids == null) + { + alwaysCallTabids = new List(); //create new list + //nothing in cache, build list + List providers = GetModuleProviders(portalId).Where(p => p.ProviderConfig.IsActive).ToList(); + foreach (ExtensionUrlProvider provider in providers) + { + //check the always call property + if (provider.AlwaysCallForRewrite(portalId)) + { + if (provider.ProviderConfig.AllTabs) + { + if (alwaysCallTabids.Contains(RewriteController.AllTabsRewrite) == false) + { + alwaysCallTabids.Add(RewriteController.AllTabsRewrite); + } + } + else + { + foreach (int providerTabId in provider.ProviderConfig.TabIds) + { + if (alwaysCallTabids.Contains(tabId) == false) + { + alwaysCallTabids.Add(providerTabId); + } + } + } + } + } + //now store back in cache + CacheController.StoreAlwaysCallProviderTabs(portalId, alwaysCallTabids, settings); + } + if (alwaysCallTabids.Contains(tabId) || alwaysCallTabids.Contains(RewriteController.AllTabsRewrite)) + { + checkForAlwaysCallResult = true; + } + return checkForAlwaysCallResult; + } + + internal static bool CheckForRedirect(Uri requestUri, + UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings, + out string location, + ref List messages, + Guid parentTraceId) + { + bool redirected = false; + location = ""; + ExtensionUrlProvider activeProvider = null; + try + { + List providersToCall = GetProvidersToCall(result.TabId, result.PortalId, settings, + parentTraceId); + if (providersToCall != null && providersToCall.Count > 0) + { + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + foreach (ExtensionUrlProvider provider in providersToCall) + { + activeProvider = provider; //for error handling + redirected = provider.CheckForRedirect(result.TabId, result.PortalId, result.HttpAlias, + requestUri, queryStringCol, options, out location, + ref messages); + if (redirected) + { + result.FinalUrl = location; + result.Reason = RedirectReason.Module_Provider_Redirect; + break; + } + } + } + } + catch (Exception ex) + { + //log module provider exception + LogModuleProviderExceptionInRequest(ex, "500 Internal Server Error", activeProvider, result, messages); + //return defaults + redirected = false; + location = ""; + string providerName = "Unknown"; + if (activeProvider != null) + { + providerName = activeProvider.ProviderConfig.ProviderName; + } + if (result != null) + { + result.DebugMessages.Add("Exception in provider [" + providerName + "] :" + ex.Message); + } + } + return redirected; + } + + /// + /// Returns boolean value is any loaded providers require checking of rewrite / redirect values from the site root (ie, not dnn tab path) + /// + /// + internal static bool CheckForSiteRootRewrite(int portalId, FriendlyUrlSettings settings, Guid parentTraceId) + { + var providers = GetProvidersToCall(RewriteController.SiteRootRewrite, portalId, settings, parentTraceId); + + //list should have returned all providers with site root rewrite, but double check here in case of faulty third-party logic + return providers.Any(provider => provider.AlwaysUsesDnnPagePath(portalId) == false); + } + + + internal static bool GetUrlFromExtensionUrlProviders(int portalId, + TabInfo tab, + FriendlyUrlSettings settings, + string friendlyUrlPath, + string cultureCode, + ref string endingPageName, + out string changedPath, + out bool changeToSiteRoot, + ref List messages, + Guid parentTraceId) + { + bool wasChanged = false; + changedPath = friendlyUrlPath; + changeToSiteRoot = false; + ExtensionUrlProvider activeProvider = null; + if (messages == null) + { + messages = new List(); + } + try + { + List providersToCall = GetProvidersToCall(tab.TabID, portalId, settings, + parentTraceId); + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + foreach (ExtensionUrlProvider provider in providersToCall) + { + activeProvider = provider; //keep for exception purposes + bool useDnnPagePath; + //go through and call each provider to generate the friendly urls for the module + string customPath = provider.ChangeFriendlyUrl(tab, + friendlyUrlPath, + options, + cultureCode, + ref endingPageName, + out useDnnPagePath, + ref messages); + + if (string.IsNullOrEmpty(endingPageName)) + { + endingPageName = Globals.glbDefaultPage; //set back to default.aspx if provider cleared it + } + //now check to see if a change was made or not. Don't trust the provider. + if (!string.IsNullOrEmpty(customPath)) + { + //was customPath any different to friendlyUrlPath? + if (String.CompareOrdinal(customPath, friendlyUrlPath) != 0) + { + wasChanged = true; + changedPath = customPath.Trim(); + changeToSiteRoot = !useDnnPagePath; //useDNNpagePath means no change to site root. + const string format = "Path returned from {0} -> path:{1}, ending Page:{2}, use Page Path:{3}"; + messages.Add(string.Format(format, provider.ProviderConfig.ProviderName, customPath, endingPageName, useDnnPagePath)); + break; //first module provider to change the Url is the only one used + } + } + } + } + catch (Exception ex) + { + LogModuleProviderExceptionInRequest(ex, "500 Internal Server Error", activeProvider, null, messages); + //reset all values to defaults + wasChanged = false; + changedPath = friendlyUrlPath; + changeToSiteRoot = false; + } + return wasChanged; + } + + internal static bool TransformFriendlyUrlPath(string newUrl, + string tabKeyVal, + string[] urlParms, + bool isSiteRootMatch, + ref UrlAction result, + FriendlyUrlSettings settings, + out string rewrittenUrl, + out bool newAction, + ref List messages, + Guid parentTraceId) + { + bool rewriteDone = false; + rewrittenUrl = newUrl; + newAction = false; + ExtensionUrlProvider activeProvider = null; + try + { + int tabId = result.TabId; + if (isSiteRootMatch) + { + tabId = RewriteController.SiteRootRewrite; + } + List providersToCall = GetProvidersToCall(tabId, + result.PortalId, + settings, + parentTraceId); + if (providersToCall != null && providersToCall.Count > 0) + { + //now check for providers by calling the providers + int upperBound = urlParms.GetUpperBound(0); + //clean extension off parameters array + var parms = new string[upperBound + 1]; + Array.ConstrainedCopy(urlParms, 0, parms, 0, upperBound + 1); + if (upperBound >= 0) + { + bool replaced; + parms[upperBound] = RewriteController.CleanExtension(parms[upperBound], settings, out replaced); + } + //get options from current settings + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + foreach (ExtensionUrlProvider provider in providersToCall) + { + //set active provider for exception handling + activeProvider = provider; + //call down to specific providers and see if we get a rewrite + string location; + int status; + string queryString = provider.TransformFriendlyUrlToQueryString(parms, + result.TabId, + result.PortalId, + options, + result.CultureCode, + result.PortalAlias, + ref messages, + out status, + out location); + if (status == 0 || status == 200) //either not set, or set to '200 OK'. + { + if (!string.IsNullOrEmpty(queryString) && queryString != newUrl) + { + rewriteDone = true; + //check for duplicate tabIds. + string qsRemainder = null; + if (Regex.IsMatch(queryString, @"tabid=\d+", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + //930 : look for other querystring information in the rewritten Url, or invalid rewritten urls can be created + //pattern to determine which tab matches + const string rewrittenUrlPattern = @"(?(?:\?|&)tabid=\d+)(?&[^=]+=[^&]*)*"; + //look for any other querystirng information in the already rewritten Url (ie language parameters) + Match rewrittenUrlMatch = Regex.Match(rewrittenUrl, rewrittenUrlPattern, + RegexOptions.IgnoreCase | + RegexOptions.CultureInvariant); + if (rewrittenUrlMatch.Groups["qs"].Success) + { + //keep any other querystring remainders + qsRemainder = rewrittenUrlMatch.Groups["qs"].Captures.Cast().Aggregate("", (current, qsCapture) => current + qsCapture.Value); //initialise + } + //supplied value overwrites existing value, so remove from the rewritten url + rewrittenUrl = Regex.Replace(rewrittenUrl, rewrittenUrlPattern, "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + if (rewrittenUrl.Contains("?") == false) + { + //use a leading ?, not a leading & + queryString = FriendlyUrlController.EnsureNotLeadingChar("&", queryString); + queryString = FriendlyUrlController.EnsureLeadingChar("?", queryString); + } + else + { + //use a leading &, not a leading ? + queryString = FriendlyUrlController.EnsureNotLeadingChar("?", queryString); + queryString = FriendlyUrlController.EnsureLeadingChar("&", queryString); + } + + //add querystring onto rewritten Url + rewrittenUrl += queryString; + if (qsRemainder != null) + { + rewrittenUrl += qsRemainder; + } + break; + } + } + else + { + switch (status) + { + case 301: + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Module_Provider_Rewrite_Redirect; + result.FinalUrl = location; + break; + case 302: + result.Action = ActionType.Redirect302; + result.Reason = RedirectReason.Module_Provider_Rewrite_Redirect; + result.FinalUrl = location; + break; + case 404: + result.Action = ActionType.Output404; + break; + case 500: + result.Action = ActionType.Output500; + break; + } + newAction = true; //not doing a 200 status + break; + } + } + } + } + catch (Exception ex) + { + //log module provider exception + LogModuleProviderExceptionInRequest(ex, "500 Internal Server Error", activeProvider, result, messages); + //reset values to initial + rewriteDone = false; + rewrittenUrl = newUrl; + newAction = false; + string providerName = "Unknown"; + if (activeProvider != null) + { + providerName = activeProvider.ProviderConfig.ProviderName; + } + if (result != null) + { + result.DebugMessages.Add("Exception in provider [" + providerName + "] :" + ex.Message); + } + } + return rewriteDone; + } + + #endregion + + #region Public Methods + + public static void DeleteProvider(ExtensionUrlProviderInfo urlProvider) + { + DataProvider.Instance().DeleteExtensionUrlProvider(urlProvider.ExtensionUrlProviderId); + ClearCache(); + } + + public static void DisableProvider(int providerId, int portalId) + { + DataProvider.Instance().UpdateExtensionUrlProvider(providerId, false); + ClearCache(portalId); + } + + public static void EnableProvider(int providerId, int portalId) + { + DataProvider.Instance().UpdateExtensionUrlProvider(providerId, true); + ClearCache(portalId); + } + + public static List GetProviders(int portalId) + { + return CBO.FillCollection(DataProvider.Instance().GetExtensionUrlProviders(portalId)); + } + + /// + /// Loads the module providers + /// + /// + /// + /// Note : similar copy for UI purposes in ConfigurationController.cs + public static List GetModuleProviders(int portalId) + { + var cacheKey = String.Format("ExtensionUrlProviders_{0}", portalId); + var moduleProviders = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, + 60, + CacheItemPriority.High, + portalId), + c => + { + var id = (int)c.Params[0]; + IDataReader dr = DataProvider.Instance().GetExtensionUrlProviders(id); + var providers = new List(); + var providerConfigs = CBO.FillCollection(dr, new List(), false); + + foreach (var providerConfig in providerConfigs) + { + var providerType = Reflection.CreateType(providerConfig.ProviderType); + var provider = Reflection.CreateObject(providerType) as ExtensionUrlProvider; + + if (provider != null) + { + provider.ProviderConfig = providerConfig; + provider.ProviderConfig.PortalId = id; + providers.Add(provider); + } + } + + if (dr.NextResult()) + { + //Setup Settings + while (dr.Read()) + { + var extensionUrlProviderId = Null.SetNullInteger(dr["ExtensionUrlProviderID"]); + var key = Null.SetNullString(dr["SettingName"]); + var value = Null.SetNullString(dr["SettingValue"]); + + var provider = providers.SingleOrDefault(p => p.ProviderConfig.ExtensionUrlProviderId == extensionUrlProviderId); + if (provider != null) + { + provider.ProviderConfig.Settings[key] = value; + } + } + } + + if (dr.NextResult()) + { + //Setup Tabs + while (dr.Read()) + { + var extensionUrlProviderId = Null.SetNullInteger(dr["ExtensionUrlProviderID"]); + var tabId = Null.SetNullInteger(dr["TabID"]); + + var provider = providers.SingleOrDefault(p => p.ProviderConfig.ExtensionUrlProviderId == extensionUrlProviderId); + if (provider != null && !provider.ProviderConfig.TabIds.Contains(tabId)) + { + provider.ProviderConfig.TabIds.Add(tabId); + } + } + } + + //Close reader + CBO.CloseDataReader(dr, true); + + return providers; + }); + + return moduleProviders; + } + + public static FriendlyUrlOptions GetOptionsFromSettings(FriendlyUrlSettings settings) + { + return new FriendlyUrlOptions + { + PunctuationReplacement = (settings.ReplaceSpaceWith != FriendlyUrlSettings.ReplaceSpaceWithNothing) + ? settings.ReplaceSpaceWith + : String.Empty, + SpaceEncoding = settings.SpaceEncodingValue, + MaxUrlPathLength = 200, + ConvertDiacriticChars = settings.AutoAsciiConvert, + RegexMatch = settings.RegexMatch, + IllegalChars = settings.IllegalChars, + ReplaceChars = settings.ReplaceChars, + ReplaceDoubleChars = settings.ReplaceDoubleChars, + ReplaceCharWithChar = settings.ReplaceCharacterDictionary, + PageExtension = settings.PageExtensionUsageType == PageExtensionUsageType.Never ? "" : settings.PageExtension + }; + } + + /// + /// logs an exception related to a module provider once per cache-lifetime + /// + /// + /// + /// + /// + /// + public static void LogModuleProviderExceptionInRequest(Exception ex, string status, + ExtensionUrlProvider provider, + UrlAction result, + List messages) + { + if (ex != null) + { + string moduleProviderName = "Unknown Provider"; + string moduleProviderVersion = "Unknown Version"; + if (provider != null) + { + moduleProviderName = provider.ProviderConfig.ProviderName; + moduleProviderVersion = provider.GetType().Assembly.GetName(false).Version.ToString(); + } + //this logic prevents a site logging an exception for every request made. Instead + //the exception will be logged once for the life of the cache / application restart or 1 hour, whichever is shorter. + //create a cache key for this exception type + string cacheKey = ex.GetType().ToString(); + //see if there is an existing object logged for this exception type + object existingEx = DataCache.GetCache(cacheKey); + if (existingEx == null) + { + //if there was no existing object logged for this exception type, this is a new exception + DateTime expire = DateTime.Now.AddHours(1); + DataCache.SetCache(cacheKey, cacheKey, expire); + //just store the cache key - it doesn't really matter + //create a log event + string productVer = Assembly.GetExecutingAssembly().GetName(false).Version.ToString(); + var elc = new EventLogController(); + var logEntry = new LogInfo {LogTypeKey = "GENERAL_EXCEPTION"}; + logEntry.AddProperty("Url Rewriting Extension Url Provider Exception", + "Exception in Url Rewriting Process"); + logEntry.AddProperty("Provider Name", moduleProviderName); + logEntry.AddProperty("Provider Version", moduleProviderVersion); + logEntry.AddProperty("Http Status", status); + logEntry.AddProperty("Product Version", productVer); + if (result != null) + { + logEntry.AddProperty("Original Path", result.OriginalPath ?? "null"); + logEntry.AddProperty("Raw Url", result.RawUrl ?? "null"); + logEntry.AddProperty("Final Url", result.FinalUrl ?? "null"); + + logEntry.AddProperty("Rewrite Result", !string.IsNullOrEmpty(result.RewritePath) + ? result.RewritePath + : "[no rewrite]"); + logEntry.AddProperty("Redirect Location", string.IsNullOrEmpty(result.FinalUrl) + ? "[no redirect]" + : result.FinalUrl); + logEntry.AddProperty("Action", result.Action.ToString()); + logEntry.AddProperty("Reason", result.Reason.ToString()); + logEntry.AddProperty("Portal Id", result.PortalId.ToString()); + logEntry.AddProperty("Tab Id", result.TabId.ToString()); + logEntry.AddProperty("Http Alias", result.PortalAlias != null ? result.PortalAlias.HTTPAlias : "Null"); + + if (result.DebugMessages != null) + { + int i = 1; + foreach (string debugMessage in result.DebugMessages) + { + string msg = debugMessage; + if (debugMessage == null) + { + msg = "[message was null]"; + } + logEntry.AddProperty("Debug Message[result] " + i.ToString(), msg); + i++; + } + } + } + else + { + logEntry.AddProperty("Result", "Result value null"); + } + if (messages != null) + { + int i = 1; + foreach (string msg in messages) + { + logEntry.AddProperty("Debug Message[raw] " + i.ToString(), msg); + i++; + } + } + logEntry.AddProperty("Exception Type", ex.GetType().ToString()); + logEntry.AddProperty("Message", ex.Message); + logEntry.AddProperty("Stack Trace", ex.StackTrace); + if (ex.InnerException != null) + { + logEntry.AddProperty("Inner Exception Message", ex.InnerException.Message); + logEntry.AddProperty("Inner Exception Stacktrace", ex.InnerException.StackTrace); + } + logEntry.BypassBuffering = true; + elc.AddLog(logEntry); + } + } + } + + public static void SaveProvider(ExtensionUrlProviderInfo provider) + { + provider.ExtensionUrlProviderId = DataProvider.Instance().AddExtensionUrlProvider( + provider.ExtensionUrlProviderId, + provider.DesktopModuleId, + provider.ProviderName, + provider.ProviderType, + provider.SettingsControlSrc, + provider.IsActive, + provider.RewriteAllUrls, + provider.RedirectAllUrls, + provider.ReplaceAllUrls); + } + + public static void SaveSetting(int providerId, int portalId, string settingName, string settingValue) + { + DataProvider.Instance().SaveExtensionUrlProviderSetting(providerId, portalId, settingName, settingValue); + ClearCache(portalId); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderInfo.cs b/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderInfo.cs new file mode 100644 index 00000000000..063cb2677cc --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ExtensionUrlProviderInfo.cs @@ -0,0 +1,111 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Entities.Urls +{ + public class ExtensionUrlProviderInfo : IHydratable + { + public ExtensionUrlProviderInfo() + { + ExtensionUrlProviderId = -1; + Settings = new Dictionary(); + TabIds = new List(); + } + + /// + /// When true, the module provider will be used for all tabs in the current portal. Including a specific tabid switches value to false. + /// + public bool AllTabs { get { return TabIds.Count == 0; } } + + /// + /// The DesktopModuleId is used to associate a particular Extension Url Provider with a specific DotNetNuke extension. + /// + /// + /// If the Extension provider is not associated with any particular DotNetNuke extension, return null. + /// + public int DesktopModuleId { get; set; } + + public int ExtensionUrlProviderId { get; set; } + + /// + /// When true, provider is active + /// + public bool IsActive { get; set; } + + public int PortalId { get; set; } + + public string ProviderName { get; set; } + + public string ProviderType { get; set; } + + /// + /// When true, TransformFriendlyUrl is called for every Url in the portal + /// When false, TransformFriendlyUrl is called only for tabs in the TabIds list + /// + public bool RewriteAllUrls { get; set; } + + /// + /// When true, CheckForRedirect is called for every Url in the portal + /// When false, CheckForRedirect is called only for tabs in the TabIds list + /// + public bool RedirectAllUrls { get; set; } + + /// + /// When true, ChangeFriendlyUrl is called for every generated Url called through the NavigateUrl API + /// When false, ChangeFriendlyUrl is called only for tabs in the TabIds list + /// + public bool ReplaceAllUrls { get; set; } + + public string SettingsControlSrc { get; set; } + + public Dictionary Settings { get; private set; } + + /// + /// Returns a list of TabIds where the module provider should be called when generating friendly urls + /// + public List TabIds { get; private set; } + + public int KeyID { get; set; } + + public void Fill(IDataReader dr) + { + ExtensionUrlProviderId = Null.SetNullInteger(dr["ExtensionUrlProviderId"]); + PortalId = Null.SetNullInteger(dr["PortalId"]); + DesktopModuleId = Null.SetNullInteger(dr["DesktopModuleId"]); + ProviderName = Null.SetNullString(dr["ProviderName"]); + ProviderType = Null.SetNullString(dr["ProviderType"]); + SettingsControlSrc = Null.SetNullString(dr["SettingsControlSrc"]); + IsActive = Null.SetNullBoolean(dr["IsActive"]); + RewriteAllUrls = Null.SetNullBoolean(dr["RewriteAllUrls"]); + RedirectAllUrls = Null.SetNullBoolean(dr["RedirectAllUrls"]); + ReplaceAllUrls = Null.SetNullBoolean(dr["ReplaceAllUrls"]); + } + + } +} diff --git a/DNN Platform/Library/Entities/Urls/FriendlyUrlController.cs b/DNN Platform/Library/Entities/Urls/FriendlyUrlController.cs new file mode 100644 index 00000000000..3e26ad6e223 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/FriendlyUrlController.cs @@ -0,0 +1,1294 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.ClientCapability; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; + +using Assembly = System.Reflection.Assembly; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class FriendlyUrlController + { + private static Dictionary _providerObjects; + + #region Constants + + private const string DisableMobileRedirectCookieName = "disablemobileredirect"; //dnn cookies + private const string DisableRedirectPresistCookieName = "disableredirectpresist"; //dnn cookies + + private const string DisableMobileRedirectQueryStringName = "nomo"; + //google uses the same name nomo=1 means do not redirect to mobile + + private const string MobileViewSiteCookieName = "dnn_IsMobile"; + private const string DisableMobileViewCookieName = "dnn_NoMobile"; + + #endregion + + #region Friendly Url Settings Control + + public static FriendlyUrlSettings GetCurrentSettings(int portalId) + { + return new FriendlyUrlSettings(portalId); + } + + #endregion + + #region Friendly Url Provider methods + + /// + /// Determines if the tab is excluded from FriendlyUrl Processing + /// + /// + /// + /// If true, we are checking for rewriting purposes, if false, we are checking for friendly Url Generating. + /// + private static bool IsExcludedFromFriendlyUrls(TabInfo tab, FriendlyUrlSettings settings, bool rewriting) + { + //note this is a duplicate of another method in RewriteController.cs + bool exclude = false; + string tabPath = (tab.TabPath.Replace("//", "/") + ";").ToLower(); + if (settings.UseBaseFriendlyUrls != null) + { + exclude = settings.UseBaseFriendlyUrls.ToLower().Contains(tabPath); + } + + return exclude; + } + + private static void SetExclusionProperties(TabInfo tab, FriendlyUrlSettings settings) + { + string tabPath = (tab.TabPath.Replace("//", "/") + ";").ToLower(); + tab.UseBaseFriendlyUrls = settings.UseBaseFriendlyUrls != null && settings.UseBaseFriendlyUrls.ToLower().Contains(tabPath); + } + /* + /// + /// Builds up a collection of the Friendly Urls for a tab + /// + /// The TabInfoEx object + /// Whether to add in the redirects for the 'standard' DNN urls + /// + /// The current friendly Url settings + /// Updated to insert where an ascii replacement or spaces-replaced replacement has been made (562) + private static void BuildFriendlyUrls(TabInfo tab, bool includeStdUrls, PortalSettings portalSettings, FriendlyUrlSettings settings) + { + + //unfriendly Url + if (includeStdUrls) + { + string stdUrl = Globals.glbDefaultPage + "?TabId=" + tab.TabID.ToString(); + string stdHttpStatus = "200"; + string httpAlias = portalSettings.PortalAlias.HTTPAlias; + string defaultCulture = portalSettings.DefaultLanguage; + var locales = LocaleController.Instance.GetLocales(portalSettings.PortalId); + + string baseFriendlyHttpStatus = "200"; + int seqNum = -1; + //check for custom redirects + //bool tabHasCustom200 = false; + var culturesWithCustomUrls = new List(); + if (tab.TabUrls.Count > 0) + { + //there are custom redirects for this tab + //cycle through all and collect the list of cultures where a + //custom redirect has been implemented + foreach (TabUrlInfo redirect in tab.TabUrls) + { + if (redirect.HttpStatus == "200" && !redirect.IsSystem) + { + //there is a custom redirect for this culture + //751 : use the default culture if the redirect doesn't have a valid culture set + string redirectCulture = redirect.CultureCode; + if (string.IsNullOrEmpty(redirectCulture)) + { + redirectCulture = portalSettings.DefaultLanguage; + } + + if (!culturesWithCustomUrls.Contains(redirectCulture)) + { + culturesWithCustomUrls.Add(redirectCulture); + } + } + } + } + + //add friendly urls first (sequence number goes in reverse) + if (Host.Host.UseFriendlyUrls) + { + //determine whether post process or use base by looking at current settings + SetExclusionProperties(tab, settings); + + //friendly Urls are switched on + //std = default.aspx?tabId=xx + //and page not excluded from redirects + bool onlyBaseUrls = tab.UseBaseFriendlyUrls; + //use base means only use Base Friendly Urls (searchFriendly) + + //if not using base urls, and redirect all unfriendly, and not in the list of pages to not redirect + if (!onlyBaseUrls & settings.RedirectUnfriendly && !tab.DoNotRedirect) + { + //all base urls will be 301 + baseFriendlyHttpStatus = "301"; + stdHttpStatus = "301"; + //default url 301'd if friendly Urls on and redirect unfriendly switch 'on' + } + var localeCodes = new List(); + if (!string.IsNullOrEmpty(tab.CultureCode)) + { + //the tab culture is specified, so skip all locales and only process those for the locale + localeCodes.Add(tab.CultureCode); + } + else + { + localeCodes.AddRange(from Locale lc in locales.Values select lc.Code); + } + foreach (string cultureCode in localeCodes) //go through and generate the urls for each language + { + string langQs = "&language=" + cultureCode; + if (cultureCode == defaultCulture) + { + langQs = ""; + } + + var improvedFriendlyUrls = new Dictionary(); + //call friendly url provider to get current friendly url (uses all settings) + string baseFriendlyUrl = GetFriendlyUrl(tab, + stdUrl + langQs, + Globals.glbDefaultPage, + portalSettings.PortalAlias.HTTPAlias, + settings); + + if (onlyBaseUrls == false) + { + //get the improved friendly Url for this tab + //improved friendly Url = 'human friendly' url generated by Advanced Friendly Url Provider : note call is made to ignore custom redirects + //this temp switch is to clear out the useBaseFriendlyUrls setting. The post-process setting means the generated + //friendly url will be a base url, and then replaced later when the page is finished. Because we want to pretend we're + //looking at the finished product, we clear out the value and restore it after the friendly url generation + string improvedFriendlyUrl = GetImprovedFriendlyUrl(tab, + stdUrl + langQs, + Globals.glbDefaultPage, + portalSettings, + true, + settings); + + improvedFriendlyUrls.Add("hfurl:" + cultureCode, improvedFriendlyUrl); + //get any other values + bool autoAsciiConvert = false; + bool replaceSpacesWith = false; + if (settings.AutoAsciiConvert) + { + //check to see that the ascii conversion would actually produce a different result + string changedTabPath = ReplaceDiacritics(tab.TabPath); + if (changedTabPath != tab.TabPath) + { + autoAsciiConvert = true; + } + } + if (settings.ReplaceSpaceWith != FriendlyUrlSettings.ReplaceSpaceWithNothing) + { + if (tab.TabName.Contains(" ")) + { + string tabPath = BuildTabPathWithReplacement(tab, " ", settings.ReplaceSpaceWith); + if (tabPath != tab.TabPath) + { + replaceSpacesWith = true; + } + } + } + if (autoAsciiConvert && replaceSpacesWith) + { + string replaceSpaceWith = settings.ReplaceSpaceWith; + settings.ReplaceSpaceWith = "None"; + settings.AutoAsciiConvert = false; + //get one without auto ascii convert, and replace spaces off + string impUrl = GetImprovedFriendlyUrl(tab, + stdUrl + langQs, + Globals.glbDefaultPage, + httpAlias, + true, + settings); + improvedFriendlyUrls.Add("aac:rsw:" + cultureCode, impUrl); + settings.AutoAsciiConvert = true; + //now get one with ascii convert on, and replace spaces still off + //impUrl = GetImprovedFriendlyUrl(tab, stdUrl, Globals.glbDefaultPage, httpAlias, true, settings); + //improvedFriendlyUrls.Add("aac", impUrl); + settings.ReplaceSpaceWith = replaceSpaceWith; + } + if (autoAsciiConvert && !replaceSpacesWith) + { + settings.AutoAsciiConvert = false; + //get one with auto ascii convert off + string impUrl = GetImprovedFriendlyUrl(tab, + stdUrl + langQs, + Globals.glbDefaultPage, + httpAlias, + true, + settings); + improvedFriendlyUrls.Add("aac:" + cultureCode, impUrl); + settings.AutoAsciiConvert = true; + } + if (!autoAsciiConvert && replaceSpacesWith) + { + string replaceSpaceWith = settings.ReplaceSpaceWith; + settings.ReplaceSpaceWith = "None"; + //get one with replace spaces off + string impUrl = GetImprovedFriendlyUrl(tab, + stdUrl + langQs, + Globals.glbDefaultPage, + httpAlias, + true, + settings); + improvedFriendlyUrls.Add("rsw:" + cultureCode, impUrl); + settings.ReplaceSpaceWith = replaceSpaceWith; + } + bool tabHasCustom200 = culturesWithCustomUrls.Contains(cultureCode); + foreach (string key in improvedFriendlyUrls.Keys) + { + string friendlyUrl = improvedFriendlyUrls[key]; + if (friendlyUrl != baseFriendlyUrl && friendlyUrl != "") + { + //if the improved friendly Url is different to the base friendly Url, + //then we will add it in as a 'fixed' url, except if the improved friendly Url + //is actually a redirect in the first place + bool found = false; + foreach (TabUrlInfo redirect in tab.TabUrls) + { + //compare each redirect to the improved friendly Url + //just in case it is the same + if (String.Compare(redirect.Url, friendlyUrl, StringComparison.OrdinalIgnoreCase) == 0) + { + found = true; + } + } + if (!found) + { + //ok if hte improved friendly Url isn't a tab redirect record, + //then add in the improved friendly Url as a 'fixed' url + var predefinedRedirect = new TabUrlInfo + { + TabId = tab.TabID, + CultureCode = cultureCode + }; + if (key.StartsWith("hfurl") == false) + { + //this means it's not the actual url, it's either a spaces replace, + //auto ascii or both output. It should be a 301 unless redirectunfriendly + //is off, or the page is excluded from redirects + if (settings.RedirectUnfriendly && !tab.DoNotRedirect) + { + predefinedRedirect.HttpStatus = "301"; //redirect to custom url + } + else + { + predefinedRedirect.HttpStatus = "200"; //allow it to work + } + } + else + { + //the hfurl key is the base human friendly url + if (tabHasCustom200 && (settings.RedirectUnfriendly && !tab.DoNotRedirect)) + { + predefinedRedirect.HttpStatus = "301"; + } + else + { + predefinedRedirect.HttpStatus = "200"; + //if no redirects, or not redirecting unfriendly, then 200 is OK + } + } + predefinedRedirect.Url = friendlyUrl; + predefinedRedirect.IsSystem = true; + predefinedRedirect.SeqNum = seqNum; + tab.TabUrls.Insert(0, predefinedRedirect); + seqNum--; + } + } + else + { + //improved Friendly Url same as base Friendly Url, so we 200 this one, regardless of redirection settings + if (tabHasCustom200 == false) + { + baseFriendlyHttpStatus = "200"; + } + } + } + } + //base friendly url + var baseFriendly = new TabUrlInfo + { + TabId = tab.TabID, + HttpStatus = (settings.RedirectUnfriendly == false || IsExcludedFromFriendlyUrls(tab, settings, true)) + ? "200" + : baseFriendlyHttpStatus, + CultureCode = cultureCode, + Url = baseFriendlyUrl, + IsSystem = true, + SeqNum = seqNum + }; + tab.TabUrls.Insert(0, baseFriendly); + seqNum--; + } + //standard url (/default.aspx?tabid=xx) + var std = new TabUrlInfo + { + TabId = tab.TabID, + HttpStatus = stdHttpStatus, + CultureCode = (tab.CultureCode == "") ? defaultCulture : tab.CultureCode, + Url = stdUrl, + IsSystem = true, + SeqNum = seqNum, + }; + tab.TabUrls.Insert(0, std); + seqNum--; + } + } + } + + /// + /// A reflection based call to the Friendly Url provider to get the 'base' (dnn standard) urls + /// + /// + /// + /// + /// + /// + /// + internal static string GetFriendlyUrl(TabInfo tab, string path, string defaultPage, string httpAlias, + FriendlyUrlSettings settings) + { + List messages; + object result = CallFriendlyUrlProviderMethod("BaseFriendlyUrl", out messages, tab, path, defaultPage, httpAlias, settings); + if (result == null) + { + return Globals.NavigateURL(tab.TabID); + } + return (string) result; + } + + internal static string GetImprovedFriendlyUrl(TabInfo tab, string path, string defaultPage, string httpAlias, + bool ignoreCustomRedirects) + { + FriendlyUrlSettings settings = GetCurrentSettings(tab.PortalID); + List messages; + return GetImprovedFriendlyUrl(tab, path, defaultPage, httpAlias, ignoreCustomRedirects, settings, + out messages); + } + + /// + /// A reflection based call to the friendly URl Provider object. Done like this to avoid a circular reference + /// + /// + /// + /// + /// + /// + /// + /// + internal static string GetImprovedFriendlyUrl(TabInfo tab, string path, string defaultPage, string httpAlias, + bool ignoreCustomRedirects, FriendlyUrlSettings settings) + { + List messages; + return GetImprovedFriendlyUrl(tab, path, defaultPage, httpAlias, ignoreCustomRedirects, settings, + out messages); + } + + internal static string GetImprovedFriendlyUrl(TabInfo tab, string path, string defaultPage, string httpAlias, + bool ignoreCustomRedirects, FriendlyUrlSettings settings, + out List messages) + { + object result = CallFriendlyUrlProviderMethod("ImprovedFriendlyUrlWithMessages", out messages, tab, path, + defaultPage, httpAlias, ignoreCustomRedirects, settings); + if (result != null) + { + return (string) result; + } + return ""; + } + + internal static string GetImprovedFriendlyUrl(TabInfo tab, string path, string defaultPage, + PortalSettings portalSettings, bool ignoreCustomRedirects, + FriendlyUrlSettings settings) + { + List messages; + object result = CallFriendlyUrlProviderMethod("ImprovedFriendlyUrlWithSettings", out messages, tab, path, + defaultPage, portalSettings, ignoreCustomRedirects, settings); + if (result != null) + { + return (string) result; + } + return ""; + } + + internal static string GetImprovedFriendlyUrl(TabInfo tab, string path, string defaultPage, + PortalSettings portalSettings, bool ignoreCustomRedirects, + FriendlyUrlSettings settings, out List messages) + { + object result = CallFriendlyUrlProviderMethod("ImprovedFriendlyUrlWithSettingsAndMessages", out messages, + tab, path, defaultPage, portalSettings, ignoreCustomRedirects, + settings); + if (result != null) + { + return (string) result; + } + return ""; + } + /* + /// + /// A reflection based called to the Friendly Url Provider object. Done like this to avoid circular references + /// + /// + /// + /// + /// + internal static string BuildTabPathWithReplacement(TabInfo tab, string replaceCharacter, string replaceWith) + { + object result = CallTabPathHelperMethod("BuildTabPathWithReplacement", tab, replaceCharacter, replaceWith); + if (result != null) + { + return (string) result; + } + return ""; + } + + internal static string ReplaceDiacritics(string tabPath) + { + object result = CallTabPathHelperMethod("ReplaceDiacritics", tabPath); + if (result != null) + { + return (string) result; + } + return ""; + } + + public static void RebuildCustomUrlDict(string reason, int portalId) + { + CallTabDictControllerMethod("InvalidateDictionary", reason, null, portalId); + } + + //internal static void ProcessTestRequest(string httpMethod, Uri requestUri, UrlAction result, NameValueCollection queryString, FriendlyUrlSettings settings, out List messages) + //{ + // //public void ProcessRequest(HttpContext context, HttpRequest request, HttpServerUtility Server, HttpResponse response, bool useFriendlyUrls, string requestType, Uri requestUri, UrlAction result, NameValueCollection queryStringCol, FriendlyUrlSettings settings) + // bool useFriendlyUrls = (DotNetNuke.Entities.Host.HostSettings.GetHostSetting("UseFriendlyUrls") == "Y"); + // object retval = CallUrlRewriterMethod("ProcessTestRequest", out messages, useFriendlyUrls, httpMethod, requestUri, result, queryString, settings); + //} + /// + /// Gets the Reflection MethodInfo object of the FriendlyUrlProvider method, + /// as LONG as the iFInity.UrlMaster.FriendlyUrlProvider can be found + /// + /// This is a heavyweight proc, don't call too much! + /// + /// + private static object CallFriendlyUrlProviderMethod(string methodName, out List messages, + params object[] parameters) + { + return CallFriendlyUrlProviderDllMethod(methodName, "iFinity.DNN.Modules.UrlMaster.DNNFriendlyUrlProvider", + out messages, parameters); + } + + private static void CallTabDictControllerMethod(string methodName, params object[] parameters) + { + CallFriendlyUrlProviderDllMethod(methodName, "iFinity.DNN.Modules.UrlMaster.TabDictController", + parameters); + } + + private static object CallTabPathHelperMethod(string methodName, params object[] parameters) + { + return CallFriendlyUrlProviderDllMethod(methodName, "iFinity.DNN.Modules.UrlMaster.TabPathHelper", + parameters); + } + + private static object CallFriendlyUrlProviderDllMethod(string methodName, string typeName, + params object[] parameters) + { + List messages; + return CallFriendlyUrlProviderDllMethod(methodName, typeName, out messages, parameters); + } + + private static object CallFriendlyUrlProviderDllMethod(string methodName, string typeName, + out List messages, params object[] parameters) + { + object result = null; + messages = null; + try + { + object providerObj = null; + + Assembly urlMasterProvider = Assembly.Load("iFinity.UrlMaster.FriendlyUrlProvider"); + Type[] types = urlMasterProvider.GetTypes(); + foreach (Type type in types) + { + if ((type.FullName == typeName) & (type.IsClass)) + { + Type providerType = type; + string providerTypeName = providerType.Name; + //570 : check to see if it is an abstract class before trying to instantiate the + //calling object + if (!providerType.IsAbstract) + { + // get the provider objects from the stored collection if necessary + if (_providerObjects != null) + { + if (_providerObjects.ContainsKey(providerTypeName)) + { + providerObj = _providerObjects[providerTypeName]; + } + } + if (providerObj == null) + { + providerObj = Activator.CreateInstance(providerType); + } + + if (_providerObjects == null) + { + _providerObjects = new Dictionary {{providerTypeName, providerObj}}; + } + } + + if (providerObj != null || providerType.IsAbstract) + { + MethodInfo method = providerType.GetMethod(methodName); + if (method != null) + { + //new collection + int messageParmIdx = -1; + var parmValues = new List(parameters); + ParameterInfo[] methodParms = method.GetParameters(); + for (int i = 0; i <= methodParms.GetUpperBound(0); i++) + { + if (methodParms[i].IsOut && i > parameters.GetUpperBound(0) && + methodParms[i].Name.ToLower() == "messages") + { + //add on another one on the end + parmValues.Add(messages); + messageParmIdx = i; + parameters = parmValues.ToArray(); + } + if (methodParms[i].Name.ToLower() == "parenttraceid" && + i > parameters.GetUpperBound(0)) + { + parmValues.Add(Guid.Empty); + parameters = parmValues.ToArray(); + } + } + result = method.Invoke(providerObj, parameters); + //get the out messages value + if (messageParmIdx > -1) + { + messages = (List) parameters[messageParmIdx]; + } + } + break; + } + } + } + //} + } + catch (Exception ex) + { + //get the standard DNN friendly Url by loading up HttpModules + if (messages == null) + { + messages = new List(); + } + messages.Add("Error:[" + ex.Message + "]"); + if (ex.InnerException != null) + { + messages.Add("Inner Error:[ " + ex.InnerException.Message + "]"); + messages.Add("Stack Trace :[ " + ex.InnerException.StackTrace + "]"); + } + } + return result; + } + */ + #endregion + + #region Database methods + + public static Dictionary GetTabs(int portalId, bool includeStdUrls) + { + return GetTabs(portalId, includeStdUrls, GetCurrentSettings(portalId)); + } + + public static Dictionary GetTabs(int portalId, bool includeStdUrls, FriendlyUrlSettings settings) + { + PortalSettings portalSettings = null; + //716 just ignore portal settings if we don't actually need it + if (includeStdUrls) + { + portalSettings = PortalController.GetCurrentPortalSettings(); + } + return GetTabs(portalId, includeStdUrls, portalSettings, settings); + } + + public static Dictionary GetTabs(int portalId, bool includeStdUrls, PortalSettings portalSettings, FriendlyUrlSettings settings) + { + var tc = new TabController(); + //811 : friendly urls for admin/host tabs + var tabs = new Dictionary(); + var portalTabs = tc.GetTabsByPortal(portalId); + var hostTabs = tc.GetTabsByPortal(-1); + + foreach (TabInfo tab in portalTabs.Values) + { + tabs[tab.TabID] = tab; + } + + if (settings.FriendlyAdminHostUrls) + { + foreach (TabInfo tab in hostTabs.Values) + { + tabs[tab.TabID] = tab; + } + } + return tabs; + } + + /// + /// Returns a list of http alias values where that alias is associated with a tab as a custom alias + /// + /// Aliases returned are all in lower case only + public static List GetCustomAliasesForTabs() + { + var aliases = new List(); + + IDataReader dr = DataProvider.Instance().GetCustomAliasesForTabs(); + try + { + while (dr.Read()) + { + aliases.Add(Null.SetNullString(dr["HttpAlias"])); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return aliases; + } + + /* + internal static Dictionary GetTabs(int portalId) + { + var tabs = (Dictionary)HttpContext.Current.Session["tabs" + portalId.ToString()] ?? + new Dictionary(); + return tabs; + } + + internal static void StashTabs(Dictionary tabs, int portalId) + { + HttpContext.Current.Session["tabs" + portalId.ToString()] = tabs; + var portals = (List) HttpContext.Current.Session["tabportals"] ?? new List(); + if (portals.Contains(portalId) == false) + { + portals.Add(portalId); + } + HttpContext.Current.Session["tabportals"] = portals; + } + + internal static void FlushTabs() + { + var portals = (List) HttpContext.Current.Session["tabportals"]; + if (portals != null) + { + foreach (int portalId in portals) + { + HttpContext.Current.Session.Remove("tabs" + portalId.ToString()); + } + } + HttpContext.Current.Session.Remove("tabportals"); + } + + internal static void FlushTabs(int PortalId) + { + HttpContext.Current.Session["tabs" + PortalId.ToString()] = null; + var portals = (List) HttpContext.Current.Session["tabportals"]; + if (portals != null && portals.Contains(PortalId)) + { + portals.Remove(PortalId); + } + HttpContext.Current.Session["tabportals"] = portals; + } + */ + public static TabInfo GetTab(int tabId, bool addStdUrls) + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + return GetTab(tabId, addStdUrls, portalSettings, GetCurrentSettings(portalSettings.PortalId)); + } + + public static TabInfo GetTab(int tabId, bool addStdUrls, PortalSettings portalSettings, FriendlyUrlSettings settings) + { + var tc = new TabController(); + TabInfo tab = tc.GetTab(tabId, portalSettings.PortalId, false); + if (addStdUrls) + { + //Add on the standard Urls that exist for a tab, based on settings like + //replacing spaces, diacritic characters and languages + //BuildFriendlyUrls(tab, true, portalSettings, settings); + } + return tab; + } + + //internal static void RebuildStandardUrls(TabInfo tab, PortalSettings portalSettings, + // FriendlyUrlSettings settings) + //{ + // if (tab != null) + // { + // var standardRedirects = new List(); + // foreach (TabRedirectInfo redirect in tab.TabRedirects) + // { + // if (redirect.FixedUrl) + // { + // standardRedirects.Add(redirect.Key); + // } + // } + // //now remove the standard redirects + // foreach (string key in standardRedirects) + // { + // tab.TabRedirects.Remove(key); + // } + // } + // BuildFriendlyUrls(tab, true, portalSettings, settings); + //} + + //public static void RecheckRedirectsForTab(TabInfo tab, string changingKey) + //{ + // RecheckRedirectsForTab(tab, changingKey, GetCurrentSettings(false, true, tab.PortalID)); + //} + + //public static void RecheckRedirectsForTab(TabInfo tab, string changingKey, FriendlyUrlSettings settings) + //{ + // //essentially the smae logic as in BuildFriendlyUrl, but slightly different as we aren't building + // //up the standard urls, just processing them to make sure they obey the 301 redirect settings + // var cultureHasCustomRedirectWith200 = new Dictionary(); + // //cycle through all of the custom redirects, looking to see for the different culture codes/custom redirects + // foreach (TabRedirectInfo redirect in tab.TabRedirects) + // { + // if (redirect.FixedUrl == false) + // { + // if (redirect.HttpStatus == "200") + // { + // if (!cultureHasCustomRedirectWith200.ContainsKey(redirect.CultureCode)) + // { + // cultureHasCustomRedirectWith200.Add(redirect.CultureCode, true); + // } + // } + // } + // } + // //all the 'fixed' urls should be 301'd + // TabRedirectInfo bestRedirect = null; + // var bestRedirects = new Dictionary(); + // foreach (TabRedirectInfo redirect in tab.TabRedirects) + // { + // //see if this culture has a custom redirect + // bool customRedirectWith200 = false; + // if (cultureHasCustomRedirectWith200.ContainsKey(redirect.CultureCode)) + // { + // customRedirectWith200 = cultureHasCustomRedirectWith200[redirect.CultureCode]; + // } + + // if (customRedirectWith200 && settings.RedirectUnfriendly) + // { + // if (redirect.FixedUrl && redirect.HttpStatus == "200") + // { + // redirect.HttpStatus = "301"; + // } + // } + + // if (customRedirectWith200 == false) + // //no custom urls with 200 status on them (ie,on this page, no custom urls which are not redirects) + // { + // if (redirect.FixedUrl && settings.RedirectUnfriendly == false) + // { + // redirect.HttpStatus = "200"; //no redirect unfriendly, so all fixed Url's are 200 status + // } + // else if (redirect.FixedUrl && settings.RedirectUnfriendly) + // { + // bestRedirect = redirect; + // //redirect unfriendly, we just want to get the last fixed url, because tihs is the 'friendliest' (per the buildFriendlyUrl procedure) + // SetAsBestRedirect(redirect, bestRedirects); + // } + // } + // else + // { + // if (!redirect.FixedUrl && changingKey != null && redirect.Key == changingKey && + // redirect.HttpStatus == "200") + // { + // //not a fixed url (custom redirect), the changing key is known, and this is the item that + // //the key change was for, and this is a 200, well : we have our best redriect + // bestRedirect = redirect; + // SetAsBestRedirect(redirect, bestRedirects); + // } + // } + // } + // //the best redirect is the last fixed url + // /* + // if (bestRedirect != null) + // { + // bestRedirect.HttpStatus = "200"; + // //if the best Redirect isn't a fixed url, and the redirectUnfriendly switch is on + // //then set all the other redirects to 301's + // if (bestRedirect.FixedUrl == false && settings.RedirectUnfriendly) + // { + // foreach (TabRedirectInfo redirect in tab.TabRedirects) + // { + // //any custom redirect that isn't the chosen redirect and + // //is http status 200 will be changed to 301 + // if (redirect.FixedUrl == false + // && redirect.Key != bestRedirect.Key + // && redirect.HttpStatus == "200" ) + // { + // //final check : this is a candidate for setting to 301 redirect, unless it's a different culture code to the bestRedirect + // if (redirect.CultureCode == bestRedirect.CultureCode) + // redirect.HttpStatus = "301"; + // //else + // //don't change httpStatus for redirects in a different culture code to the changing one + // } + // } + // } + // }*/ + // if (bestRedirects.Count > 0) + // { + // foreach (string cultureCode in bestRedirects.Keys) + // { + // //if the best redirect isn't a fixed url, and the redirectUnfriendly switch is on + // //every other url for this culture is a 301 redirect to the bestFriendlyUrl for this culture + // TabRedirectInfo bestRedirectForCulture = bestRedirects[cultureCode]; + // foreach (TabRedirectInfo redirect in tab.TabRedirects) + // { + // if (redirect.CultureCode == cultureCode //same culture + // && redirect.Key != bestRedirectForCulture.Key // not the best redirect + // && redirect.HttpStatus == "200" // not already set as redirect + // && redirect.FixedUrl == false) //not a fixed url + // { + // //change this to a 301 + // redirect.HttpStatus = "301"; + // } + // else if (redirect.CultureCode == cultureCode //same culture + // && redirect.Key == bestRedirectForCulture.Key //is the best redirect + // && redirect.HttpStatus != "200") //not 200 status + // { + // redirect.HttpStatus = "200"; + // } + // } + // } + // } + //} + + //private static void SetAsBestRedirect(TabRedirectInfo redirect, + // Dictionary bestRedirects) + //{ + // string culture = redirect.CultureCode; + // if (bestRedirects.ContainsKey(culture)) + // { + // bestRedirects[culture] = redirect; + // } + // else + // { + // bestRedirects.Add(culture, redirect); + // } + //} + + ///// + ///// Saves any changes to the Tabs objects + ///// + ///// + //public static void Save(Dictionary tabs) + //{ + // throw new NotImplementedException("Tabs Save"); + //} + + #endregion + + private static bool IsMobileClient() + { + return (HttpContext.Current.Request.Browser != null) && ClientCapabilityProvider.CurrentClientCapability.IsMobile; + } + + #region Internal Methods + + internal static bool CanUseMobileDevice(HttpRequest request, HttpResponse response) + { + bool canUseMobileDevice = true; + //if (int.TryParse(app.Request.QueryString[DisableMobileRedirectQueryStringName], out val)) + //{ + // if (val == 0) //forced enable. clear any cookie previously set + // { + // if (app.Response.Cookies[DisableMobileRedirectCookieName] != null) + // { + // HttpCookie cookie = new HttpCookie(DisableMobileRedirectCookieName); + // cookie.Expires = DateTime.Now.AddMinutes(-1); + // app.Response.Cookies.Add(cookie); + // } + + // if (app.Response.Cookies[DisableRedirectPresistCookieName] != null) + // { + // HttpCookie cookie = new HttpCookie(DisableRedirectPresistCookieName); + // cookie.Expires = DateTime.Now.AddMinutes(-1); + // app.Response.Cookies.Add(cookie); + // } + // } + // else if (val == 1) //forced disable. need to setup cookie + // { + // allowed = false; + // } + //} + int val; + if (int.TryParse(request.QueryString[DisableMobileRedirectQueryStringName], out val)) + { + //the nomo value is in the querystring + if (val == 1) + { + //no, can't do it + canUseMobileDevice = false; + var cookie = new HttpCookie(DisableMobileViewCookieName); + response.Cookies.Set(cookie); + } + else + { + //check for disable mobile view cookie name + HttpCookie cookie = request.Cookies[DisableMobileViewCookieName]; + if (cookie != null) + { + //if exists, expire cookie to allow redirect + cookie = new HttpCookie(DisableMobileViewCookieName) { Expires = DateTime.Now.AddMinutes(-1) }; + response.Cookies.Set(cookie); + } + //check the DotNetNuke cookies for allowed + if (request.Cookies[DisableMobileRedirectCookieName] != null + && request.Cookies[DisableRedirectPresistCookieName] != null) //check for cookie + { + //cookies exist, can't use mobile device + canUseMobileDevice = false; + } + } + } + else + { + //look for disable mobile view cookie + HttpCookie cookie = request.Cookies[DisableMobileViewCookieName]; + if (cookie != null) + { + canUseMobileDevice = false; + } + } + + return canUseMobileDevice; + } + + /// + /// Replaces the core IsAdminTab call which was decommissioned for DNN 5.0 + /// + /// The path of the tab //admin//someothername + /// + /// Duplicated in RewriteController.cs + /// + internal static bool IsAdminTab(int portalId, string tabPath, FriendlyUrlSettings settings) + { + //fallback position - all portals match 'Admin' + const string adminPageName = "Admin"; + //we should be checking that the tab path matches //Admin//pagename or //admin + //in this way we should avoid partial matches (ie //Administrators + if (tabPath.StartsWith("//" + adminPageName + "//", StringComparison.CurrentCultureIgnoreCase) + || String.Compare(tabPath, "//" + adminPageName, StringComparison.OrdinalIgnoreCase) == 0) + { + return true; + } + return false; + } + + #endregion + + #region Public Methods + + public static string CleanNameForUrl(string urlName, FriendlyUrlOptions options, out bool replacedUnwantedChars) + { + replacedUnwantedChars = false; + //get options + if (options == null) + { + options = new FriendlyUrlOptions(); + } + bool convertDiacritics = options.ConvertDiacriticChars; + string regexMatch = options.RegexMatch; + string illegalChars = options.IllegalChars; + string replaceWith = options.PunctuationReplacement; + string replaceChars = options.ReplaceChars; + bool replaceDoubleChars = options.ReplaceDoubleChars; + Dictionary replacementChars = options.ReplaceCharWithChar; + + if (urlName == null) + { + urlName = ""; + } + var result = new StringBuilder(urlName.Length); + int i = 0; + int last = urlName.ToCharArray().GetUpperBound(0); + string normalisedUrl = urlName; + if (convertDiacritics) + { + normalisedUrl = urlName.Normalize(NormalizationForm.FormD); + if (string.CompareOrdinal(normalisedUrl, urlName) != 0) + { + replacedUnwantedChars = true; //replaced an accented character + } + } + bool doublePeriod = false; + foreach (char c in normalisedUrl) + { + //look for a double period in the name + if (!doublePeriod && c == '.' && i > 0 && urlName[i - 1] == '.') + { + doublePeriod = true; + } + //use string for manipulation + string ch = c.ToString(); + //do replacement in pre-defined list? + if (replacementChars != null && replacementChars.ContainsKey(c.ToString())) + { + //replace with value + ch = replacementChars[c.ToString()]; + replacedUnwantedChars = true; + } + else + { + //not in replacement list, check if valid char + if (Regex.IsMatch(ch, regexMatch, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) + { + //check replace character with the punctuation replacmenet + if (replaceChars.ToLower().Contains(ch.ToLower())) + { + ch = replaceWith; //in list of replacment chars + if (ch != " ") // if not replacing spaces, which are implied + { + replacedUnwantedChars = true; + } + } + else + { + ch = ""; //not a replacement or allowed char, so doesn't go into Url + replacedUnwantedChars = true; + //if we are here, this character isn't going into the output Url + } + } + else + { + //this char is allowed because it didn't match the regexMatch pattern + //however we may still want to replace it in Urls + if (illegalChars.ToLower().Contains(ch.ToLower())) + { + ch = ""; //illegal character, removed from list + replacedUnwantedChars = true; + } + else + { + //but we also want to check the list of illegal chars - these must never be allowed, + //even if the settings inadvertently let them through. This is a double check + //to prevent accidental modification to regex taking down a site + if (replaceChars.ToLower().Contains(ch.ToLower())) + { + if (ch != " ") // if not replacing spaces, which are implied + { + replacedUnwantedChars = true; + } + ch = replaceWith; //in list of replacment chars + } + } + } + } + + if (i == last) + { + //834 : strip off last character if it is a '.' + if (!(ch == "-" || ch == replaceWith || ch == ".")) + { + //only append if not the same as the replacement character + result.Append(ch); + } + else + { + replacedUnwantedChars = true; //last char not added - effectively replaced with nothing. + } + } + else + { + result.Append(ch); + } + i++; //increment counter + } + + if (doublePeriod) + { + result = result.Replace("..", ""); + } + //replace any duplicated replacement characters by doing replace twice + //replaces -- with - or --- with - //749 : ampersand not completed replaced + if (replaceDoubleChars && !string.IsNullOrEmpty(replaceWith)) + { + result = result.Replace(replaceWith + replaceWith, replaceWith); + result = result.Replace(replaceWith + replaceWith, replaceWith); + } + + return result.ToString(); + } + + /// + /// Ensures that the path starts with the leading character + /// + /// + /// + /// + public static string EnsureLeadingChar(string leading, string path) + { + if (leading != null && path != null + && leading.Length <= path.Length && leading != "") + { + string start = path.Substring(0, leading.Length); + if (String.Compare(start, leading, StringComparison.OrdinalIgnoreCase) != 0) + { + //not leading with this + path = leading + path; + } + } + return path; + } + + public static string EnsureNotLeadingChar(string leading, string path) + { + if (leading != null && path != null + && leading.Length <= path.Length && leading != "") + { + string start = path.Substring(0, leading.Length); + if (String.Compare(start, leading, StringComparison.OrdinalIgnoreCase) == 0) + { + //matches start, take leading off + path = path.Substring(leading.Length); + } + } + return path; + } + + //737 : detect mobile and other types of browsers + public static BrowserTypes GetBrowserType(HttpRequest request, HttpResponse response, FriendlyUrlSettings settings) + { + var browserType = BrowserTypes.Normal; + if (request != null && settings != null) + { + bool isCookieSet = false; + bool isMobile = false; + if (CanUseMobileDevice(request, response)) + { + HttpCookie viewMobileCookie = response.Cookies[MobileViewSiteCookieName]; + if (viewMobileCookie != null && bool.TryParse(viewMobileCookie.Value, out isMobile)) + { + isCookieSet = true; + } + if (isMobile == false) + { + if (!isCookieSet) + { + isMobile = IsMobileClient(); + if (isMobile) + { + browserType = BrowserTypes.Mobile; + } + + // Store the result as a cookie. + response.Cookies.Set(new HttpCookie(MobileViewSiteCookieName, isMobile.ToString())); + } + } + else + { + browserType = BrowserTypes.Mobile; + } + } + } + return browserType; + } + + public static string ValidateUrl(string cleanUrl, int validateUrlForTabId, PortalSettings settings, out bool modified) + { + modified = false; + bool isUnique; + var uniqueUrl = cleanUrl; + int counter = 0; + do + { + if (counter > 0) + { + uniqueUrl = uniqueUrl + counter.ToString(CultureInfo.InvariantCulture); + modified = true; + } + isUnique = ValidateUrl(uniqueUrl, validateUrlForTabId, settings); + counter++; + } while (!isUnique); + + return uniqueUrl; + } + + private static bool ValidateUrl(string url, int validateUrlForTabId, PortalSettings settings) + { + bool isUnique = true; + + //Try and get a user by the url + var user = UserController.GetUserByVanityUrl(settings.PortalId, url); + isUnique = (user == null); + + if (isUnique) + { + //Try and get a tab by the url + int tabId = TabController.GetTabByTabPath(settings.PortalId, "//" + url, settings.CultureCode); + isUnique = (tabId == -1 || tabId == validateUrlForTabId); + } + return isUnique; + } + + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/FriendlyUrlOptions.cs b/DNN Platform/Library/Entities/Urls/FriendlyUrlOptions.cs new file mode 100644 index 00000000000..982dff127cc --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/FriendlyUrlOptions.cs @@ -0,0 +1,92 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// This class encapsulates different options used in generating friendly urls + /// + [Serializable] + public class FriendlyUrlOptions + { + public bool ConvertDiacriticChars; + public string IllegalChars; + public int MaxUrlPathLength; + public string PageExtension; + public string PunctuationReplacement; + //922 : change to use regexMatch pattern for allowable characters + public string RegexMatch; + public Dictionary ReplaceCharWithChar = new Dictionary(); + public string ReplaceChars; + public bool ReplaceDoubleChars; + public string SpaceEncoding; + + public bool CanGenerateNonStandardPath + { + //replaces statements like this + //if ((settings.ReplaceSpaceWith != null && settings.ReplaceSpaceWith.Length > 0) || settings.ReplaceCharWithCharDict != null && settings.ReplaceCharWithCharDict.Count > 0) + get + { + bool result = false; + if (string.IsNullOrEmpty(PunctuationReplacement) == false) + { + result = true; + } + else if (ReplaceCharWithChar != null && ReplaceCharWithChar.Count > 0) + { + result = true; + } + else if (ConvertDiacriticChars) + { + result = true; + } + + return result; + } + } + + public FriendlyUrlOptions Clone() + { + var cloned = new FriendlyUrlOptions + { + PunctuationReplacement = PunctuationReplacement, + SpaceEncoding = SpaceEncoding, + MaxUrlPathLength = MaxUrlPathLength, + ConvertDiacriticChars = ConvertDiacriticChars, + PageExtension = PageExtension, + RegexMatch = RegexMatch, + ReplaceCharWithChar = ReplaceCharWithChar, + IllegalChars = IllegalChars, + ReplaceChars = ReplaceChars + }; + return cloned; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/FriendlyUrlPathController.cs b/DNN Platform/Library/Entities/Urls/FriendlyUrlPathController.cs new file mode 100644 index 00000000000..684290e6e7a --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/FriendlyUrlPathController.cs @@ -0,0 +1,346 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal class FriendlyUrlPathController + { + #region Private Methods + + /// + /// Splits out the userid value from the supplied Friendly Url Path + /// + /// + /// The 'other' parameters which form the total UserProfile Url (if supplied) + /// + /// The remaining path not associated with the user id + /// + private static void SplitUserIdFromFriendlyUrlPath(string urlPath, + string parmName, + string otherParametersPath, + out string rawUserId, + out string remainingPath) + { + //688 : allow for other parts to be in the url by capturing more with the regex filters + string regexPattern; + rawUserId = null; + remainingPath = ""; + //generally the path will start with a / and not end with one, but it's possible to get all sorts of things + if (!string.IsNullOrEmpty(otherParametersPath)) + { + //remove the trailing slash from otherParamtersPath if it exists, because the other parameters may be anywhere in the path + if (otherParametersPath.EndsWith("/")) + { + otherParametersPath = otherParametersPath.Substring(0, otherParametersPath.Length - 1); + } + const string patternFormatWithParameters = @"/?(?.*)(?=_parm_)(?(?<=/|^)(?:_parm_)/(?[\d\w]+)){0,1}/?(?_otherparm_){0,1}/?(?(?<=/)(?:_parm_)/(?[\d\w]+)){0,1}(?.*)"; + regexPattern = patternFormatWithParameters.Replace("_parm_", parmName); + regexPattern = regexPattern.Replace("_otherparm_", otherParametersPath); + } + else + { + const string patternNoParameters = @"/?(?.*)(?(?<=/|^)(?:_parm_)/(?[\d\w]+)/?)+(?.*)"; + regexPattern = patternNoParameters.Replace("_parm_", parmName); + } + //check the regex match + Match parmMatch = Regex.Match(urlPath, regexPattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (parmMatch.Success) + { + //must be nothing in the op1 and op2 values + Group otherParmsGp = parmMatch.Groups["op"]; + Group parm1ValueGp = parmMatch.Groups["p1v"]; + Group parm2ValueGp = parmMatch.Groups["p2v"]; + Group rem1ParmsGp = parmMatch.Groups["rem1"]; //remainder at the start of the match + Group rem2ParmsGp = parmMatch.Groups["rem2"]; //remainder at the end of the match + + if (otherParmsGp != null && otherParmsGp.Success && (parm1ValueGp.Success || parm2ValueGp.Success)) + { + //matched the other parm value and either the p1 or p2 value + rawUserId = parm1ValueGp.Success ? parm1ValueGp.Value : parm2ValueGp.Value; + } + else + { + if ((otherParmsGp == null || otherParmsGp.Success == false) && parm1ValueGp != null && + parm1ValueGp.Success) + { + rawUserId = parm1ValueGp.Value; + } + } + //add back the remainders + if (rem1ParmsGp != null && rem1ParmsGp.Success) + { + remainingPath = rem1ParmsGp.Value; + } + if (rem2ParmsGp != null && rem2ParmsGp.Success) + { + remainingPath += rem2ParmsGp.Value; + } + if (remainingPath.EndsWith("/")) + { + remainingPath = remainingPath.Substring(0, remainingPath.Length - 1); + } + //722: drop out the parts of the remaining path that are in the 'otherParameters' path. + // the other parameters path will be automatically provided upon rewrite + if (otherParametersPath != null) + { + remainingPath = Regex.Replace(remainingPath, Regex.Escape(otherParametersPath), "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + + if (parmName.Contains("|") && rawUserId != null) + { + //eliminate any dups from the remaining path + string[] vals = parmName.Split('|'); + foreach (string val in vals) + { + string find = "/?" + Regex.Escape(val + "/" + rawUserId); + remainingPath = Regex.Replace(remainingPath, find, "", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + } + } + if (remainingPath.Length > 0 && remainingPath.StartsWith("/") == false) + { + remainingPath = "/" + remainingPath; + } + } + } + + #endregion + + #region Internal Methods + + /// + /// This method checks the list of rules for parameter replacement and modifies the parameter path accordingly + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal static bool CheckParameterRegexReplacement(string parameterPath, + TabInfo tab, + FriendlyUrlSettings settings, + int portalId, + out string replacedPath, + ref List messages, + out bool changeToSiteRoot, + Guid parentTraceId) + { + bool replaced = false; + replacedPath = ""; + changeToSiteRoot = false; + if (messages == null) + { + messages = new List(); + } + + var replaceActions = CacheController.GetParameterReplacements(settings, portalId, ref messages); + if (replaceActions != null && replaceActions.Count > 0) + { + List parmReplaces = null; + int tabId = tab.TabID; + + if (replaceActions.ContainsKey(tabId)) + { + //find the right set of replaced actions for this tab + parmReplaces = replaceActions[tabId]; + } + + //check for 'all tabs' replaceions + if (replaceActions.ContainsKey(-1)) //-1 means 'all tabs' - replacing across all tabs + { + //initialise to empty collection if there are no specific tab replaces + if (parmReplaces == null) + { + parmReplaces = new List(); + } + //add in the all replaces + List allReplaces = replaceActions[-1]; + parmReplaces.AddRange(allReplaces); //add the 'all' range to the tab range + } + if (parmReplaces != null) + { + //OK what we have now is a list of replaces for the currently requested tab (either because it was specified by tab id, + // or because there is a replaced for 'all tabs' + try + { + foreach (ParameterReplaceAction parmReplace in parmReplaces) + { + //do a regex on the 'lookFor' in the parameter path + var parmRegex = new Regex(parmReplace.LookFor, + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (parmRegex.IsMatch(parameterPath)) + { + replacedPath = parmRegex.Replace(parameterPath, parmReplace.ReplaceWith); + messages.Add(parmReplace.Name + " replace rule match, replaced : " + parameterPath + " with: " + replacedPath); + replaced = true; + //593: if this replacement is marked as a site root replacement, we will be + //removing the page path from the final url + changeToSiteRoot = parmReplace.ChangeToSiteRoot; + break; + } + messages.Add(parmReplace.Name + " replace rule not matched {" + parameterPath + "}"); + } + } + catch (Exception ex) + { + //catch exceptions here because most likely to be related to regular expressions + //don't want to kill entire site because of this + Services.Exceptions.Exceptions.LogException(ex); + messages.Add("Exception : " + ex.Message + "\n" + ex.StackTrace); + } + } + } + return replaced; + } + + internal static bool CheckUserProfileReplacement(string newPath, + TabInfo tab, + PortalSettings portalSettings, + FriendlyUrlSettings settings, + FriendlyUrlOptions options, + out string changedPath, + out bool changeToSiteRoot, + out bool allowOtherParameters, + ref List meessages, + Guid parentTraceId) + { + if (meessages == null) + { + meessages = new List(); + } + bool urlWasChanged = false; + + //initialise defaults to always return valid items + changedPath = newPath; + changeToSiteRoot = false; + allowOtherParameters = true; + + //determine if this url should be converted to a userprofile url by checking the saved rules matching the tab/portalid + if (portalSettings != null && tab.PortalID == portalSettings.PortalId && + (tab.TabID == portalSettings.UserTabId || portalSettings.UserTabId == -1 || + tab.ParentId == portalSettings.UserTabId)) //-1 == all tabs in portal + { + int userId; + string rawUserId, remainingPath; + //split the userid and other profile parameters from the friendly url path, + //and return the userid and remaining parts as separate items + SplitUserIdFromFriendlyUrlPath(newPath, + "UserId", + "", + out rawUserId, + out remainingPath); + if (rawUserId != null) + { + meessages.Add("User Profile Url : RawUserId = " + rawUserId + " remainingPath = " + remainingPath); + } + else + { + meessages.Add("User Profile Url : RawUserId = " + "null" + " remainingPath = " + remainingPath); + } + + //the rawuserid is just the string representation of the userid from the path. + //It should be considered 'untrusted' until cleaned up, + //converted to an int and checked against the database + if (!String.IsNullOrEmpty(rawUserId) && Int32.TryParse(rawUserId, out userId)) + { + bool doReplacement = false; + string urlName = String.Empty; + + //Get the User + var user = UserController.GetUserById(portalSettings.PortalId, userId); + + if (user != null && !String.IsNullOrEmpty(user.VanityUrl)) + { + doReplacement = true; + urlName = (!String.IsNullOrEmpty(settings.VanityUrlPrefix)) ? String.Format("{0}/{1}", settings.VanityUrlPrefix, user.VanityUrl) : user.VanityUrl; + urlWasChanged = true; + } + + if (doReplacement) + { + //check to see whether this is a match on the parentid or not + if (portalSettings.UserTabId == tab.ParentId && portalSettings.UserTabId > -1) + { + //replacing for the parent tab id + string childTabPath = TabIndexController.GetTabPath(tab, options, parentTraceId); + if (string.IsNullOrEmpty(childTabPath) == false) + { + //remove the parent tab path from the child tab path + var tc = new TabController(); + TabInfo profilePage = tc.GetTab(tab.ParentId, tab.PortalID, false); + string profilePagePath = TabIndexController.GetTabPath(profilePage, options, parentTraceId); + if (childTabPath.Contains(profilePagePath)) + { + //only replace when the child tab path contains the parent path - if it's a custom url that + //doesn't incorporate the parent path, then leave it alone + childTabPath = childTabPath.Replace(profilePagePath, ""); + childTabPath = childTabPath.Replace("//", "/"); + remainingPath += FriendlyUrlController.EnsureLeadingChar("/", childTabPath); + } + } + } + changedPath = "/" + urlName; + //append any extra remaining path value to the end + if (!string.IsNullOrEmpty(remainingPath)) + { + if (remainingPath.StartsWith("/") == false) + { + changedPath += "/" + remainingPath; + } + else + { + changedPath += remainingPath; + } + } + urlWasChanged = true; + changeToSiteRoot = true; //we will be doing domain.com/urlname + allowOtherParameters = false; + //can't have any others (wouldn't have matched in the regex if there were) + } + else + { + meessages.Add("User Profile : doReplacement = false"); + } + } + } + return urlWasChanged; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/FriendlyUrlProviderBase.cs b/DNN Platform/Library/Entities/Urls/FriendlyUrlProviderBase.cs new file mode 100644 index 00000000000..6844b43d431 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/FriendlyUrlProviderBase.cs @@ -0,0 +1,71 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Specialized; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public abstract class FriendlyUrlProviderBase + { + protected UrlFormatType UrlFormat { get; private set; } + + internal FriendlyUrlProviderBase(NameValueCollection attributes) + { + if (!String.IsNullOrEmpty(attributes["urlFormat"])) + { + switch (attributes["urlFormat"].ToLower()) + { + case "searchfriendly": + UrlFormat = UrlFormatType.SearchFriendly; + break; + case "humanfriendly": + UrlFormat = UrlFormatType.HumanFriendly; + break; + case "advanced": + case "customonly": + UrlFormat = UrlFormatType.Advanced; + break; + default: + UrlFormat = UrlFormatType.SearchFriendly; + break; + } + } + } + + internal abstract string FriendlyUrl(TabInfo tab, string path); + + internal abstract string FriendlyUrl(TabInfo tab, string path, string pageName); + + internal abstract string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings portalSettings); + + internal abstract string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/FriendlyUrlSettings.cs b/DNN Platform/Library/Entities/Urls/FriendlyUrlSettings.cs new file mode 100644 index 00000000000..8cd84dc5774 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/FriendlyUrlSettings.cs @@ -0,0 +1,448 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Collections; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class FriendlyUrlSettings + { + #region Private Members + + private const string _oldTriggerRegexValue = @"(.+)(\&ctl=tab)(.+)|(/Admin/Tabs/)"; + + //894 : new switch to disable custom url provider + private string _internalAliases; + private string _pageExtensionUsage = PageExtensionUsageType.AlwaysUse.ToString(); + + private string _deletedTabHandling; + + #endregion + + #region private helper methods + + internal List PortalValues { get; set; } + + + #endregion + + public const string ReplaceSpaceWithNothing = "None"; + public const string SpaceEncodingPlus = "+"; + public const string SpaceEncodingHex = "%20"; + + // Settings Keys + public const string DeletedTabHandlingTypeSetting = "AUM_DeletedTabHandlingType"; + public const string ErrorPage404Setting = "AUM_ErrorPage404"; + public const string ErrorPage500Setting = "AUM_ErrorPage500"; + public const string ForceLowerCaseSetting = "AUM_ForceLowerCase"; + public const string PageExtensionSetting = "AUM_PageExtension"; + public const string PageExtensionUsageSetting = "AUM_PageExtensionUsage"; + public const string RedirectOldProfileUrlSetting = "AUM_RedirectOldProfileUrl"; + public const string RedirectUnfriendlySetting = "AUM_RedirectUnfriendly"; + public const string ReplaceSpaceWithSetting = "AUM_ReplaceSpaceWith"; + public const string UrlFormatSetting = "AUM_UrlFormat"; + public const string RedirectMixedCaseSetting = "AUM_RedirectMixedCase"; + public const string SpaceEncodingValueSetting = "AUM_SpaceEncodingValue"; + public const string AutoAsciiConvertSetting = "AUM_AutoAsciiConvert"; + public const string ReplaceCharsSetting = "AUM_ReplaceChars"; + public const string CheckForDuplicatedUrlsSetting = "AUM_CheckForDuplicatedUrls"; + public const string FriendlyAdminHostUrlsSetting = "AUM_FriendlyAdminHostUrls"; + public const string EnableCustomProvidersSetting = "AUM_EnableCustomProviders"; + public const string ReplaceCharWithCharSetting = "AUM_ReplaceCharWithChar"; + public const string IgnoreRegexSetting = "AUM_IgnoreUrlRegex"; + public const string SiteUrlsOnlyRegexSetting = "AUM_SiteUrlsOnlyRegex"; + public const string DoNotRedirectUrlRegexSetting = "AUM_DoNotRedirectUrlRegex"; + public const string DoNotRedirectHttpsUrlRegexSetting = "AUM_DoNotRedirectHttpsUrlRegex"; + public const string PreventLowerCaseUrlRegexSetting = "AUM_PreventLowerCaseUrlRegex"; + public const string DoNotUseFriendlyUrlRegexSetting = "AUM_DoNotUseFriendlyUrlRegex"; + public const string KeepInQueryStringRegexSetting = "AUM_KeepInQueryStringRegex"; + public const string UrlsWithNoExtensionRegexSetting = "AUM_UrlsWithNoExtensionRegex"; + public const string ValidFriendlyUrlRegexSetting = "AUM_ValidFriendlyUrlRegex"; + public const string DoNotRewriteRegExSetting = "AUM_DoNotRewriteRegEx"; + public const string UsePortalDefaultLanguageSetting = "AUM_UsePortalDefaultLanguage"; + public const string AllowDebugCodeSetting = "AUM_AllowDebugCode"; + public const string LogCacheMessagesSetting = "AUM_LogCacheMessages"; + public const string VanityUrlPrefixSetting = "AUM_VanityUrlPrefix"; + + #region Public Properties + + internal bool AllowReporting { get; set; } + + public bool AllowDebugCode { get; set; } + + public bool AutoAsciiConvert { get; set; } + + public TimeSpan CacheTime { get; set; } + + public bool CheckForDuplicateUrls { get; set; } + + public DeletedTabHandlingType DeletedTabHandlingType + { + get + { + DeletedTabHandlingType val; + switch (_deletedTabHandling.ToLower()) + { + case "do301redirecttoportalhome": + val = DeletedTabHandlingType.Do301RedirectToPortalHome; + break; + default: + val = DeletedTabHandlingType.Do404Error; + break; + } + return val; + } + set + { + string newValue = value.ToString(); + _deletedTabHandling = newValue; + } + } + + public string DoNotIncludeInPathRegex { get; set; } + + public string DoNotRedirectRegex { get; set; } + + public string DoNotRedirectSecureRegex { get; set; } + + public string DoNotRewriteRegex { get; set; } + + public bool ForceLowerCase { get; set; } + + public string ForceLowerCaseRegex { get; set; } + + public bool ForcePortalDefaultLanguage { get; set; } + + public DNNPageForwardType ForwardExternalUrlsType + { + get + { + return DNNPageForwardType.Redirect301; + } + } + + public bool FriendlyAdminHostUrls { get; set; } + + public bool EnableCustomProviders { get; set; } + + public string IgnoreRegex { get; set; } + + public string IllegalChars { get; set; } + + public bool IncludePageName { get; set; } + + public List InternalAliasList { get; private set; } + + public bool IsDirty { get; set; } + + public bool IsLoading { get; private set; } + + public bool LogCacheMessages { get; set; } + + public string NoFriendlyUrlRegex { get; set; } + + public string PageExtension { get; set; } + + public PageExtensionUsageType PageExtensionUsageType + { + get + { + var val = PageExtensionUsageType.Never; + switch (_pageExtensionUsage.ToLower()) + { + case "always": + case "alwaysuse": + val = PageExtensionUsageType.AlwaysUse; + break; + case "never": + val = PageExtensionUsageType.Never; + break; + case "pageonly": + val = PageExtensionUsageType.PageOnly; + break; + } + return val; + } + set + { + string newValue = value.ToString(); + _pageExtensionUsage = newValue; + } + } + + public int PortalId { get; set; } + + public List ProcessRequestList { get; private set; } + + public bool RedirectDefaultPage { get; set; } + + public bool RedirectOldProfileUrl { get; set; } + + public bool RedirectUnfriendly { get; set; } + + public bool RedirectWrongCase { get; set; } + + public string Regex404 { get; set; } + + public string RegexMatch { get; set; } + + public Dictionary ReplaceCharacterDictionary { get; private set; } + + public string ReplaceChars { get; set; } + + public bool ReplaceDoubleChars { get; set; } + + public string ReplaceSpaceWith { get; set; } + + public string SpaceEncodingValue { get; set; } + + public bool SSLClientRedirect { get; set; } + + public int TabId404 { get; set; } + + public int TabId500 { get; set; } + + public string Url404 { get; set; } + + public string Url500 { get; set; } + + public string UrlFormat { get; set; } + + public string UseBaseFriendlyUrls { get; set; } + + public string UseMobileAlias { get; set; } + + public string UseSiteUrlsRegex { get; set; } + + public string ValidExtensionlessUrlsRegex { get; set; } + + public string InternalAliases + { + get { return _internalAliases; } + set + { + _internalAliases = value; + ParseInternalAliases(); //splits into list + } + } + + public string VanityUrlPrefix { get; set; } + + #endregion + + #region initialization methods + + private bool GetBooleanSetting(string key, bool defaultValue) + { + //First Get the Host Value using the passed in value as default + var returnValue = (PortalId < -1) ? defaultValue : HostController.Instance.GetBoolean(key, defaultValue); + + if (PortalId > -1) + { + //Next check if there is a Portal Value, using the Host value as default + returnValue = PortalController.GetPortalSettingAsBoolean(key, PortalId, returnValue); + } + + return returnValue; + } + + private int GetIntegerSetting(string key, int defaultValue) + { + //First Get the Host Value using the passed in value as default + var returnValue = (PortalId < -1) ? defaultValue : HostController.Instance.GetInteger(key, defaultValue); + + if (PortalId > -1) + { + //Next check if there is a Portal Value, using the Host value as default + returnValue = PortalController.GetPortalSettingAsInteger(key, PortalId, returnValue); + } + + return returnValue; + } + + private string GetStringSetting(string key, string defaultValue) + { + //First Get the Host Value using the passed in value as default + var returnValue = (PortalId < -1) ? defaultValue : HostController.Instance.GetString(key, defaultValue); + + if (PortalId > -1) + { + //Next check if there is a Portal Value, using the Host value as default + returnValue = PortalController.GetPortalSetting(key, PortalId, returnValue); + } + + return returnValue; + } + + /// + /// Initialiser for FriendlyUrlSettings provider object. Initialises values by reading in from the web.config file + /// + public FriendlyUrlSettings(int portalId) + { + PortalId = portalId; + + PortalValues = new List(); + + IncludePageName = GetBooleanSetting("includePageName", true); + RegexMatch = GetStringSetting(ValidFriendlyUrlRegexSetting, @"[^\w\d _-]"); + RedirectUnfriendly = GetBooleanSetting(RedirectUnfriendlySetting, true); + UrlFormat = GetStringSetting(UrlFormatSetting, "advanced"); + + //541 moved doNotRedirect and doNotRedirectRegex from under 'redirectUnfriendly' code + DoNotRedirectRegex = GetStringSetting(DoNotRedirectUrlRegexSetting, @"(\.axd)|/Rss\.aspx|/SiteMap\.aspx|/ProfilePic\.ashx|/LinkClick\.aspx|/Providers/|/DesktopModules/|ctl=MobilePreview|/ctl/MobilePreview"); + DoNotRedirectSecureRegex = GetStringSetting(DoNotRedirectHttpsUrlRegexSetting, String.Empty); + + DoNotRewriteRegex = GetStringSetting(DoNotRewriteRegExSetting, @"/DesktopModules/|/Providers/|/LinkClick\.aspx|/profilepic\.ashx"); + + RedirectDefaultPage = GetBooleanSetting("redirectDefaultPage", false); + PageExtension = GetStringSetting(PageExtensionSetting, ".aspx"); + _pageExtensionUsage = GetStringSetting(PageExtensionUsageSetting, PageExtensionUsageType.Never.ToString()); + + IgnoreRegex = GetStringSetting(IgnoreRegexSetting, @"(?()¿¡«»!"""); + IllegalChars = GetStringSetting("illegalChars", @"<>/\?:&=+|%#"); + ReplaceDoubleChars = GetBooleanSetting("replaceDoubleChars", true); + + //793 : checkforDupUrls not being read + CheckForDuplicateUrls = GetBooleanSetting(CheckForDuplicatedUrlsSetting, true); + + /* 454 New 404 error handling */ + Regex404 = GetStringSetting("regex404", String.Empty); + TabId404 = PortalController.GetPortalSettingAsInteger(ErrorPage404Setting, PortalId, -1); + Url404 = GetStringSetting("url404", String.Empty); + + //get the 500 error values, if not supplied, use the 404 values + TabId500 = PortalController.GetPortalSettingAsInteger(ErrorPage500Setting, PortalId, -1); + if (TabId500 == -1) + { + TabId500 = TabId404; + } + Url500 = GetStringSetting("url500", null) ?? Url404; + + _deletedTabHandling = PortalController.GetPortalSetting(DeletedTabHandlingTypeSetting, PortalId, DeletedTabHandlingType.Do404Error.ToString()); + + UseBaseFriendlyUrls = GetStringSetting("useBaseFriendlyUrls", "/SearchResults;/ModuleDefinitions"); + if (UseBaseFriendlyUrls.EndsWith(";") == false) + { + UseBaseFriendlyUrls += ";"; + } + + //655 : new noFriendlyUrlRegex value to ignore generation of certain urls + NoFriendlyUrlRegex = GetStringSetting(DoNotUseFriendlyUrlRegexSetting, @"/Rss\.aspx"); + + //703 default debug code to false + AllowDebugCode = GetBooleanSetting(AllowDebugCodeSetting, false); + //allow reporting value for checking for updates and reporting usage data + AllowReporting = GetBooleanSetting("allowReporting", true); + + //737 : integrate mobile alias + UseMobileAlias = GetStringSetting("useMobileAlias", null); + + VanityUrlPrefix = GetStringSetting(VanityUrlPrefixSetting, "users"); + + // allow for a list of internal aliases + _internalAliases = GetStringSetting("internalAliases", null); + ParseInternalAliases(); + + //661 : do not include in path + //742 : was not reading and saving value when 'doNotIncludeInPathRegex' used + DoNotIncludeInPathRegex = GetStringSetting(KeepInQueryStringRegexSetting, @"/nomo/\d+|/runningDefault/[^/]+|/popup/(?:true|false)|/(?:page|category|sort|tags)/[^/]+"); + + string processRequests = GetStringSetting("processRequests", null); + if (processRequests != null) + { + processRequests = processRequests.ToLower(); + ProcessRequestList = !string.IsNullOrEmpty(processRequests) + ? new List(processRequests.Split(';')) + : null; + } + + //urls to be modified in the output html stream + AutoAsciiConvert = GetBooleanSetting(AutoAsciiConvertSetting, false); + + //810 : allow forcing of default language in rewrites + ForcePortalDefaultLanguage = GetBooleanSetting(UsePortalDefaultLanguageSetting, true); + FriendlyAdminHostUrls = GetBooleanSetting(FriendlyAdminHostUrlsSetting, true); + //894 : new switch to disable custom providers if necessary + EnableCustomProviders = GetBooleanSetting(EnableCustomProvidersSetting, true); + + CacheTime = new TimeSpan(0, GetIntegerSetting("cacheTime", 1440), 0); + + RedirectOldProfileUrl = PortalController.GetPortalSettingAsBoolean(RedirectOldProfileUrlSetting, PortalId, true); + } + + private void ParseInternalAliases() + { + if (!string.IsNullOrEmpty(_internalAliases)) + { + InternalAliasList = new List(); + string[] raw = _internalAliases.Split(';'); + foreach (string rawVal in raw) + { + if (rawVal.Length > 0) + { + var ia = new InternalAlias { HttpAlias = rawVal }; + if (InternalAliasList.Contains(ia) == false) + { + InternalAliasList.Add(ia); + } + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/IExtensionUrlProviderSettingsControl.cs b/DNN Platform/Library/Entities/Urls/IExtensionUrlProviderSettingsControl.cs new file mode 100644 index 00000000000..5a433c8e2a2 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/IExtensionUrlProviderSettingsControl.cs @@ -0,0 +1,40 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Urls +{ + public interface IExtensionUrlProviderSettingsControl + { + ExtensionUrlProviderInfo Provider { get; set; } + + void LoadSettings(); + + /// + /// Build the Settings Dictionary and return it to the caller to persist to the database + /// + /// + Dictionary SaveSettings(); + } +} diff --git a/DNN Platform/Library/Entities/Urls/InternalAlias.cs b/DNN Platform/Library/Entities/Urls/InternalAlias.cs new file mode 100644 index 00000000000..19438f3f4d3 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/InternalAlias.cs @@ -0,0 +1,33 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class InternalAlias + { + public string HttpAlias; + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/PageExtensionUsageType.cs b/DNN Platform/Library/Entities/Urls/PageExtensionUsageType.cs new file mode 100644 index 00000000000..9c557e2df28 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/PageExtensionUsageType.cs @@ -0,0 +1,32 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum PageExtensionUsageType + { + AlwaysUse, + PageOnly, + Never + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/PageIndexData.cs b/DNN Platform/Library/Entities/Urls/PageIndexData.cs new file mode 100644 index 00000000000..421a397fc95 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/PageIndexData.cs @@ -0,0 +1,37 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The PageIndexData class is used during the page index build process. + /// + [Serializable] + internal class PageIndexData + { + public string LastPageKey; + public string LastPageValue; + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/PageUsage.cs b/DNN Platform/Library/Entities/Urls/PageUsage.cs new file mode 100644 index 00000000000..6c4b6e6a208 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/PageUsage.cs @@ -0,0 +1,33 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum PageUsage + { + NoTabs = -1, + ThisTab = 0, + //AnotherTab = 1, + //AllTabs = 2 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/PagingInfo.cs b/DNN Platform/Library/Entities/Urls/PagingInfo.cs new file mode 100644 index 00000000000..1818389a9fb --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/PagingInfo.cs @@ -0,0 +1,72 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// Class used as a utility to help manage paging in database queries + /// + public class PagingInfo + { + public PagingInfo(int pageNumber, int pageSize) + { + PageNumber = pageNumber; + PageSize = pageSize; + } + + public int PageNumber { get; private set; } + + public int PageSize { get; private set; } + + public int FirstRow { get; private set; } + + public int LastRow { get; private set; } + + public int TotalRows { get; private set; } + + public int TotalPages { get; private set; } + + public bool IsLastPage + { + get + { + if (LastRow >= (TotalRows)) + { + return true; + } + else + { + return false; + } + } + } + + public void UpdatePageResults(int firstRow, int lastRow, int totalRows, int totalPages) + { + FirstRow = firstRow; + LastRow = lastRow; + TotalRows = totalRows; + TotalPages = totalPages; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ParameterRedirectAction.cs b/DNN Platform/Library/Entities/Urls/ParameterRedirectAction.cs new file mode 100644 index 00000000000..7936dc3d851 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ParameterRedirectAction.cs @@ -0,0 +1,40 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class ParameterRedirectAction + { + public string Action { get; set; } + public bool ChangeToSiteRoot { get; set; } + public bool ForDefaultPage { get; set; } + public string LookFor { get; set; } + public string Name { get; set; } + public int PortalId { get; set; } + public string RedirectTo { get; set; } + public int TabId { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ParameterReplaceAction.cs b/DNN Platform/Library/Entities/Urls/ParameterReplaceAction.cs new file mode 100644 index 00000000000..2d3059c53ed --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ParameterReplaceAction.cs @@ -0,0 +1,38 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class ParameterReplaceAction + { + public bool ChangeToSiteRoot { get; set; } + public string LookFor { get; set; } + public string Name { get; set; } + public int PortalId { get; set; } + public string ReplaceWith { get; set; } + public int TabId { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/ParameterRewriteAction.cs b/DNN Platform/Library/Entities/Urls/ParameterRewriteAction.cs new file mode 100644 index 00000000000..94738abf5dc --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/ParameterRewriteAction.cs @@ -0,0 +1,38 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class ParameterRewriteAction + { + public bool ForSiteRoot { get; set; } + public string LookFor { get; set; } + public string Name { get; set; } + public int PortalId { get; set; } + public string RewriteTo { get; set; } + public int TabId { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/PathSizes.cs b/DNN Platform/Library/Entities/Urls/PathSizes.cs new file mode 100644 index 00000000000..fa7e1cad64b --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/PathSizes.cs @@ -0,0 +1,65 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + [Serializable] + public class PathSizes + { + public int MaxAliasDepth { get; set; } + public int MaxTabPathDepth{ get; set; } + public int MinAliasDepth { get; set; } + public int MinTabPathDepth { get; set; } + + public void SetAliasDepth(string httpAlias) + { + int aliasPathDepth = httpAlias.Length - httpAlias.Replace("/", "").Length; + if (aliasPathDepth > MaxAliasDepth) + { + MaxAliasDepth = aliasPathDepth; + } + if (aliasPathDepth < MinAliasDepth) + { + MinAliasDepth = aliasPathDepth; + } + } + + public void SetTabPathDepth(int tabPathDepth) + { + if (tabPathDepth > MaxTabPathDepth) + { + MaxTabPathDepth = tabPathDepth; + } + if (tabPathDepth < MinTabPathDepth) + { + MinTabPathDepth = tabPathDepth; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/RedirectController.cs b/DNN Platform/Library/Entities/Urls/RedirectController.cs new file mode 100644 index 00000000000..e54b5526221 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/RedirectController.cs @@ -0,0 +1,443 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal class RedirectController + { + /// + /// Cancels a redirect + /// + /// + /// + /// + /// + internal static void CancelRedirect(ref UrlAction result, HttpContext context, FriendlyUrlSettings settings, string message) + { + result.Action = ActionType.Continue; + result.Reason = RedirectReason.Not_Redirected; + result.FinalUrl = null; + //clean the path for the rewrite + NameValueCollection queryString = null; + if (context != null) + { + queryString = context.Request.QueryString; + } + result.RewritePath = RedirectTokens.RemoveAnyRedirectTokens(result.RewritePath, queryString); + //redo the rewrite to fix up the problem. The user has ticked 'permanent redirect' but hasn't supplied a forwarding Url + if (context != null) + //if no context supplied, means no rewrite was required because querystring didn't contain do301 action + { + //RewriterUtils.RewriteUrl(context, result.RewritePath, settings.RebaseClientPath); + RewriterUtils.RewriteUrl(context, result.RewritePath); + } + result.DebugMessages.Add(message); + } + + /// + /// Checks for a redirect based on a module friendly url provider rule + /// + /// + /// + /// + /// + /// + /// + internal static bool CheckForModuleProviderRedirect(Uri requestUri, + ref UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + var messages = new List(); + string location; + bool redirected = ExtensionUrlProviderController.CheckForRedirect(requestUri, + result, + queryStringCol, + settings, + out location, + ref messages, + parentTraceId); + if (messages != null) + { + result.DebugMessages.AddRange(messages); + } + if (redirected) + { + result.FinalUrl = location; + result.Action = ActionType.Redirect301; + result.Reason = RedirectReason.Custom_Redirect; + } + return redirected; + } + + internal static bool CheckForParameterRedirect(Uri requestUri, + ref UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings) + { + //check for parameter replaced works by inspecting the parameters on a rewritten request, comparing + //them agains the list of regex expressions on the friendlyurls.config file, and redirecting to the same page + //but with new parameters, if there was a match + bool redirect = false; + //get the redirect actions for this portal + var messages = new List(); + Dictionary> redirectActions = CacheController.GetParameterRedirects(settings, result.PortalId, ref messages); + if (redirectActions != null && redirectActions.Count > 0) + { + try + { + #region trycatch block + + string rewrittenUrl = result.RewritePath ?? result.RawUrl; + + List parmRedirects = null; + //find the matching redirects for the tabid + int tabId = result.TabId; + if (tabId > -1) + { + if (redirectActions.ContainsKey(tabId)) + { + //find the right set of replaced actions for this tab + parmRedirects = redirectActions[tabId]; + } + } + //check for 'all tabs' redirections + if (redirectActions.ContainsKey(-1)) //-1 means 'all tabs' - rewriting across all tabs + { + //initialise to empty collection if there are no specific tab redirects + if (parmRedirects == null) + { + parmRedirects = new List(); + } + //add in the all redirects + List allRedirects = redirectActions[-1]; + parmRedirects.AddRange(allRedirects); //add the 'all' range to the tab range + tabId = result.TabId; + } + if (redirectActions.ContainsKey(-2) && result.OriginalPath.ToLower().Contains("default.aspx")) + { + //for the default.aspx page + if (parmRedirects == null) + { + parmRedirects = new List(); + } + List defaultRedirects = redirectActions[-2]; + parmRedirects.AddRange(defaultRedirects); //add the default.aspx redirects to the list + tabId = result.TabId; + } + //726 : allow for site-root redirects, ie redirects where no page match + if (redirectActions.ContainsKey(-3)) + { + //request is for site root + if (parmRedirects == null) + { + parmRedirects = new List(); + } + List siteRootRedirects = redirectActions[-3]; + parmRedirects.AddRange(siteRootRedirects); //add the site root redirects to the collection + } + //OK what we have now is a list of redirects for the currently requested tab (either because it was specified by tab id, + // or because there is a replaced for 'all tabs' + + var tc = new TabController(); + if (parmRedirects != null && parmRedirects.Count > 0 && rewrittenUrl != null) + { + foreach (ParameterRedirectAction parmRedirect in parmRedirects) + { + //regex test each replaced to see if there is a match between the parameter string + //and the parmRedirect + string compareWith = rewrittenUrl; + var redirectRegex = new Regex(parmRedirect.LookFor, + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + Match regexMatch = redirectRegex.Match(compareWith); + bool success = regexMatch.Success; + bool siteRootTried = false; + //if no match, but there is a site root redirect to try + if (!success && parmRedirect.TabId == -3) + { + siteRootTried = true; + compareWith = result.OriginalPathNoAlias; + regexMatch = redirectRegex.Match(compareWith); + success = regexMatch.Success; + } + if (!success) + { + result.DebugMessages.Add(parmRedirect.Name + " redirect not matched (" + rewrittenUrl + + ")"); + if (siteRootTried) + { + result.DebugMessages.Add(parmRedirect.Name + " redirect not matched [site root] (" + + result.OriginalPathNoAlias + ")"); + } + } + else + { + //success! there was a match in the parameters + string parms = redirectRegex.Replace(compareWith, parmRedirect.RedirectTo); + if (siteRootTried) + { + result.DebugMessages.Add(parmRedirect.Name + " redirect matched [site root] with (" + + result.OriginalPathNoAlias + "), replaced with " + parms); + } + else + { + result.DebugMessages.Add(parmRedirect.Name + " redirect matched with (" + + compareWith + "), replaced with " + parms); + } + string finalUrl = ""; + //now we need to generate the friendly Url + + //first check to see if the parameter replacement string has a destination tabid specified + if (parms.ToLower().Contains("tabid/")) + { + //if so, using a feature whereby the dest tabid can be changed within the parameters, which will + //redirect the page as well as redirecting the parameter values + string[] parmParts = parms.Split('/'); + bool tabIdNext = false; + foreach (string parmPart in parmParts) + { + if (tabIdNext) + { + //changes the tabid of page, effects a page redirect along with a parameter redirect + Int32.TryParse(parmPart, out tabId); + parms = parms.Replace("tabid/" + tabId.ToString(), ""); + //remove the tabid/xx from the path + break; //that's it, we're finished + } + if (parmPart.ToLower() == "tabid") + { + tabIdNext = true; + } + } + } + else if (tabId == -1) + { + //find the home tabid for this portal + //735 : switch to custom method for getting portal + PortalInfo portal = CacheController.GetPortal(result.PortalId, true); + tabId = portal.HomeTabId; + } + if (parmRedirect.ChangeToSiteRoot) + { + //when change to siteroot requested, new path goes directly off the portal alias + //so set the finalUrl as the poratl alias + finalUrl = result.Scheme + result.HttpAlias + "/"; + } + else + { + //if the tabid has been supplied, do a friendly url provider lookup to get the correct format for the tab url + if (tabId > -1) + { + TabInfo tab = tc.GetTab(tabId, result.PortalId, false); + if (tab != null) + { + string path = Globals.glbDefaultPage + TabIndexController.CreateRewritePath(tab.TabID, ""); + string friendlyUrlNoParms = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(tab, + path, + Globals.glbDefaultPage, + result.HttpAlias, + false, + settings, + Guid.Empty); + if (friendlyUrlNoParms.EndsWith("/") == false) + { + friendlyUrlNoParms += "/"; + } + finalUrl = friendlyUrlNoParms; + } + if (tab == null) + { + result.DebugMessages.Add(parmRedirect.Name + + " tabId in redirect rule (tabId:" + + tabId.ToString() + ", portalId:" + + result.PortalId.ToString() + + " ), tab was not found"); + } + else + { + result.DebugMessages.Add(parmRedirect.Name + + " tabId in redirect rule (tabId:" + + tabId.ToString() + ", portalId:" + + result.PortalId.ToString() + " ), tab found : " + + tab.TabName); + } + } + } + if (parms.StartsWith("//")) + { + parms = parms.Substring(2); + } + if (parms.StartsWith("/")) + { + parms = parms.Substring(1); + } + + if (settings.PageExtensionUsageType != PageExtensionUsageType.Never) + { + if (parms.EndsWith("/")) + { + parms = parms.TrimEnd('/'); + } + if (parms.Length > 0) + { + //we are adding more parms onto the end, so remove the page extension + //from the parameter list + //946 : exception when settings.PageExtension value is empty + parms += settings.PageExtension; + //816: if page extension is /, then don't do this + if (settings.PageExtension != "/" && + string.IsNullOrEmpty(settings.PageExtension) == false) + { + finalUrl = finalUrl.Replace(settings.PageExtension, ""); + } + } + else + { + //we are removing all the parms altogether, so + //the url needs to end in the page extension only + //816: if page extension is /, then don't do this + if (settings.PageExtension != "/" && + string.IsNullOrEmpty(settings.PageExtension) == false) + { + finalUrl = finalUrl.Replace(settings.PageExtension + "/", + settings.PageExtension); + } + } + } + //put the replaced parms back on the end + finalUrl += parms; + + //set the final url + result.FinalUrl = finalUrl; + result.Reason = RedirectReason.Custom_Redirect; + switch (parmRedirect.Action) + { + case "301": + result.Action = ActionType.Redirect301; + break; + case "302": + result.Action = ActionType.Redirect302; + break; + case "404": + result.Action = ActionType.Output404; + break; + } + redirect = true; + break; + } + } + } + + #endregion + } + catch (Exception ex) + { + Services.Exceptions.Exceptions.LogException(ex); + messages.Add("Exception: " + ex.Message + "\n" + ex.StackTrace); + } + finally + { + if (messages.Count > 0) + { + result.DebugMessages.AddRange(messages); + } + } + } + return redirect; + } + + /// + /// Gets a redirect Url for when the tab has a specified external Url that is of type 'TabType.Tab'. This covers both + /// 'PermanentRedirect' and 'ExternalUrl' scenarios, where the settings are to redirect the value. + /// + /// + /// + /// + /// + /// + /// + /// + /// 823 : Moved from CheckForRedirects to allow call earlier in pipeline + internal static string GetTabRedirectUrl(TabInfo tab, + FriendlyUrlSettings settings, + string cleanPath, + UrlAction result, + out bool permRedirect, + Guid parentTraceId) + { + string bestFriendlyUrl = null; + //592 : check for permanent redirect + permRedirect = tab.PermanentRedirect; + int redirectTabId; + if (int.TryParse(tab.Url, out redirectTabId)) + { + //ok, redirecting to a new tab, specified by the tabid in the Url field + var tc = new TabController(); + TabInfo redirectTab = tc.GetTab(redirectTabId, tab.PortalID, false); + if (redirectTab != null) + { + //now get the friendly url for that tab + bestFriendlyUrl = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(redirectTab, + cleanPath, + Globals.glbDefaultPage, + result.HttpAlias, + false, + settings, + parentTraceId); + } + } + else + { + //use the url, as specified in the dnn tab url property + //776 : when no url, don't redirect + if (tab.Url != "") + { + bestFriendlyUrl = tab.Url; + } + else + { + //776: no actual Url for the 'perm redirect'. + //this is a mistake on the part of the person who created the perm redirect + //but don't create a redirect or there will be a terminal loop + permRedirect = false; + } + } + return bestFriendlyUrl; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/RedirectReason.cs b/DNN Platform/Library/Entities/Urls/RedirectReason.cs new file mode 100644 index 00000000000..aa331376e61 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/RedirectReason.cs @@ -0,0 +1,65 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum RedirectReason + { + Unfriendly_Url_1, + Unfriendly_Url_2, + Not_Lower_Case, + Wrong_Sub_Domain, + Custom_Redirect, + Wrong_Portal, + Not_Redirected, + Deleted_Page, + Disabled_Page, + Spaces_Replaced, + Wrong_Portal_Alias, + Wrong_Portal_Alias_For_Browser_Type, + Wrong_Portal_Alias_For_Culture, + Wrong_Portal_Alias_For_Culture_And_Browser, + Custom_Tab_Alias, + Site_Root_Home, + Secure_Page_Requested, + Tab_External_Url, + Tab_Permanent_Redirect, + Host_Portal_Used, + Alias_In_Url, + User_Profile_Url, + Unfriendly_Url_Child_Portal, + Unfriendly_Url_TabId, + Error_Event, + No_Portal_Alias, + Requested_404, + Requested_404_In_Url, + Page_404, + Exception, + File_Url, + Built_In_Url, + SiteUrls_Config_Rule, + Diacritic_Characters, + Module_Provider_Rewrite_Redirect, + Module_Provider_Redirect + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/RedirectTokens.cs b/DNN Platform/Library/Entities/Urls/RedirectTokens.cs new file mode 100644 index 00000000000..a3d52692b17 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/RedirectTokens.cs @@ -0,0 +1,538 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Text.RegularExpressions; + +namespace DotNetNuke.Entities.Urls +{ + /// + /// This class contains helpers which set the redirect action and reason tokens. These are fake additions to the rewritten query string + /// which are used as a type of property to store intent of a particular url in the page index. This is done to keep the base type + /// stored in the page index dictionary as a value type (string) rather than a object type with properties. So the two 'properties' + /// of a Url are the action (ie 301 redirect, 302 redirect, 404, etc) and the reason (home page redirect, etc) are stored as + /// part of the rewritten querystring in the index. These then have to be removed and translated back to 'action' parameters + /// when the rewriting actually happens. So all methods in this class are to do with either storing or retrieving these tokens. + /// + internal static class RedirectTokens + { + #region Private Methods + + /// + /// Returns the list of tokens found in a rewrite path as a key/value dictionary + /// + /// + /// Rewritten Url path + /// + /// + /// + /// Returns a list of the redirect tokens found in the querystring + /// + /// + private static List GetRedirectReasonTokensFromRewritePath(string rewritePath) + { + var reasons = new List(); + MatchCollection matches = Regex.Matches(rewritePath, @"&rr=(?[^&].)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + foreach (Match match in matches) + { + if (match.Success) + { + Group rrG = match.Groups["rr"]; + if (rrG.Success) + { + string rr = match.Groups["rr"].Value; + reasons.Add(rr); + } + } + } + return reasons; + } + + private static void GetRedirectActionTokenAndValue(ActionType action, out string token, out string value) + { + switch (action) + { + case ActionType.CheckFor301: + token = "do301"; + value = "check"; + break; + case ActionType.Redirect301: + token = "do301"; + value = "true"; + break; + case ActionType.Output404: + token = "do404"; + value = "true"; + break; + case ActionType.Redirect302: + token = "do302"; + value = "true"; + break; + default: + token = ""; + value = ""; + break; + } + } + + private static string GetRedirectReasonRewriteToken(RedirectReason reason) + { + string result = ""; + switch (reason) + { + case RedirectReason.Deleted_Page: + result = "&rr=dl"; + break; + case RedirectReason.Disabled_Page: + //838 : handle disabled page separately + result = "&rr=db"; + break; + case RedirectReason.Tab_Permanent_Redirect: + result = "&rr=pr"; + break; + case RedirectReason.Spaces_Replaced: + result = "&rr=sr"; + break; + case RedirectReason.Site_Root_Home: + result = "&rr=hp"; + break; + case RedirectReason.Diacritic_Characters: + result = "&rr=dc"; + break; + case RedirectReason.User_Profile_Url: + result = "&rr=up"; + break; + case RedirectReason.Custom_Redirect: + result = "&rr=cr"; + break; + } + return result; + } + + private static Dictionary GetRedirectTokensAndValuesFromRewritePath(string rewritePath, out bool hasDupes) + { + hasDupes = false; + var results = new Dictionary(); + MatchCollection matches = Regex.Matches(rewritePath, + @"(?<=(?

&|\?))(?do301|do302|do404)=(?[^&]+)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + foreach (Match tokenMatch in matches) + { + string tk = tokenMatch.Groups["tk"].Value; + string val = tokenMatch.Groups["val"].Value; + if (results.ContainsKey(tk)) + { + hasDupes = true; + } + else + { + results.Add(tk, val); + } + } + return results; + } + + #endregion + + #region Internal Methods + + ///

+ /// Adds on a redirect reason to the rewrite path + /// + /// + /// + /// + /// + internal static string AddRedirectReasonToRewritePath(string existingRewritePath, ActionType action, RedirectReason reason) + { + string result = existingRewritePath; + string token, value; + GetRedirectActionTokenAndValue(action, out token, out value); + string tokenAndValue = token + "=" + value; + bool addToken = true; + //look for existing action + bool hasDupes; + Dictionary tokensAndValues = GetRedirectTokensAndValuesFromRewritePath(existingRewritePath, + out hasDupes); + //can't overwrite existing tokens in certain cases + if (tokensAndValues.Count > 0) + { + //only case we allow is an ovewrite of a do301=check by a do301=true or do302=true + if (token == "do301" || token == "do302") + { + if (tokensAndValues.ContainsKey("do301") && tokensAndValues["do301"] == "check") + { + result = existingRewritePath.Replace("do301=check", tokenAndValue); + } + } + addToken = false; //already done + } + if (addToken) + { + if (result.Contains(tokenAndValue) == false) + { + if (result.Contains("?")) + { + result += "&" + tokenAndValue; + } + else + { + result += "?" + tokenAndValue; + } + + //the reasonToken helps the rewrite process determine why a redirect is required + //after the token is stored in the page dictionary + string reasonToken = GetRedirectReasonRewriteToken(reason); + if (reasonToken != "") + { + result += reasonToken; + } + } + else + { + //special case : add the number of times a 301 has been requested + if (tokenAndValue == "do301=true" && reason == RedirectReason.User_Profile_Url) + { + result += "&num301=2"; + } + } + } + return result; + } + + /// + /// DetermineRedirectReasonAndAction extracts the redirect value from the rewrite url and + /// returns the new rewritten url, and the reason for the redirection, and an action value for the type of redirect + /// + /// Rewritten url as found in page dictionary + /// The current rewrite result. + /// true if there are parameters in the path, false if not + /// current FriendlyUrlSettings object + /// New action value for UrlAction object + /// New redirect reason value for UrlAction object + /// Url to used for rewrite process + /// the new Url, with any replacements done. Replacements occur when a reason token + /// was stored in the tab dictionary entry just to indicate a redirect reason. + internal static void DetermineRedirectReasonAndAction(string rewrittenUrl, + UrlAction result, + bool wasParms, + FriendlyUrlSettings settings, + out string newUrl, + out RedirectReason reason, + out ActionType action) + { + //init parms + newUrl = rewrittenUrl; + action = result.Action; + reason = result.Reason; + + //get the action type from the rewrite path + ActionType foundAction; + bool actionInPath = GetActionFromRewritePath(rewrittenUrl, out foundAction); + //only overrwrite action if it was found in the rewrite path + if (actionInPath) + { + action = foundAction; + } + //get the list of redirect reason tokens from the url + List redirectReasons = GetRedirectReasonTokensFromRewritePath(rewrittenUrl); + + //when redirect action in path, and redirect reasons are empty, add custom redirect + if (redirectReasons.Count == 0 && action != ActionType.Continue) + { + redirectReasons.Add("cr"); + } + bool clearActionToken = false; + foreach (string rrTkn in redirectReasons) + { + switch (rrTkn) + { + case "up": + //user profile redirect + clearActionToken = true; + if (wasParms) + { + if (reason == RedirectReason.Not_Redirected) + { + if (settings.RedirectOldProfileUrl) + { + reason = RedirectReason.User_Profile_Url; + action = ActionType.CheckFor301; + } + else + { + action = ActionType.Continue; + } + } + } + else + { + //if no parms, then we're not doing a userprofileaction redirect + reason = RedirectReason.Custom_Redirect; + //then check for a 301 redirect + action = ActionType.CheckFor301; + } + + break; + + case "dl": + case "db": + //deleted tab dl + //disabled tab db + clearActionToken = true; + //626 Deleted tab hanlding not working properyly - override + if (settings.DeletedTabHandlingType == DeletedTabHandlingType.Do404Error) + { + action = ActionType.Output404; //output a 404 as per settings + } + + //838 : handle disabled pages separately + reason = rrTkn == "dl" ? RedirectReason.Deleted_Page : RedirectReason.Disabled_Page; + break; + + case "pr": + //pr = permanent redirect + reason = RedirectReason.Tab_Permanent_Redirect; + clearActionToken = true; + break; + + case "sr": + //sr = spaces replaced in url + clearActionToken = true; + reason = RedirectReason.Spaces_Replaced; + break; + + case "hp": + //hp = home page redirect + if (wasParms) + { + //cancel the home page replaced if there were parameters added and page extensions + //are in use - otherwise a 404 will occur for the relative path + reason = RedirectReason.Not_Redirected; + action = ActionType.Continue; + clearActionToken = true; + } + else + { + reason = RedirectReason.Site_Root_Home; + clearActionToken = true; + } + break; + + + default: + //any other redirect with no reason is a custom redirect + if (reason == RedirectReason.Not_Redirected) + { + reason = RedirectReason.Custom_Redirect; + } + clearActionToken = true; + break; + } + } + if (clearActionToken) + { + //clear both action and reason + newUrl = RemoveAnyRedirectTokensAndReasons(newUrl); + } + else + { + //clear just reason + newUrl = RemoveAnyRedirectReasons(newUrl); + } + } + + /// + /// Return the action type from a rewritten Url + /// + /// + /// + /// + internal static bool GetActionFromRewritePath(string rewrittenUrl, out ActionType action) + { + bool found = false; + action = ActionType.Continue; //default + MatchCollection actionMatches = Regex.Matches(rewrittenUrl, + @"(?<=(?

&|\?))(?do301|do302|do404)=(?[^&]+)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + foreach (Match actionMatch in actionMatches) + { + if (actionMatch.Success) + { + found = true; + string tk = actionMatch.Groups["tk"].Value; + string val = actionMatch.Groups["val"].Value; + switch (tk.ToLower()) + { + case "do301": + if (val.ToLower() == "true") + { + action = ActionType.Redirect301; + } + else + { + if (val.ToLower() == "check") + { + action = ActionType.CheckFor301; + } + } + break; + case "do404": + if (val.ToLower() == "true") + { + action = ActionType.Output404; + } + break; + case "do302": + if (val.ToLower() == "true") + { + action = ActionType.Redirect302; + } + break; + } + //if there is more than one match, if we have a solid action, then break + if (action != ActionType.Continue) + { + break; //this should, by rights, not happen in normal operation + } + } + } + return found; + } + + ///

+ /// Removes any reason tokens from the querystring + /// + /// + /// + internal static string RemoveAnyRedirectReasons(string rewritePath) + { + return Regex.Replace(rewritePath, @"&rr=(?[^&].)", ""); + } + + /// + /// Removes any redirect tokens from the rewrite path + /// + /// + /// + /// + internal static string RemoveAnyRedirectTokens(string path, NameValueCollection queryStringCol) + { + //don't really care what the value is, but need it for replacing + //the do301 is an internal value, used to control redirects from the page index + if (string.IsNullOrEmpty(path) == false) + { + string val = null; + if (queryStringCol != null) + { + val = queryStringCol["do301"]; + } + if (string.IsNullOrEmpty(val)) + { + val = "true"; + } + //nix the 301 redirect query string value or terminal loops-a-plenty + path = path.Replace("&do301=" + val, ""); + path = path.Replace("?do301=" + val, ""); + + //911 : object not set error + if (queryStringCol != null) + { + val = queryStringCol["do302"]; + } + if (string.IsNullOrEmpty(val)) + { + val = "true"; + } + //nix the 302 redirect query string value or terminal loops-a-plenty + path = path.Replace("&do302=" + val, ""); + path = path.Replace("?do302=" + val, ""); + } + return path; + } + + /// + /// Removes and redirect tokens and redirect reasons from the rewritePath + /// + /// + /// + internal static string RemoveAnyRedirectTokensAndReasons(string rewritePath) + { + string result = RemoveAnyRedirectReasons(rewritePath); + //regex expression matches a token and removes it + Match tokenMatch = Regex.Match(result, @"(?<=(?

&|\?))(?do301|do302|do404)=(?[^&]+)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (tokenMatch.Success) + { + //tokenAndValue is the do301=true + string tokenAndValue = tokenMatch.Value; + //p is either a ? or a & + string p = tokenMatch.Groups["p"].Value; + if (p == "?") + { + result = result.Replace(tokenAndValue, ""); + if (result.Contains("?&")) + { + result = result.Replace("?&", "?"); + } + else + { + if (result.EndsWith("?") || result.EndsWith("&")) + { + //trim end + result = result.Substring(0, result.Length - 1); + } + } + } + else + { + //p == "&" + result = result.Replace("&" + tokenAndValue, ""); + } + } + + return result; + } + + ///

+ /// Sets the Action and Reason values in the UrlAction parameter + /// + /// + /// + internal static void SetRedirectReasonAndAction(ref UrlAction result, FriendlyUrlSettings settings) + { + RedirectReason reason; + ActionType action; + string newUrl; + DetermineRedirectReasonAndAction(result.RewritePath, result, true, settings, out newUrl, out reason, + out action); + result.Action = action; + result.Reason = reason; + result.RewritePath = newUrl; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/RewriteController.cs b/DNN Platform/Library/Entities/Urls/RewriteController.cs new file mode 100644 index 00000000000..a18398c19b6 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/RewriteController.cs @@ -0,0 +1,1801 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.Caching; +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Urls.Config; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class RewriteController + { + internal const int SiteRootRewrite = -3; + internal const int AllTabsRewrite = -1; + + #region Private Methods + + private static string AddQueryStringToRewritePath(string rewritePath, string queryString) + { + //now add back querystring if they existed + if (queryString != "") + { + bool rewritePathHasQuery = rewritePath.IndexOf("?", StringComparison.Ordinal) != -1; + if (queryString.StartsWith("?")) + { + queryString = queryString.Substring(1); + } + string[] parms = queryString.Split('&'); + // iterate through the array of parameters + for (int i = 0; i < parms.Length; i++) + { + bool hasValue = false; + // get parameter name + string parmName = parms[i]; + //check if parm name contains a value as well + if (parmName.IndexOf("=", StringComparison.Ordinal) != -1) + { + //snip off the =value part of the parm + parmName = parmName.Substring(0, parmName.IndexOf("=", StringComparison.Ordinal)); + hasValue = true; + } + //597 : do a compare with the '=' on the end to only + //compare the entire parmname, not just the start + string comparePath1 = "?" + parmName.ToLower(); + string comparePath2 = "&" + parmName.ToLower(); + if (hasValue) + { + comparePath1 += "="; + comparePath2 += "="; + } + // check if parameter already exists in the rewrite path + // we only want to add the querystring back on if the + // query string keys were not already shown in the friendly + // url path + if (!rewritePath.ToLower().Contains(comparePath1) + && !rewritePath.ToLower().Contains(comparePath2)) + { + //622 : remove encoding from querystring paths + //699 : reverses 622 because works from Request.QUeryString instead of Request.Url.Query + //string queryStringPiece = System.Web.HttpUtility.UrlDecode(parms[i]); + string queryStringPiece = parms[i]; + //no decoding - querystring passes through rewriting process untouched + // add parameter to SendTo value + if (rewritePathHasQuery) + { + rewritePath = rewritePath + "&" + queryStringPiece; + } + else + { + rewritePath = rewritePath + "?" + queryStringPiece; + rewritePathHasQuery = true; + } + } + } + } + return rewritePath; + } + + private static string CheckIfPortalAlias(string url, NameValueCollection querystringCol, UrlAction result, FriendlyUrlSettings settings, SharedDictionary tabDict) + { + string newUrl = url; + bool reWritten = false; + + string defaultPage = Globals.glbDefaultPage.ToLower(); + string portalAliasUrl = url.ToLower().Replace("/" + defaultPage, ""); + //if there is a straight match on a portal alias, it's the home page for that portal requested + var portalAlias = PortalAliasController.GetPortalAliasInfo(portalAliasUrl); + if (portalAlias != null) + { + //special case : sometimes, some servers issue root/default.aspx when root/ was requested, sometimes not. It depends + //on other server software installed (apparently) + //so check the raw Url and the url, and see if they are the same except for the /default.aspx + string rawUrl = result.RawUrl; + if (url.ToLower().EndsWith(rawUrl + defaultPage.ToLower())) + { + //special case - change the url to be equal to the raw Url + url = url.Substring(0, url.Length - defaultPage.Length); + } + + if (settings.RedirectDefaultPage + && url.ToLower().EndsWith("/" + defaultPage) + && result.RedirectAllowed) + { + result.Reason = RedirectReason.Site_Root_Home; + result.FinalUrl = Globals.AddHTTP(portalAliasUrl + "/"); + result.Action = ActionType.Redirect301; + } + else + { + //special case -> look in the tabdict for a blank intercept + //735 : switch to custom method for getting portal + PortalInfo portal = CacheController.GetPortal(portalAlias.PortalID, true); + if (portal.HomeTabId == -1) + { + string tabKey = url; + if (tabKey.EndsWith("/")) + { + tabKey = tabKey.TrimEnd('/'); + } + tabKey += "::"; + using (tabDict.GetReadLock()) + { + if (tabDict.ContainsKey(tabKey)) + { + newUrl = tabDict[tabKey]; + reWritten = true; + } + } + //if no home tab, but matched a portal alias, and no trailing /default.aspx + //and no 'newUrl' value because not rewritten, then append the /default.aspx + //and ask for a rewrite on that one. + //DNNDEV-27291 + if (reWritten == false) + { + newUrl = "/" + DotNetNuke.Common.Globals.glbDefaultPage; + reWritten = true; + } + } + else + { + //set rewrite to home page of site + //760: check for portal alias specific culture before choosing home tabid + bool checkForCustomAlias = false; + bool customTabAlias = false; + //check for culture-specific aliases + string culture = null; + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portal.PortalID).ToList(); + //if there are chosen portal aliases, check to see if the found alias is one of them + //if not, then will check for a custom alias per tab + if (primaryAliases.ContainsAlias(portal.PortalID, portalAlias.HTTPAlias) == false) + { + checkForCustomAlias = true; + } + else + { + //check for a specific culture for the alias + culture = primaryAliases.GetCultureByPortalIdAndAlias(portal.PortalID, portalAlias.HTTPAlias); + } + if (checkForCustomAlias) + { + //ok, this isnt' a chosen portal alias, check the list of custom aliases + List customAliasesForTabs = TabIndexController.GetCustomPortalAliases(settings); + if (customAliasesForTabs != null && customAliasesForTabs.Contains(portalAlias.HTTPAlias.ToLower())) + { + //ok, the alias is used as a custom tab, so now look in the dictionary to see if it's used a 'root' context + string tabKey = url.ToLower(); + if (tabKey.EndsWith("/")) + { + tabKey = tabKey.TrimEnd('/'); + } + if (tabKey.EndsWith("/default.aspx")) + { + tabKey = tabKey.Substring(0, tabKey.Length - 13); //13 = "/default.aspx".length + } + tabKey += "::"; + using (tabDict.GetReadLock()) + { + if (tabDict.ContainsKey(tabKey)) + { + newUrl = tabDict[tabKey]; + reWritten = true; + customTabAlias = true; //this alias is used as the alias for a custom tab + } + } + } + } + if (customTabAlias == false) + { + int tabId; + if (!String.IsNullOrEmpty(querystringCol["TabId"])) + { + tabId = Convert.ToInt32(querystringCol["TabId"]); + result.Action = ActionType.CheckFor301; + } + else + { + tabId = portal.HomeTabId; + //not a custom alias for a specific tab, so it must be the home page for the portal we identified + if (culture == null) + { + culture = portal.DefaultLanguage; //set culture to default if not found specifically + } + else + { + //if there is a specific culture for this alias, and it's different to the default language, then + //go check for a specific culture home page (5.5 and later) + tabId = TabPathHelper.GetHomePageTabIdForCulture(portal.DefaultLanguage, + portal.PortalID, + culture, + tabId); + } + } + //see if there is a skin for the alias/culture combination + string skin = TabPathHelper.GetTabAliasSkinForTabAndAlias(portalAlias.PortalID, + portalAlias.HTTPAlias, culture); + if (string.IsNullOrEmpty(skin) == false) + { + newUrl = Globals.glbDefaultPage + TabIndexController.CreateRewritePath(tabId, "", "skinSrc=" + skin); + } + else + { + newUrl = Globals.glbDefaultPage + TabIndexController.CreateRewritePath(tabId, ""); + } + if (culture != portal.DefaultLanguage) + { + AddLanguageCodeToRewritePath(ref newUrl, culture); + } + //add on language specified by current portal alias + reWritten = true; + } + } + } + + if (reWritten) + { + //check for replaced to site root from /default.aspx + // 838 set redirect reason and action from result + SetRewriteParameters(ref result, newUrl); + ActionType action; + RedirectReason reason; + string resultingUrl; + RedirectTokens.DetermineRedirectReasonAndAction(newUrl, result, true, settings, out resultingUrl, out reason, out action); + newUrl = resultingUrl; + result.Action = action; + result.Reason = reason; + } + } + return newUrl; + } + + private static bool CheckSpecialCase(string tabKeyVal, SharedDictionary tabDict) + { + bool found = false; + int pathStart = tabKeyVal.LastIndexOf("::", StringComparison.Ordinal); //look for portal alias separator + int lastPath = tabKeyVal.LastIndexOf('/'); + //get any path separator in the tab path portion + if (pathStart > lastPath) + { + lastPath = pathStart; + } + if (lastPath >= 0) + { + int defaultStart = tabKeyVal.ToLower().IndexOf("default", lastPath, StringComparison.Ordinal); + //no .aspx on the end anymore + if (defaultStart > 0 && defaultStart > lastPath) + //there is a default in the path, and it's not the entire path (ie pagnamedefault and not default) + { + tabKeyVal = tabKeyVal.Substring(0, defaultStart); + //get rid of the default.aspx part + using (tabDict.GetReadLock()) + { + found = tabDict.ContainsKey(tabKeyVal); + //lookup the tabpath in the tab dictionary again + } + } + } + return found; + } + + private static UserInfo GetUser(int portalId, string vanityUrl) + { + string cacheKey = string.Format(CacheController.VanityUrlLookupKey, portalId); + var vanityUrlLookupDictionary = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, 20, CacheItemPriority.High, portalId), + (c) => new Dictionary()); + + if (!vanityUrlLookupDictionary.ContainsKey(vanityUrl)) + { + vanityUrlLookupDictionary[vanityUrl] = UserController.GetUserByVanityUrl(portalId, vanityUrl); + } + + return vanityUrlLookupDictionary[vanityUrl]; + } + + + private static bool CheckTabPath(string tabKeyVal, UrlAction result, FriendlyUrlSettings settings, SharedDictionary tabDict, ref string newUrl) + { + bool found; + string userParam = String.Empty; + string tabLookUpKey = tabKeyVal; + using (tabDict.GetReadLock()) + { + found = tabDict.ContainsKey(tabLookUpKey); //lookup the tabpath in the tab dictionary + } + + //special case, if no extensions and the last part of the tabKeyVal contains default.aspx, then + //split off the default.aspx part and try again - compensating for gemini issue http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=8651&PROJID=39 + if (!found && settings.PageExtensionUsageType != PageExtensionUsageType.AlwaysUse) + { + found = CheckSpecialCase(tabLookUpKey, tabDict); + } + + //Check for VanityUrl + var doNotRedirectRegex = new Regex(settings.DoNotRedirectRegex); + if (!found && !AdvancedUrlRewriter.ServiceApi.IsMatch(result.RawUrl) && !doNotRedirectRegex.IsMatch(result.RawUrl)) + { + string[] urlParams = tabLookUpKey.Split(new[] { "::" }, StringSplitOptions.None); + if (urlParams.Length > 1) + { + //Extract the first Url parameter + string tabPath = urlParams[1]; + + var urlSegments = tabPath.Split('/'); + + string prefix = urlSegments[0]; + + if (prefix == settings.VanityUrlPrefix && urlSegments.Length == 2) + { + string vanityUrl = urlSegments[1]; + + //check if its a vanityUrl + var user = GetUser(result.PortalId, vanityUrl); + if (user != null) + { + userParam = "UserId=" + user.UserID.ToString(); + + //Get the User profile Tab + var portal = new PortalController().GetPortal(result.PortalId); + var profilePage = new TabController().GetTab(portal.UserTabId, result.PortalId, false); + + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + string profilePagePath = TabPathHelper.GetFriendlyUrlTabPath(profilePage, options, Guid.NewGuid()); + + //modify lookup key; + tabLookUpKey = tabLookUpKey.Replace("::" + String.Format("{0}/{1}", settings.VanityUrlPrefix, vanityUrl), "::" + profilePagePath.TrimStart('/').ToLowerInvariant()); + + using (tabDict.GetReadLock()) + { + found = tabDict.ContainsKey(tabLookUpKey); //lookup the tabpath in the tab dictionary + } + } + } + } + } + + if (found) + { + using (tabDict.GetReadLock()) + { + //determine what the rewritten URl will be + newUrl = tabDict[tabLookUpKey]; + } + if (!String.IsNullOrEmpty(userParam)) + { + newUrl = newUrl + "&" + userParam; + } + //if this is a match on the trigger dictionary rebuild, + //then temporarily store this value in case it's a page name change + //677 : only match if is on actual tabKeyVal match, to prevent site root redirects + //statements were moved into this 'if' statement + result.dictVal = newUrl; + result.dictKey = tabKeyVal; + } + return found; + } + + private static string CheckLanguageMatch(ref string url, UrlAction result) + { + //ok now scan for the language modifier + Match langMatch = Regex.Match(url, "/language/(?.[^/]+)(?:/|$)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + //searches for a string like language/en-US/ in the url + string langParms = ""; + if (langMatch.Success) + { + //OK there is a language modifier in the path + //we want to shift this so it is back on the end where it belongs + langParms = langMatch.Value.TrimEnd('/'); //in the format of /language/en-US only + //it doesn't matter if you get /home.aspx/language/en-US in the url field because the .aspx gets + //removed when matching with the tab dictionary + url = url.Replace(langParms, "") + langParms; + result.CultureCode = langMatch.Groups["code"].Value; //get the culture code in the requested url + + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(result.PortalId).ToList(); + if (primaryAliases.Count > 0) + { + string aliasCulture = primaryAliases.GetCultureByPortalIdAndAlias(result.PortalId, result.HttpAlias); + if (aliasCulture != null) + { + //want to do a 301 check because this potentially has a duplicate of portal alias and culture code in the url, which + //is not the best combination + if (result.Action == ActionType.Continue) + { + result.Action = ActionType.CheckFor301; + } + } + } + } + return langParms; + } + + private static string ReplaceDefaultPage(string newUrl, string requestUrl, IEnumerable list) + { + string url = newUrl; //fall back case: we don't change anything + //iterate the list and replace in the url is a match is found + foreach (string requestPage in list) + { + if (requestUrl.ToLower().Contains(requestPage)) + { + url = newUrl.Replace(Globals.glbDefaultPage, requestPage); + break; + } + } + return url; + } + + private static string RewriteParametersFromModuleProvider(string newUrl, + string tabKeyVal, + string[] urlParms, + bool isSiteRootMatch, + UrlAction result, + FriendlyUrlSettings settings, + out bool rewriteParms, + out bool newAction, + ref List messages, + Guid parentTraceId) + { + string rewrittenUrl; + rewriteParms = ExtensionUrlProviderController.TransformFriendlyUrlPath(newUrl, + tabKeyVal, + urlParms, + isSiteRootMatch, + ref result, + settings, + out rewrittenUrl, + out newAction, + ref messages, + parentTraceId); + if (rewriteParms) + { + result.CustomParmRewrite = true; + } + return rewrittenUrl; + } + + private static void SetRewriteParameters(ref UrlAction result, string rewritePath) + { + //split out found replaced and store tabid, rulePortalId and do301 if found + result.RewritePath = rewritePath; + MatchCollection qsItems = Regex.Matches(rewritePath, @"(?:\&|\?)(?:(?.[^\=\&]*)\=(?.[^\=\&]*))"); + foreach (Match itemMatch in qsItems) + { + string val = itemMatch.Groups["val"].Value; + string key = itemMatch.Groups["key"].Value; + switch (key.ToLower()) + { + case "tabid": + int tabidtemp; + if (Int32.TryParse(val, out tabidtemp)) + { + result.TabId = tabidtemp; + } + break; + case "portalid": + int pid; + if (Int32.TryParse(val, out pid)) + { + result.PortalId = pid; + } + break; + case "language": + result.CultureCode = val; + break; + case "ctl": + //786: force redirect for ctl/terms or ctl/privacy + RequestRedirectOnBuiltInUrl(val, rewritePath, result); + break; + } + } + //remove the application path + result.RewritePath = result.RewritePath.Replace(result.ApplicationPath + "/", ""); + } + + #endregion + + #region Internal Methods + + /// + /// appends a language/culture code value if it is not already present in the rewrite path + /// + /// + /// + /// + internal static bool AddLanguageCodeToRewritePath(ref string rewritePath, string cultureCode) + { + bool changed = false; + //758 : check for any language identifier in the Url before adding a new one, not just the same one + if (!string.IsNullOrEmpty(cultureCode) && !rewritePath.ToLower().Contains("language=")) + { + changed = true; + if (rewritePath.Contains("?")) + { + rewritePath += "&language=" + cultureCode; + } + else + { + rewritePath += "?language=" + cultureCode; + } + } + return changed; + } + + /// + /// appends a skin value to the rewrite path, as long as there is no existing skin in the path + /// + /// + /// The current rewrite path + /// The selected skin + /// + /// + /// 852 : Add skin src to rewrite path for specific aliases + internal static bool AddSkinToRewritePath(int tabId, int portalId, ref string rewritePath, string skin, out string message) + { + bool changed = false; + message = null; + TabInfo tab = null; + if (tabId > 0 && portalId > -1) + { + var tc = new TabController(); + tab = tc.GetTab(tabId, portalId, false); + } + //don't overwrite specific skin at tab level for rewritten Urls + if (tab == null || string.IsNullOrEmpty(tab.SkinSrc)) + { + if (!string.IsNullOrEmpty(skin) && skin != "default" && !rewritePath.ToLower().Contains("skinsrc=")) + { + message = "Added SkinSrc : " + skin; + changed = true; + rewritePath += rewritePath.Contains("?") ? "&SkinSrc=" + skin.Replace(".ascx", "") : "?SkinSrc=" + skin.Replace(".ascx", ""); + } + } + else + { + if (!string.IsNullOrEmpty(tab.SkinSrc)) + { + message = "Tab " + tab.TabID.ToString() + " has skin specified : " + tab.SkinSrc; + if (skin != tab.SkinSrc) + { + message += " - " + skin + " not applied due to tab specific skin"; + } + } + } + return changed; + } + + /// + /// Checks for exclusions on Rewriting the path, based on a regex pattern + /// + /// + /// + /// + /// + internal static bool CanRewriteRequest(UrlAction result, string requestedPath, FriendlyUrlSettings settings) + { + bool retVal; + try + { + //var uri = new Uri(requestedPath); + //if (uri.PathAndQuery.ToLowerInvariant().StartsWith("/default.aspx")) + //{ + // retVal = false; + // result.CanRewrite = StateBoolean.True; + // result.RewritePath = uri.PathAndQuery.Substring(1); + //} + //else + //{ + if (String.IsNullOrEmpty(settings.DoNotRewriteRegex) || + (!Regex.IsMatch(requestedPath, settings.DoNotRewriteRegex, + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))) + { + retVal = true; + result.CanRewrite = StateBoolean.True; + } + else + { + retVal = false; + result.CanRewrite = StateBoolean.False; + } + //} + } + catch (Exception ex) + { + retVal = true; //always rewrite if an error in the regex + + UrlRewriterUtils.LogExceptionInRequest(ex, "NotSet", result); + result.Ex = ex; + } + return retVal; + } + + internal static string CleanExtension(string value, string extension, out bool replaced) + { + return CleanExtension(value, extension, "", out replaced); + } + + internal static string CleanExtension(string value, FriendlyUrlSettings settings, string langParms, out bool replaced) + { + return CleanExtension(value, settings.PageExtension, langParms, out replaced); + } + + internal static string CleanExtension(string value, FriendlyUrlSettings settings, out bool replaced) + { + return CleanExtension(value, settings.PageExtension, "", out replaced); + } + + internal static string CleanExtension(string value, string extension, string langParms, out bool replaced) + { + string result = value; + string ext = extension.ToLower(); + replaced = false; + if (result.ToLower().EndsWith(ext) && ext != "") + { + result = result.Substring(0, result.Length - ext.Length); + replaced = true; + } + else + { + if (result.ToLower().EndsWith(".aspx")) + { + result = result.Substring(0, result.Length - 5); + replaced = true; + } + else + { + //object not set errors when language parameters used + if (string.IsNullOrEmpty(langParms) == false) + { + //safely remove .aspx from the language path without doing a full .aspx -> "" replace on the entire path + if (string.IsNullOrEmpty(result) == false && + result.ToLower().EndsWith(".aspx" + langParms.ToLower())) + { + result = result.Substring(0, result.Length - (5 + langParms.Length)) + langParms; + replaced = true; + } + } + else if (result.EndsWith("/")) + { + result = result.Substring(0, result.Length - 1); + replaced = true; + } + } + } + return result; + } + + /// + /// Returns either the rewritten path (if a rewrite used) or the requested path (if no rewrite used) + /// + /// + /// + /// Url suitable for input into friendly url generation routine + internal static string GetRewriteOrRequestedPath(UrlAction result, Uri requestUri) + { + var pathOnly = result.RewritePath; + if (result.DoRewrite == false) + { + //if no rewrite, then the path should have been a non-friendly path, and therefore can be passed in to get the friendly Url + pathOnly = requestUri.Authority + requestUri.PathAndQuery; + int aliasEnd = + pathOnly.IndexOf(result.PortalAlias.HTTPAlias, StringComparison.InvariantCultureIgnoreCase) + + result.PortalAlias.HTTPAlias.Length; + if (aliasEnd > -1) + { + pathOnly = pathOnly.Substring(aliasEnd); + } + pathOnly = HttpUtility.UrlDecode(pathOnly, Encoding.UTF8); + } + return pathOnly; + } + + internal static string GetTabFromDictionary(string url, NameValueCollection querystringCol, FriendlyUrlSettings settings, UrlAction result, Guid parentTraceId) + { + //retrive the tab dictionary from the cache and get the path depth values + int maxAliasPathDepth; + int maxTabPathDepth; + int minAliasPathDepth; + int minTabPathDepth; + bool triedFixingSubdomain = false; + int curAliasPathDepth = 0; + + var tabDict = TabIndexController.FetchTabDictionary(result.PortalId, + out minTabPathDepth, + out maxTabPathDepth, + out minAliasPathDepth, + out maxAliasPathDepth, + settings, + false, + result.BypassCachedDictionary, + parentTraceId); + + //clean up and prepare the url for scanning + if (url.EndsWith("/")) + { + url = url.TrimEnd('/'); + } + + //ok now scan for the language modifier + string langParms = CheckLanguageMatch(ref url, result); + + //clean off the extension before checking the url matches, but + //remember if an extension existed + bool hadExtension; + string cleanUrl = CleanExtension(url, settings, langParms, out hadExtension); + string[] splitUrl = cleanUrl.Split('/'); + + //initialise logic switches + bool reWritten = false; + bool finished = false; + + string newUrl = CheckIfPortalAlias(url, querystringCol, result, settings, tabDict); + if (newUrl != url) + { + finished = true; + reWritten = true; + } + + //start looping through the url segments looking for a match in the tab dictionary + while (finished == false) + { + //first, try forming up a key based on alias/tabpath + int lastIndex = splitUrl.GetUpperBound(0); + int arraySize = lastIndex + 1; + int totalDepth = maxAliasPathDepth + 1 + maxTabPathDepth + 1; + + //the maximum depth of segments of a valid url + for (int i = lastIndex; i >= 0; i += -1) + { + //only start checking the url when it is in the range of the min->max number of segments + if ((i > minAliasPathDepth & i <= totalDepth)) + { + //join all the tab path sections together + //flag to remember if the incoming path had a .aspx or other pageAndExtension on it + int tabPathStart = curAliasPathDepth + 1; + int tabPathLength = i - curAliasPathDepth; + if ((tabPathStart + tabPathLength) <= arraySize) + { + string tabPath = ""; + if ((tabPathLength > -1)) + { + tabPath = string.Join("/", splitUrl, tabPathStart, tabPathLength); + } + string aliasPath; + if ((curAliasPathDepth <= lastIndex)) + { + aliasPath = string.Join("/", splitUrl, 0, curAliasPathDepth + 1); + } + else + { + finished = true; + break; + } + int parmsSize = lastIndex - i; + int parmStart = i + 1; //determine if any parameters on this value + + //make up the index that is looked for in the Tab Dictionary + string urlPart = aliasPath + "::" + tabPath; + //the :: allows separation of pagename and portal alias + + string tabKeyVal = urlPart.ToLower(); //force lower case lookup, all keys are lower case + + //Try with querystring first If last Index + bool found = false; + if (querystringCol.Count > 0) + { + found = CheckTabPath(tabKeyVal + "?" + querystringCol.ToString().Split('&')[0].ToLowerInvariant(), result, settings, tabDict, ref newUrl); + } + if (!found) + { + found = CheckTabPath(tabKeyVal, result, settings, tabDict, ref newUrl); + } + + bool isSiteRootMatch = false; + if (!found && tabPathLength == 1) + { + //look for special case where the site root has a * value + string siteRootLookup = aliasPath + "::" + "*"; + using (tabDict.GetReadLock()) + { + found = tabDict.ContainsKey(siteRootLookup); + if (found) + { + isSiteRootMatch = true; + newUrl = tabDict[siteRootLookup]; + parmsSize++; //re-increase the parameter size + parmStart--; //shift the point of the parms starting back one + } + } + } + + if (found) + { + if (settings.ProcessRequestList != null) + { + newUrl = ReplaceDefaultPage(newUrl, url, settings.ProcessRequestList); + } + + //look for a plain match on the default.aspx page which indicates no more rewriting needs to be done + if (!isSiteRootMatch && (newUrl == Globals.glbDefaultPage || newUrl == Globals.glbDefaultPage + "[UseBase]")) + { + //the [UseBase] moniker is a shortcut hack. It's used to recognise pages which have been excluded + //from using Friendly Urls. The request will go on to be processed by the dnn siteurls.config processing. + //this stops the loop and exits the function + newUrl = newUrl.Replace("[UseBase]", ""); //get rid of usebase hack pattern + SetRewriteParameters(ref result, newUrl); //set result + finished = true; + } + else + { + //708 : move result rewrite set so that downstream functions know the tabid + SetRewriteParameters(ref result, newUrl); + //found the correct rewrite page, now investigate whether there + //is part of the url path that needs to be converted to tab id's + // Multi Language Urls not being rewritten + if (parmsSize > 0) + { + bool rewriteParms = false; + + //determine the url action and reason from embedded rewriting tokens + ActionType action; + RedirectReason reason; + string resultingUrl; + RedirectTokens.DetermineRedirectReasonAndAction(newUrl, + result, + true, + settings, + out resultingUrl, + out reason, + out action); + newUrl = resultingUrl; + result.Action = action; + result.Reason = reason; + + //copy the parms into a separate array + var urlParms = new string[parmsSize]; + Array.ConstrainedCopy(splitUrl, parmStart, urlParms, 0, parmsSize); + + if (!isSiteRootMatch && result.Reason == RedirectReason.User_Profile_Url) + { + result.Reason = RedirectReason.Not_Redirected; + newUrl = RedirectTokens.RemoveAnyRedirectTokensAndReasons(newUrl); + } + + //738 : check for custom module providers + //894 : allow disable of custom url providers functionality + if (!rewriteParms && settings.EnableCustomProviders) + { + bool newAction; + //newAction tracks whether or not a new 'action' (ie 301, 404, etc) has been requested. + //call the module friendly url providers. Note that the rewriteParms value will be changed if there is a rewrite. + List messages = result.DebugMessages; + newUrl = RewriteParametersFromModuleProvider(newUrl, + tabKeyVal, + urlParms, + isSiteRootMatch, + result, + settings, + out rewriteParms, + out newAction, + ref messages, + parentTraceId); + result.DebugMessages = messages; + if (newAction) + { + finished = true; + } + } + //do a rewrite on the parameters from the stored parameter regex rewrites + if (!rewriteParms) + { + newUrl = RewriteParameters(newUrl, + tabKeyVal, + urlParms, + isSiteRootMatch, + result, + out rewriteParms, + parentTraceId); + } + if (rewriteParms && isSiteRootMatch) + { + //set rewrite parameters to take tabid for site root matches + SetRewriteParameters(ref result, newUrl); + } + + //if the parms weren't rewritten by means of a regex, then process them normally + if (!rewriteParms && !isSiteRootMatch) + //can only try other matches if it wasn't a site root match + { + //put those parms on the back of the url as a query string + string cultureCode; + newUrl = RewriteParameters(newUrl, + tabKeyVal, + urlParms, + result, + langParms, + settings, + out cultureCode); + if (cultureCode != null) //set culture code if not already set + { + result.CultureCode = cultureCode; + } + } + //now check if the request involved a page pageAndExtension, (.aspx) and shouldn't have + if (!finished) + { + //944 : don't switch to 301 redirect if action already set to 404 + if ((settings.PageExtensionUsageType == PageExtensionUsageType.Never + || settings.PageExtensionUsageType == PageExtensionUsageType.PageOnly) & + hadExtension) + { + //948 : use new 'no downgrade' method + result.SetActionWithNoDowngrade(ActionType.CheckFor301); + } + else + //866 : redirect back from no extension to extension if it didn't have one + if (settings.PageExtensionUsageType != PageExtensionUsageType.Never && + hadExtension == false) + { + //948 : use new 'no downgrade' method + result.SetActionWithNoDowngrade(ActionType.CheckFor301); + } + } + + if (isSiteRootMatch && !finished) + //when it was a site root match, this must be matched with a custom parameter regex + { + //only finished if the parms were rewritten by means of a regex rewrite + reWritten = rewriteParms; + finished = rewriteParms; + } + else + { + //rewriting done + reWritten = true; + finished = true; + } + } + else + { + //determine the url action and redirect reason from embedded tokens in the url rewrite path + string resultUrl; + RedirectReason reason; + ActionType action; + //add back language parameters if they were there + if (string.IsNullOrEmpty(langParms) == false) + { + string[] parms = langParms.Split('/'); + if (parms.GetUpperBound(0) >= 1) + { + if (parms[0] == "" && parms.GetUpperBound(0) > 1) + { + newUrl += "&" + parms[1] + "=" + parms[2]; + } + else + { + newUrl += "&" + parms[0] + "=" + parms[1]; + } + } + } + RedirectTokens.DetermineRedirectReasonAndAction(newUrl, result, false, settings, + out resultUrl, out reason, + out action); + newUrl = resultUrl; + result.Reason = reason; + result.Action = action; + + if (settings.EnableCustomProviders && ExtensionUrlProviderController.CheckForAlwaysCallProviders(result.PortalId, + result.TabId, + settings, + parentTraceId)) + { + bool newAction; + //newAction tracks whether or not a new 'action' (ie 301, 404, etc) has been requested. + //call the module friendly url providers. Note that the rewriteParms value will be changed if there is a rewrite. + string[] urlParms = (new List()).ToArray(); //empty parm array + if (string.IsNullOrEmpty(langParms) == false) + { + urlParms = langParms.Split('/'); + //split the lang parms into the url Parms + } + bool rewriteParms; + List messages = result.DebugMessages; + newUrl = RewriteParametersFromModuleProvider(newUrl, + tabKeyVal, + urlParms, + isSiteRootMatch, + result, + settings, + out rewriteParms, + out newAction, + ref messages, + parentTraceId); + result.DebugMessages = messages; + } + + //this is a page only, no parameters to deal with + //944 : don't downgrade to redirect if the current action is a 404 (see 948 for new solution to 944) + if (settings.PageExtensionUsageType == PageExtensionUsageType.Never & hadExtension) + { + //potentially a 301 replaced because shouldn't be using page extensions + //948 : check to prevent action downgrade, in case already set to redirect + result.SetActionWithNoDowngrade(ActionType.CheckFor301); + } + else + { + //866 : redirect back from no extension to extension if it didn't have one + if (settings.PageExtensionUsageType != PageExtensionUsageType.Never && + hadExtension == false) + { + result.SetActionWithNoDowngrade(ActionType.CheckFor301); + } + } + //rewriting done + reWritten = true; + finished = true; + } + } + if (finished) + { + break; + } + } + } + } + } + + //next, try forming up a key based on alias1/alias2/tabpath + if (!finished) + { + curAliasPathDepth += 1; + //gone too deep + if ((curAliasPathDepth > maxAliasPathDepth) & (reWritten == false)) + { + // no hope of finding it then + if (triedFixingSubdomain == false && false) + { + //resplit the new url + splitUrl = newUrl.Split(Convert.ToChar("/")); + curAliasPathDepth = minAliasPathDepth; + if (result.RedirectAllowed) + { + result.Action = ActionType.Redirect301; + } + //this should be redirected + triedFixingSubdomain = true; + } + else + { + if (!AdvancedUrlRewriter.ServiceApi.IsMatch(url) && result.RedirectAllowed) + { + //nothing left to try + result.Action = (settings.DeletedTabHandlingType == DeletedTabHandlingType.Do404Error) + ? ActionType.Output404 + : ActionType.Redirect301; + if (result.Action == ActionType.Redirect301) + { + result.Reason = RedirectReason.Deleted_Page; + result.DoRewrite = true; + result.FinalUrl = Globals.AddHTTP(result.PortalAlias.HTTPAlias + "/"); + reWritten = true; + } + break; + } + } + } + } + } + + result.FriendlyRewrite = reWritten; + result.DoRewrite = reWritten; + return newUrl; + } + + internal static void GetUrlWithQuerystring(HttpRequest request, Uri requestUri, out string fullUrl, out string querystring) + { + //699: incorrect encoding in absoluteUri.ToString() + string urlWoutQuery = requestUri.AbsoluteUri; + if (requestUri.Query != "") + { + urlWoutQuery = urlWoutQuery.Replace(requestUri.Query, ""); + // replace the querystring on the reuqest absolute Uri + } + //926 : do not use querystring.toString() because of encoding errors that restul, + //the encoding type is changed from utf-8 to latin-1 + querystring = requestUri.Query; + //get results + fullUrl = urlWoutQuery; + if (fullUrl.EndsWith("/_noext.aspx", StringComparison.InvariantCultureIgnoreCase)) + { + fullUrl = fullUrl.Replace("_noext.aspx", ""); + //replace this marker pattern so it looks as though it isn't there *(leave on trailing slash) + } + if (querystring != "") + { + //set up the querystring and the fullUrl to include the querystring + if (querystring.StartsWith("?") == false) + { + querystring = "?" + querystring; + } + fullUrl += querystring; + } + } + + /// + /// Identifies a request for a physical file on the system + /// + /// The Physical Path propery of the request + /// + /// + /// + /// + /// + /// + /// + /// + /// true if a physical path, false if not + internal static void IdentifyByPhysicalResource(string physicalPath, + string fullUrl, + NameValueCollection queryStringCol, + ref UrlAction result, + bool useFriendlyUrls, + FriendlyUrlSettings settings, + out bool isPhysicalResource, + out bool checkFurtherForRewrite, + Guid parentTraceId) + { + isPhysicalResource = false; + checkFurtherForRewrite = true; + if (File.Exists(physicalPath) && physicalPath.EndsWith("\\_noext.aspx") == false) + { + //resource found + string appPath = Globals.ApplicationMapPath + "\\default.aspx"; + bool isDefaultAspxPath = false; + if (String.Compare(physicalPath, appPath, StringComparison.OrdinalIgnoreCase) != 0) + { + string aliasQs; + if (AdvancedUrlRewriter.CheckForChildPortalRootUrl(fullUrl, result, out aliasQs)) + { + result.DebugMessages.Add("Child Portal Alias Root Identified"); + } + else + { + //it's not the default.aspx path or a child alias request, so we haven't identifed the resource + isPhysicalResource = true; + checkFurtherForRewrite = false; + result.DebugMessages.Add("Resource Identified No Rewrite Used"); + } + } + else + { + isDefaultAspxPath = true; + } + + if (isDefaultAspxPath) //it is the default aspx path + { + //check to see if it is a /default.aspx?key=value url (not just default.aspx, nor a child alias) + if ((queryStringCol != null && queryStringCol.Count > 0)) + { + //when there is a query string supplied, we don't need to rewrite + if (useFriendlyUrls) + { + //using friendly URls, so just nab the Tab id from the querystring + if (queryStringCol["tabId"] != null) + { + if (result.RedirectAllowed) + { + result.Action = ActionType.CheckFor301; + result.Reason = RedirectReason.Unfriendly_Url_TabId; + } + } + } + result.DoRewrite = false; + checkFurtherForRewrite = false; + //no more checking for rewrites, we have our physical file and our query string + //the default.aspx is still a physical resource, but we want to do the rest of the processing + } + else + { + //could be either default.aspx with no querystring, or a child portal alias root + //if 301 redirects are on, then we want to rewrite and replace this Url to include information like language modifiers + //so return false to indicate that the physical resource couldn't be identified + isPhysicalResource = !useFriendlyUrls; + } + } + } + + //mark as physical request + result.IsPhysicalResource = isPhysicalResource; + } + + internal static bool IdentifyByRegEx(string absoluteUri, + string queryString, + string applicationPath, + ref UrlAction result, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + var doRewrite = false; + + var rewriterConfig = RewriterConfiguration.GetConfig(); + + if (rewriterConfig != null) + { + var url = absoluteUri; //get local copy because it gets hacked around + // Remove querystring if exists.. + if (queryString != "") + { + url = url.Replace(queryString, ""); + } + + var rules = RewriterConfiguration.GetConfig().Rules; + if (rules == null) + { + throw new NullReferenceException("DotNetNuke.HttpModules.Config.RewriterRuleCollection is null"); + } + for (var i = 0; i <= rules.Count - 1; i++) + { + //iterate the Config Rules looking for a match + var lookFor = "^" + RewriterUtils.ResolveUrl(applicationPath, rules[i].LookFor) + "$"; + var re = new Regex(lookFor, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (re.IsMatch(url)) + { + var sendTo = rules[i].SendTo; + //get a new rewritePath location + + var rewritePath = RewriterUtils.ResolveUrl(applicationPath, re.Replace(url, sendTo)); //no rewrite path unless we match by regex the intended tab + var sesMatch = re.Match(url); + var sesUrlParams = sesMatch.Groups[2].Value; + //a match by regex means it's probably not a 'friendly' Url, so assume at this stage that this request will end up a 301 + if (settings.UrlFormat == "advanced" && settings.RedirectUnfriendly) + { + result.Action = ActionType.CheckFor301; + } + //if a match is found here, there is the potential for a 'friendlier' url + if ((sesUrlParams.Trim().Length > 0)) + { + sesUrlParams = sesUrlParams.Replace("\\", "/"); + var urlParams = sesUrlParams.Split('/'); + for (var x = 1; x <= urlParams.Length - 1; x++) + { + if (urlParams[x].Trim().Length > 0 && + urlParams[x].ToLower() != Globals.glbDefaultPage.ToLower()) + { + rewritePath = rewritePath + "&" + urlParams[x].Replace(".aspx", "").Trim() + "="; + if ((x < (urlParams.Length - 1))) + { + x += 1; + if ((urlParams[x].Trim() != "")) + { + rewritePath = rewritePath + urlParams[x].Replace(".aspx", ""); + } + } + } + } + } + //add back the query string if it was there + rewritePath = AddQueryStringToRewritePath(rewritePath, queryString); + + //832 : check for leading ~ - if not there, then redirect + if (sendTo.StartsWith("~")) + { + doRewrite = true; + SetRewriteParameters(ref result, rewritePath); + RedirectTokens.SetRedirectReasonAndAction(ref result, settings); + result.DoRewrite = true; + } + else + { + //we'll assume it's a 301 instead of a 302 + result.Action = ActionType.Redirect301; + result.DoRewrite = false; + result.Reason = RedirectReason.SiteUrls_Config_Rule; + result.FinalUrl = rewritePath; + } + break; //exit loop, match found + } + } + } + + return doRewrite; + } + + internal static bool IdentifyByTabPathEx(string absoluteUri, + string queryString, + UrlAction result, + NameValueCollection queryStringCol, + FriendlyUrlSettings settings, + Guid parentTraceId) + { + string scheme = result.Scheme; + if (absoluteUri.ToLower().StartsWith(scheme)) + { + absoluteUri = absoluteUri.Substring(scheme.Length); + } + // Remove QueryString if it exists in the Url value + if ((queryString != "")) + { + absoluteUri = absoluteUri.Replace(queryString, ""); + } + absoluteUri = HttpUtility.UrlDecode(absoluteUri); //decode the incoming request + string rewritePath = GetTabFromDictionary(absoluteUri, queryStringCol, settings, result, parentTraceId); + //put the query string back on the end + rewritePath = AddQueryStringToRewritePath(rewritePath, queryString); + //810 : if a culture code is not specified in the rewrite path + if (result.DoRewrite && settings.ForcePortalDefaultLanguage && result.PortalId >= 0 && + rewritePath.Contains("language=") == false) + { + //add the portal default language to the rewrite path + PortalInfo portal = CacheController.GetPortal(result.PortalId, false); + if (portal != null && !string.IsNullOrEmpty(portal.DefaultLanguage)) + { + AddLanguageCodeToRewritePath(ref rewritePath, portal.DefaultLanguage); + result.CultureCode = portal.DefaultLanguage; + result.DebugMessages.Add("Portal Default Language code " + portal.DefaultLanguage + " added"); + } + } + //set the rewrite path + result.RewritePath = rewritePath; + return result.DoRewrite; + } + + internal static bool IdentifyByTabQueryString(Uri requestUri, NameValueCollection queryStringCol, bool useFriendlyUrls, UrlAction result) + { + const bool doRewrite = false; + string requestedPath = requestUri.LocalPath; + + if (useFriendlyUrls) + { + //using friendly URls, so just nab the Tab id from the querystring + if (result.RedirectAllowed && requestedPath.EndsWith(Globals.glbDefaultPage, StringComparison.OrdinalIgnoreCase) + && (queryStringCol["tabId"] != null)) + { + result.Action = ActionType.CheckFor301; + result.Reason = RedirectReason.Unfriendly_Url_TabId; + } + } + result.DoRewrite = doRewrite; + return doRewrite; + } + + /// + /// Replaces the core IsAdminTab call which was decommissioned for DNN 5.0 + /// + /// + /// The path of the tab //admin//someothername + /// + /// /// Duplicated in UrlMasterController.cs + /// + internal static bool IsAdminTab(int portalId, string tabPath, FriendlyUrlSettings settings) + { + //fallback position - all portals match 'Admin' + const string adminPageName = "Admin"; + //we should be checking that the tab path matches //Admin//pagename or //admin + //in this way we should avoid partial matches (ie //Administrators + if (tabPath.StartsWith("//" + adminPageName + "//", StringComparison.CurrentCultureIgnoreCase) + || String.Compare(tabPath, "//" + adminPageName, StringComparison.OrdinalIgnoreCase) == 0) + { + return true; + } + return false; + } + + /// + /// Determines if the tab is excluded from FriendlyUrl Processing + /// + /// + /// + /// If true, we are checking for rewriting purposes, if false, we are checking for friendly Url Generating. + /// + internal static bool IsExcludedFromFriendlyUrls(TabInfo tab, FriendlyUrlSettings settings, bool rewriting) + { + bool exclude = false; + string tabPath = (tab.TabPath.Replace("//", "/") + ";").ToLower(); + //553 change for dnn 5.0 isAdminTab no longer returns true in any case, so + //check custom admin tab path header + //811: allow for admin tabs to be friendly + if (settings.FriendlyAdminHostUrls == false && IsAdminTab(tab.PortalID, tab.TabPath, settings)) + { + exclude = true; + } + + if (!exclude && settings.UseBaseFriendlyUrls != null) + { + exclude = settings.UseBaseFriendlyUrls.ToLower().Contains(tabPath); + } + + return exclude; + } + + /// + /// Checks for a current parameter belonging to one of the built in 'ctl' values + /// + /// + /// + /// + /// Sets the Action parameter of the Result to 'CheckFor301' if suspected. Actual redirect taken care of by friendly url redirection logic + internal static void RequestRedirectOnBuiltInUrl(string urlParm, string rewritePath, UrlAction result) + { + //on the lookout for items to potentially redirect + if ("terms|privacy|login|register".Contains(urlParm.ToLower())) + { + //likely that this should be redirected, because we don't want ctl/terms, ctl/register, etc + result.Reason = RedirectReason.Built_In_Url; + result.Action = ActionType.CheckFor301; + result.DebugMessages.Add("Built-in Url found: " + rewritePath); + } + } + + /// + /// converts an array of Url path sections into the rewritten string of parameters for the requested Url + /// + /// The current candidate for the rewritten tab path, as found in the tab dictionary + /// The tabKey value which was used to find the current newUrl value + /// The Url path (after the tab name) converted to an array + /// The UrlAction parameter keeping track of the values + /// The raw language/xx-XX values from the requested Url + /// The current friendly url settings + /// an out parameter identifying if a culture code was determined during the process. + /// + internal static string RewriteParameters(string newUrl, + string tabKeyVal, + string[] urlParms, + UrlAction result, + string langParms, + FriendlyUrlSettings settings, + out string cultureCode) + { + cultureCode = null; //culture code is assigned from the langParms value, if it exists + if (urlParms != null) + { + //determine page extension value and usage + string pageExtension = settings.PageExtension; + + var parmString = new StringBuilder(); + bool valueField = false; + bool stripLoneParm = false; + int lastParmToProcessTo = 0; + int upperBound = urlParms.GetUpperBound(0); + + string userIdParm = null; + PortalInfo thisPortal = new PortalController().GetPortal(result.PortalId); + + //check if there is more than one parm, and keep the value of the primary (first) parm + if (thisPortal.UserTabId == result.TabId || thisPortal.UserTabId == -1) + { + //719 : shift to only remove last parm on pages with 'all' match + stripLoneParm = true; //710 : don't put in username into rewritten parameters + userIdParm = "UserId"; + } + + //recheck firstParmLast - just because it is set to be that way in the config doesn't + //mean that the url will come in that way. + //first strip out any language parameters + if (langParms != null) + { + string[] langValues = langParms.TrimStart('/').Split('/'); + if (langValues.GetUpperBound(0) == 1) + { + int pos1 = -1, pos2 = -1; + for (int i = 0; i < urlParms.GetUpperBound(0); i++) + { + //match this part of the urlParms with the language parms + if (urlParms[i] == langValues[0] && urlParms[i + 1] == langValues[1]) + { + pos1 = i; + pos2 = i + 1; + break; + } + } + if (pos1 > -1 && pos2 > -1) + { + //this hacky operation removes the language urls from the array + var temp = new List(urlParms); + temp.RemoveAt(pos2); + temp.RemoveAt(pos1); + urlParms = temp.ToArray(); + upperBound = urlParms.GetUpperBound(0); + //656 : don't allow forced lower case of the culture identifier - always convert the case to aa-AA to match the standard + string cultureId = langValues[1]; + Match cultureMatch = Regex.Match(cultureId, "([a-z]{2})-([a-z]{2})", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + if (cultureMatch.Success) + { + cultureId = cultureMatch.Groups[1].Value + "-" + + cultureMatch.Groups[2].ToString().ToUpper(); + } + //set procedure level culture code, which indicates a language was found in the path + cultureCode = cultureId; + } + } + } + + lastParmToProcessTo = urlParms.GetUpperBound(0); + + //build up the parameters rewrite string by iterating through the key/value pairs in the Url + //and turn them into &key=value pairs. + string keyName = null; + bool skip = false; + bool isUserParm = false; + for (int i = 0; i <= lastParmToProcessTo; i++) + { + string thisParm = urlParms[i]; + //here's the thing - we either take the last one and put it at the start, or just go two-by-two + if (thisParm.ToLower() != Globals.glbDefaultPage.ToLower()) + { + if (thisParm.ToLower() == "tabid") + { + skip = true; + //discovering the tabid in the list of parameters means that + //it was likely a request for an old-style tab url that + //found a retVal due to match in the tab path. + //while this may mean a 301, we definitely don't want to force a 301, + //just investigate it and let the 301 redirect logic work it out + //we also want to skip the next parameter, because it is the tabid value + if (result.Reason != RedirectReason.Custom_Redirect) + { + //only reason not to let this one through and count on the + //friendly url checking code is if it was a custom redirect set up + result.Reason = RedirectReason.Not_Redirected; + result.Action = ActionType.CheckFor301; + //set the value field back to false, because, even if the parameter handling is + //first parm last, this was an old style URl desitned to be redirected. + //and we would expect old-style urls to have the correct parameter order + //note this assumes tabid is the first parm in the list. + valueField = false; + } + } + else if (!skip) + { + bool extReplaced; + string urlParm = CleanExtension(thisParm, pageExtension, out extReplaced); + + if (extReplaced && pageExtension == "") //replacing a .aspx extension + { + result.Action = ActionType.CheckFor301; + } + if (valueField) + { + //this parameter is going into the value half of a &key=value pair + parmString.Append("="); + parmString.Append(urlParm); + valueField = false; + if (isUserParm) + { + int userIdVal; + int.TryParse(urlParm, out userIdVal); + isUserParm = false; + } + //786 : redirect ctl/terms etc + if (keyName != null && keyName.ToLower() == "ctl") + { + RequestRedirectOnBuiltInUrl(urlParm, parmString.ToString(), result); + } + } + else + { + //this parameter is going into the key half of a &key=value pair + keyName = urlParm; + parmString.Append("&"); + parmString.Append(urlParm); + valueField = true; + //if we are looking for a userid parameter in this querystring, check for a match + if (userIdParm != null) + { + if (String.Compare(keyName, userIdParm, StringComparison.OrdinalIgnoreCase) == 0) + { + isUserParm = true; + } + } + } + } + else if (skip) + { + skip = false; + } + } + } + + //add back language parameters if they were found + AddLanguageCodeToRewritePath(ref newUrl, cultureCode); + //add on the parameter string + newUrl += parmString.ToString(); + + if (stripLoneParm) + { + newUrl = Regex.Replace(newUrl, @"&[^=]+(?:&|$)", "&"); + if (newUrl.EndsWith("&")) + { + newUrl = newUrl.Substring(0, newUrl.Length - 1); + } + } + //chop the last char off if it is an empty parameter + if ((newUrl[newUrl.Length - 1] == '&')) + { + newUrl = newUrl.Substring(0, newUrl.Length - 1); + } + } + return newUrl; + } + + /// + /// Scans the collection of Rewrite Parameter rules, and rewrites the parameters if a match is found + /// + /// + /// + /// + /// + /// + /// + /// + /// The new Url with the parameters rewritten onto the end of hte old Url + internal static string RewriteParameters(string newUrl, + string tabKeyVal, + string[] urlParms, + bool isSiteRoot, + UrlAction urlAction, + out bool rewriteParms, + Guid parentTraceId) + { + string result = newUrl; + rewriteParms = false; + //get the actions from the cache + var messages = new List(); + Dictionary> rewriteActions = CacheController.GetParameterRewrites(urlAction.PortalId, + ref messages, parentTraceId); + if (messages == null) + { + messages = new List(); + } + try + { + if (rewriteActions != null && rewriteActions.Count > 0) + { + SharedList tabRewrites = null; + var tabIdRegex = new Regex(@"(?:\?|\&)tabid\=(?[\d]+)", + RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + Match tabMatch = tabIdRegex.Match(newUrl); + if (tabMatch.Success) + { + string rawTabId = tabMatch.Groups["tabid"].Value; + int tabId; + if (Int32.TryParse(rawTabId, out tabId)) + { + if (rewriteActions.ContainsKey(tabId)) + { + //find the right set of rewrite actions for this tab + tabRewrites = rewriteActions[tabId]; + } + } + } + + if (rewriteActions.ContainsKey(AllTabsRewrite)) //-1 means 'all tabs' - rewriting across all tabs + { + //initialise to empty collection if there are no specific tab rewrites + if (tabRewrites == null) + { + tabRewrites = new SharedList(); + } + //add in the all rewrites + SharedList allRewrites = rewriteActions[AllTabsRewrite]; + foreach (ParameterRewriteAction rewrite in allRewrites) + { + tabRewrites.Add(rewrite); //add the 'all' range to the tab range + } + } + if (isSiteRoot && rewriteActions.ContainsKey(SiteRootRewrite)) + { + //initialise to empty collection if there are no specific tab rewrites + if (tabRewrites == null) + { + tabRewrites = new SharedList(); + } + SharedList siteRootRewrites = rewriteActions[SiteRootRewrite]; + foreach (ParameterRewriteAction rewrite in siteRootRewrites) + { + tabRewrites.Add(rewrite); //add the site root rewrites to the collection + } + } + //get the parms as a string + string parms = string.Join("/", urlParms); + + if (tabRewrites != null && tabRewrites.Count > 0) + { + //process each one until a match is found + foreach (ParameterRewriteAction rewrite in tabRewrites) + { + string lookFor = rewrite.LookFor; + //debugInfo += " lookFor:" + lookFor; + var parmRegex = new Regex(lookFor, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + //check the match, if a match found, do the replacement + if (parmRegex.IsMatch(parms)) + { + //rewrite the parameter + string sendTo = rewrite.RewriteTo; + string parmsOriginal = parms; + //replace hte parameter with the rewrite string + parms = parmRegex.Replace(parms, sendTo); + messages.Add(rewrite.Name + " rewrite match (" + parmsOriginal + "), replaced to : " + parms); + //makes sure the newUrl has got a trailing ampersand or a ? to start the query string + if (newUrl.Contains("?")) + { + if (newUrl.EndsWith("&") == false) + { + newUrl += "&"; + } + } + else //need to start the querystring off (592: allow for custom rewrites on site root) + { + newUrl += "?"; + } + + //makes sure the new parms string hasn't got a starting ampersand + if (parms.StartsWith("&")) + { + parms = parms.Substring(1); + } + //parameters are added to the back fo the newUrl + newUrl += parms; + //it's a rewrite, all right + rewriteParms = true; + result = newUrl; + urlAction.CustomParmRewrite = true; + break; + } + messages.Add(rewrite.Name + " rewrite not matched (" + parms + ")"); + } + } + } + } + catch (Exception ex) + { + Services.Exceptions.Exceptions.LogException(ex); + string error = "Exception: " + ex.Message + "\n" + ex.StackTrace; + messages.Add(error); + } + finally + { + //post messages to debug output + urlAction.DebugMessages.AddRange(messages); + } + + return result; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/RewriterUtils.cs b/DNN Platform/Library/Entities/Urls/RewriterUtils.cs new file mode 100644 index 00000000000..5db00e6fb63 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/RewriterUtils.cs @@ -0,0 +1,120 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Controllers; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class RewriterUtils + { + internal static void RewriteUrl(HttpContext context, string sendToUrl) + { + //first strip the querystring, if any + var queryString = string.Empty; + string sendToUrlLessQString = sendToUrl; + if ((sendToUrl.IndexOf("?", StringComparison.Ordinal) > 0)) + { + sendToUrlLessQString = sendToUrl.Substring(0, sendToUrl.IndexOf("?", StringComparison.Ordinal)); + queryString = sendToUrl.Substring(sendToUrl.IndexOf("?", StringComparison.Ordinal) + 1); + } + + //rewrite the path.. + context.RewritePath(sendToUrlLessQString, string.Empty, queryString); + //NOTE! The above RewritePath() overload is only supported in the .NET Framework 1.1 + //If you are using .NET Framework 1.0, use the below form instead: + //context.RewritePath(sendToUrl); + } + + internal static string ResolveUrl(string appPath, string url) + { + //String is Empty, just return Url + if (String.IsNullOrEmpty(url)) + { + return url; + } + + //String does not contain a ~, so just return Url + if ((url.StartsWith("~") == false)) + { + return url; + } + + //There is just the ~ in the Url, return the appPath + if ((url.Length == 1)) + { + return appPath; + } + var seperatorChar = url.ToCharArray()[1]; + if (seperatorChar == '/' || seperatorChar == '\\') + { + //Url looks like ~/ or ~\ + if ((appPath.Length > 1)) + { + return appPath + "/" + url.Substring(2); + } + return "/" + url.Substring(2); + } + //Url look like ~something + if ((appPath.Length > 1)) + { + return appPath + "/" + url.Substring(1); + } + return appPath + url.Substring(1); + } + + private static readonly Regex ServicesFrameworkRegex = new Regex("DesktopModules/[^/]+/API/"); + + static internal bool OmitFromRewriteProcessing(string localPath) + { + var omitSettings = String.Empty; + if (Globals.Status == Globals.UpgradeStatus.None) + { + omitSettings = HostController.Instance.GetString("OmitFromRewriteProcessing"); + } + + if (string.IsNullOrEmpty(omitSettings)) { + omitSettings = "scriptresource.axd|webresource.axd|gif|ico|jpg|jpeg|png|css|js"; + } + omitSettings = omitSettings.ToLower(); + localPath = localPath.ToLower(); + + var omissions = omitSettings.Split(new[] { '|' }); + + bool shouldOmit = omissions.Any(x => localPath.EndsWith(x)); + + if(!shouldOmit) + { + shouldOmit = ServicesFrameworkRegex.IsMatch(localPath); + } + + return shouldOmit; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/SaveUrlDto.cs b/DNN Platform/Library/Entities/Urls/SaveUrlDto.cs new file mode 100644 index 00000000000..5d83029b2c1 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/SaveUrlDto.cs @@ -0,0 +1,17 @@ +using System; + +namespace DotNetNuke.Entities.Urls +{ + public class SaveUrlDto + { + public int Id { get; set; } + public int SiteAliasKey { get; set; } + public string Path { get; set; } + public string QueryString { get; set; } + public int LocaleKey { get; set; } + public int StatusCodeKey { get; set; } + public int SiteAliasUsage { get; set; } + public bool IsSystem { get; set; } + } + +} diff --git a/DNN Platform/Library/Entities/Urls/StateBoolean.cs b/DNN Platform/Library/Entities/Urls/StateBoolean.cs new file mode 100644 index 00000000000..fcb7c727577 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/StateBoolean.cs @@ -0,0 +1,32 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum StateBoolean + { + NotSet = -1, + False = 0, + True = 1 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/StringLengthComparer.cs b/DNN Platform/Library/Entities/Urls/StringLengthComparer.cs new file mode 100644 index 00000000000..96555fcf0a6 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/StringLengthComparer.cs @@ -0,0 +1,68 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System.Collections.Generic; + +#endregion + +/* This code file contains helper classes used for Url Rewriting / Friendly Url generation */ + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The StringLengthComparer class is a comparer override used for sorting portal aliases by length + /// + internal class StringLengthComparer : Comparer + { + public override int Compare(string x, string y) + { + if (x == null && y == null) + { + return 0; + } + if (x == null) + { + return -1; + } + if (y == null) + { + return 1; + } + if (x.Length < y.Length) + { + return -1; + } + if (x.Length > y.Length) + { + return 1; + } + if (x.Length == y.Length) + { + return 0; + } + return -1; //should never reach here + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/TabIndexController.cs b/DNN Platform/Library/Entities/Urls/TabIndexController.cs new file mode 100644 index 00000000000..e08ba316a2a --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/TabIndexController.cs @@ -0,0 +1,1669 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal static class TabIndexController + { + private static readonly object tabPathDictBuildLock = new object(); + + #region Private Methods + + private static void AddCustomRedirectsToDictionary(SharedDictionary tabIndex, + Dictionary dupCheck, + string httpAlias, + TabInfo tab, + FriendlyUrlSettings settings, + FriendlyUrlOptions options, + ref string rewritePath, + out int tabPathDepth, + ref List customHttpAliasesUsed, + bool isDeleted, + Guid parentTraceId) + { + tabPathDepth = 1; + var duplicateHandlingPreference = UrlEnums.TabKeyPreference.TabRedirected; + bool checkForDupUrls = settings.CheckForDuplicateUrls; + //697 : custom url rewrites with large number of path depths fail because of incorrect path depth calculation + int maxTabPathDepth = 1; + string newRewritePath = rewritePath; + string aliasCulture = null; + //get the culture for this alias + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(tab.PortalID).ToList(); + + if (primaryAliases.Count > 0) + { + aliasCulture = primaryAliases.GetCultureByPortalIdAndAlias(tab.PortalID, httpAlias); + } + foreach (var redirect in tab.TabUrls) + { + //allow for additional qs parameters + if (!String.IsNullOrEmpty(redirect.QueryString)) + { + rewritePath += (redirect.QueryString.StartsWith("&")) ? redirect.QueryString : "&" + redirect.QueryString; + } + + string redirectTabPath = redirect.Url; + string redirectedRewritePath = rewritePath; + + //770 : allow for custom portal aliases + string redirectAlias = httpAlias; + if (redirect.PortalAliasId > 0) + { + //has a custom portal alias + var pac = new PortalAliasController(); + PortalAliasInfo customAlias = pac.GetPortalAliasByPortalAliasID(redirect.PortalAliasId); + if (customAlias != null) + { + //this will be used to add the Url to the dictionary + redirectAlias = customAlias.HTTPAlias; + //add to the list of custom aliases used by the portal + if (customHttpAliasesUsed == null) + { + customHttpAliasesUsed = new List(); + } + if (!customHttpAliasesUsed.Contains(redirectAlias)) + { + customHttpAliasesUsed.Add(redirectAlias); + } + } + } + //set the redirect status using the httpStatus + switch (redirect.HttpStatus) + { + case "301": + redirectedRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Redirect301, + RedirectReason.Custom_Redirect); + break; + case "302": + redirectedRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Redirect302, + RedirectReason.Custom_Redirect); + break; + case "404": + redirectedRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Output404, + RedirectReason.Custom_Redirect); + break; + case "200": + //when there is a 200, then replace the 'standard' path + newRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(newRewritePath, + ActionType.CheckFor301, + RedirectReason.Custom_Redirect); + //672 : replacement urls have preference over all redirects, deleted tabs and standard urls + duplicateHandlingPreference = UrlEnums.TabKeyPreference.TabOK; + break; + } + //check the culture of the redirect to see if it either doesn't match the alias or needs to specify + //the language when requested + if (redirect.CultureCode != null) + { + if (redirect.CultureCode != "" && redirect.CultureCode != "Default") + { + //806 : specify duplicates where the alias culture doesn't match the redirect culture + //so that redirect to the best match between alias culture and redirect culture + //compare the supplied alias culture with the redirect culture + //856 : if alias culture == "" and a custom 301 redirect then redirects are forced + if (!string.IsNullOrEmpty(aliasCulture) && aliasCulture != redirect.CultureCode) + { + //the culture code and the specific culture alias don't match + //set 301 check status and set to delete if a duplicate is found + redirectedRewritePath = RedirectTokens.AddRedirectReasonToRewritePath( + redirectedRewritePath, + ActionType.CheckFor301, + RedirectReason.Custom_Redirect); + newRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(newRewritePath, + ActionType.CheckFor301, + RedirectReason.Custom_Redirect); + duplicateHandlingPreference = UrlEnums.TabKeyPreference.TabRedirected; + } + //add on the culture code for the redirect, so that the rewrite silently sets the culture for the page + RewriteController.AddLanguageCodeToRewritePath(ref redirectedRewritePath, redirect.CultureCode); + } + } + //now add the custom redirect to the tab dictionary + if (String.Compare(httpAlias, redirectAlias, StringComparison.OrdinalIgnoreCase) == 0) + { + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + redirectTabPath, + redirectedRewritePath, + tab.TabID, + duplicateHandlingPreference, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + } + else + { + //770 : there is a specific alias for this tab + //if not a redirect already, make it a redirect for the wrong (original) rewrite path + string wrongAliasRedirectedRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(redirectedRewritePath, + ActionType.Redirect301, + RedirectReason.Custom_Tab_Alias); + //add in the entry with the specific redirectAlias + if (redirectTabPath == "") + { + //when adding a blank custom Url, also add in a standard tab path url, because any url that also includes querystring data will use the standard tab path + string tabPath = GetTabPath(tab, options, parentTraceId); + string stdDictRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.CheckFor301, + RedirectReason.Custom_Tab_Alias); + AddToTabDict(tabIndex, + dupCheck, + redirectAlias, + tabPath, + stdDictRewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabOK, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + //then add in the portal alias with no tabpath (ie like a site root url) + AddToTabDict(tabIndex, + dupCheck, + redirectAlias, + redirectTabPath, + redirectedRewritePath, + tab.TabID, + duplicateHandlingPreference, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + //838 : disabled tabs with custom aliases - still load the settings page without redirect + //594 : disabled / external url pages cannot navigate to settings page + if (tab.DisableLink || !string.IsNullOrEmpty(tab.Url)) + { + string settingsUrl = tabPath + "/ctl/Tab"; + string settingsRewritePath = CreateRewritePath(tab.TabID, redirect.CultureCode, "ctl=Tab"); + //no redirect on the ctl/Tab url + //add in the ctl/tab Url for the custom alias, with no redirect so that the page settings can be loaded + AddToTabDict(tabIndex, + dupCheck, + redirectAlias, + settingsUrl, + settingsRewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + } + else + { + //add in custom entry with different alias + AddToTabDict(tabIndex, + dupCheck, + redirectAlias, + redirectTabPath, + redirectedRewritePath, + tab.TabID, + duplicateHandlingPreference, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + //add in the entry with the original alias, plus an instruction to redirect if it's used + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + redirectTabPath, + wrongAliasRedirectedRewritePath, + tab.TabID, + duplicateHandlingPreference, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + } + } + if (tabPathDepth > maxTabPathDepth) + { + maxTabPathDepth = tabPathDepth; + } + } + //return the highest tabpath depth found + tabPathDepth = maxTabPathDepth; + //return any changes to the rewritePath + rewritePath = newRewritePath; + } + + + private static void AddInternalAliases(FriendlyUrlSettings settings, List usingHttpAliases) + { + if (settings.InternalAliasList != null && settings.InternalAliasList.Count > 0) + { + foreach (InternalAlias ia in settings.InternalAliasList) + { + if (usingHttpAliases.Contains(ia.HttpAlias) == false) + { + usingHttpAliases.Add(ia.HttpAlias); + } + } + } + } + + private static void AddPermanentRedirectToDictionary(SharedDictionary tabIndex, + Dictionary dupCheck, + string httpAlias, + TabInfo tab, + string tabPath, + ref string rewritePath, + ref int tabPathDepth, + bool checkForDupUrls, + bool isDeleted) + { + //because we have to catch all versions of this in the dictionary, then we have to add the 'base' url + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tab.TabPath + "/tabid/" + tab.TabID + "/default", + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + //and put in the name-less one as well, just in case a prior version of the site was runnign without the tabnames (urlformat=sefriendly) + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "/tabid/" + tab.TabID + "/default", + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + //finally, put one in for the ctl/tab combination, so that you can actually get to the page settings + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath.Replace("//", "/") + "/ctl/Tab", + CreateRewritePath(tab.TabID, "", "ctl=Tab"), + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + checkForDupUrls, + isDeleted); + } + + private static void AddSiteRootRedirects(PathSizes pathSizes, + SharedDictionary tabIndex, + IEnumerable chosenAliases, + bool hasSiteRootRedirect, + Dictionary dupCheck, + ICollection usingHttpAliases) + { + foreach (PortalAliasInfo alias in chosenAliases) //and that is once per portal alias per portal + { + string httpAlias = alias.HTTPAlias; + + //check to see if there is a parameter rewrite rule that allows for parameters on the site root + if (hasSiteRootRedirect) + { + int tempPathDepth = 0; + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "*", + "", + -1, + UrlEnums.TabKeyPreference.TabOK, + ref tempPathDepth, + false, + false); + } + + pathSizes.SetAliasDepth(httpAlias); + + //keep track of the http Aliases, this will be used to feed into the tab dictionary (ie, one alias per tab) + usingHttpAliases.Add(httpAlias.ToLowerInvariant()); + } + } + + private static void AddStandardPagesToDict(SharedDictionary tabIndex, + Dictionary dupCheck, + string httpAlias, + int portalId, + string cultureCode) + { + int tabDepth = 0; //we ignore tab depth as it is only one for these in-built urls + //850 : add in the culture code to the redirect if supplied + string portalRewritePath = "?PortalId=" + portalId.ToString(); + string cultureRewritePath = ""; + if (!string.IsNullOrEmpty(cultureCode)) + { + cultureRewritePath += "&language=" + cultureCode; + } + //hard coded page paths - using 'tabDeleted' in case there is a clash with an existing page (ie, someone has created a page that takes place of the standard page, created page has preference) + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "login", + portalRewritePath + "&ctl=Login" + cultureRewritePath, + -1, + UrlEnums.TabKeyPreference.TabDeleted, + ref tabDepth, + false, + false); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "register", + portalRewritePath + "&ctl=Register" + cultureRewritePath, + -1, + UrlEnums.TabKeyPreference.TabDeleted, + ref tabDepth, + false, + false); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "terms", + portalRewritePath + "&ctl=Terms" + cultureRewritePath, + -1, + UrlEnums.TabKeyPreference.TabDeleted, + ref tabDepth, + false, + false); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "privacy", + portalRewritePath + "&ctl=Privacy" + cultureRewritePath, + -1, + UrlEnums.TabKeyPreference.TabDeleted, + ref tabDepth, + false, + false); + } + + private static int AddTabToTabDict(SharedDictionary tabIndex, + Dictionary dupCheck, + string httpAlias, + string aliasCulture, + string customHttpAlias, + PortalInfo thisPortal, + string tabPath, + ref List customAliasesUsed, + TabInfo tab, + FriendlyUrlSettings settings, + FriendlyUrlOptions options, + int homeTabId, + ref Hashtable homePageSkins, + Guid parentTraceId) + { + string rewritePath = ""; + int tabPathDepth = 0; + bool customAliasUsedAndNotCurrent = !String.IsNullOrEmpty(customHttpAlias) && customHttpAlias != httpAlias; + + //592 : check the permanent redirect value + //736 : 5.5 changes : track tab culture code + string cultureCode = tab.CultureCode; + if (String.IsNullOrEmpty(cultureCode)) + { + cultureCode = aliasCulture; + } + bool permanentRedirect = tab.PermanentRedirect; + //determine the rewrite parameter + //for deleted, expired or pages not enabled yet, direct to the home page if the setting is enabled + //534 : tab is disabled, mark as deleted (don't want to cause duplicate tab warnings) + bool isDeleted = (tab.IsDeleted || tab.DisableLink || + (tab.EndDate < DateTime.Now && tab.EndDate > DateTime.MinValue) || + (tab.StartDate > DateTime.Now && tab.StartDate > DateTime.MinValue)); + if (isDeleted) + // don't care what setting is, redirect code will decide whether to redirect or 404 - just mark as page deleted && + // settings.DeletedTabHandlingValue == DeletedTabHandlingTypes.Do301RedirectToPortalHome) + { + //777: force 404 result for all deleted pages instead of relying on 'not found' + //838 : separate handling for disabled pages + ActionType action = settings.DeletedTabHandlingType == DeletedTabHandlingType.Do404Error + ? ActionType.Output404 + : ActionType.Redirect301; + rewritePath = tab.DisableLink + ? CreateRewritePath(homeTabId, cultureCode, action, RedirectReason.Disabled_Page) + : CreateRewritePath(homeTabId, cultureCode, action, RedirectReason.Deleted_Page); + } + else + { + //for all other pages, rewrite to the correct tabId for that page + //592 : new permanentRedirect value + if (permanentRedirect) + { + rewritePath = CreateRewritePath(tab.TabID, + cultureCode, + ActionType.Redirect301, + RedirectReason.Tab_Permanent_Redirect); + } + else + { + //852 : skin per alias at tab level - if specified + if (tab.AliasSkins != null && tab.AliasSkins.ContainsAlias(httpAlias)) + { + TabAliasSkinInfo tas = tab.AliasSkins.FindByHttpAlias(httpAlias); + if (tas != null) + { + string skinSrc = tas.SkinSrc; + if (!string.IsNullOrEmpty(skinSrc)) + { + //add skin src into rewrite path + rewritePath = CreateRewritePath(tab.TabID, cultureCode, "skinSrc=" + skinSrc); + } + + //now add to the home page skin hashtable if it's the home page. + if (homeTabId == tab.TabID) + { + string key = httpAlias + "::" + cultureCode; + string key2 = httpAlias; + if (homePageSkins.ContainsKey(key) == false) + { + homePageSkins.Add(key, skinSrc); + } + if (homePageSkins.ContainsKey(key2) == false) + { + homePageSkins.Add(key2, skinSrc); + } + } + } + } + else + { + rewritePath = CreateRewritePath(tab.TabID, cultureCode); + } + } + + if (thisPortal != null && (thisPortal.UserTabId == tab.TabID || thisPortal.UserTabId == tab.ParentId || thisPortal.UserTabId == -1)) + { + //user profile action specified. If tabid match for this tab, add a do301 check because we want to make + //sure that the trimmed Url is used when appropriate + rewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.CheckFor301, + RedirectReason.User_Profile_Url); + } + } + + if (tabPath.Replace("//", "/") != tab.TabPath.Replace("//", "/")) + { + //when the generated tab path is different to the standard tab path, character substituion has happened + //this entry is going to have space substitution in it, so it is added into the dictionary with a delete notification and a 301 replaced + //this entry is the 'original' (spaces removed) version ie mypage + string substituteRewritePath = rewritePath; + if (!isDeleted) + //if it is deleted, we don't care if the spaces were replaced, or anything else, just take care in deleted handling + { + string replaceSpaceWith = String.Empty; + if (settings.ReplaceSpaceWith != FriendlyUrlSettings.ReplaceSpaceWithNothing) + { + replaceSpaceWith = settings.ReplaceSpaceWith; + } + substituteRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(substituteRewritePath, + ActionType.Redirect301, + tabPath.Contains(replaceSpaceWith) + ? RedirectReason.Spaces_Replaced + : RedirectReason.Custom_Redirect); + } + //the preference variable determines what to do if a duplicate tab is found already in the dictionary + var preference = UrlEnums.TabKeyPreference.TabRedirected; + if (isDeleted) + { + // if the tab is actually deleted, downgrade the preference to 'deleted'. Any other tabs with the same path that + // are redirected but not deleted should take preference + preference = UrlEnums.TabKeyPreference.TabDeleted; + } + //Note ; if anything else is wrong with this url, (ie, wrong alias) then that will be corrected in a redirect + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tab.TabPath, + substituteRewritePath, + tab.TabID, + preference, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + + //check for permanent redirects as specified in the core dnn permanent redirect property + if (permanentRedirect) + { + AddPermanentRedirectToDictionary(tabIndex, + dupCheck, + httpAlias, + tab, + tabPath, + ref rewritePath, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + + //594 : disabled / external url pages cannot navigate to settings page + if (tab.DisableLink || !string.IsNullOrEmpty(tab.Url)) + { + string settingsUrl = tabPath.Replace("//", "/") + "/ctl/Tab"; + string settingsRewritePath = CreateRewritePath(tab.TabID, "", "ctl=tab"); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + settingsUrl, + settingsRewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + + //777: every tab is added to the dictionary, including those that are deleted + + //inspect the optional tab redirects and add them as well, keeping track if any are '200' status, meaning the standard Url will be 301, if replaced unfriendly is switched on + //589 : tab with custom 200 redirects not changing base url to 301 statusa + AddCustomRedirectsToDictionary(tabIndex, + dupCheck, + httpAlias, + tab, + settings, + options, + ref rewritePath, + out tabPathDepth, + ref customAliasesUsed, + isDeleted, + parentTraceId); + + //if auto ascii conversion is on, do that as well + if (settings.AutoAsciiConvert) + { + bool replacedDiacritic; + string asciiTabPath = TabPathHelper.ReplaceDiacritics(tabPath, out replacedDiacritic); + if (replacedDiacritic) + { + ActionType existingAction; + RedirectTokens.GetActionFromRewritePath(rewritePath, out existingAction); + if (settings.RedirectUnfriendly && existingAction != ActionType.Redirect301) + { + //add in a tab path, with 301, for the version with the diacritics in + string diacriticRewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Redirect301, + RedirectReason.Diacritic_Characters); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + diacriticRewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabOK, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + else + { + //add in the standard version so that the page responds to both the diacritic version + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabOK, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + } + tabPath = asciiTabPath; //switch tabpath to new, ascii-converted version for rest of processing + } + + //add the 'standard' Url in + if (tab.TabID == homeTabId && settings.RedirectUnfriendly) + { + //home page shoudl be redirected back to the site root + //899: check for redirect on home page + rewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.CheckFor301, + RedirectReason.Site_Root_Home); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabOK, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + else + { + if (customAliasUsedAndNotCurrent && settings.RedirectUnfriendly) + { + //add in the standard page, but it's a redirect to the customAlias + rewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Redirect301, + RedirectReason.Custom_Tab_Alias); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + else + { + if (customAliasUsedAndNotCurrent && settings.RedirectUnfriendly) + { + //add in the standard page, but it's a redirect to the customAlias + rewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, + ActionType.Redirect301, + RedirectReason.Custom_Tab_Alias); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + else + { + //add in the standard page to the dictionary + //931 : don't replace existing custom url if this is a redirect or a check for redirect + ActionType action; + var dupCheckPreference = UrlEnums.TabKeyPreference.TabOK; + RedirectTokens.GetActionFromRewritePath(rewritePath, out action); + if (action == ActionType.CheckFor301 || action == ActionType.Redirect301 || action == ActionType.Redirect302) + { + dupCheckPreference = UrlEnums.TabKeyPreference.TabRedirected; + } + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tabPath, + rewritePath, + tab.TabID, + dupCheckPreference, + ref tabPathDepth, + settings.CheckForDuplicateUrls, + isDeleted); + } + } + } + return tabPathDepth; + } + + private static void AddToTabDict(SharedDictionary tabIndex, + Dictionary dupCheckDict, + string httpAlias, + string tabPath, + string rewrittenPath, + int tabId, + UrlEnums.TabKeyPreference keyDupAction, + ref int tabPathDepth, + bool checkForDupUrls, + bool isDeleted) + { + //remove leading '/' and convert to lower for all keys + string tabPathSimple = tabPath.Replace("//", "/").ToLower(); + //the tabpath depth is only set if it's higher than the running highest tab path depth + int thisTabPathDepth = tabPathSimple.Length - tabPathSimple.Replace("/", "").Length; + if (thisTabPathDepth > tabPathDepth) + { + tabPathDepth = thisTabPathDepth; + } + if ((tabPathSimple.Length > 0 && tabPathSimple[0] == '/')) + { + tabPathSimple = tabPathSimple.Substring(1); + } + + //Contruct the tab key for the dictionary. Using :: allows for separation of portal alias and tab path. + string tabKey = (httpAlias + "::" + tabPathSimple).ToLower(); + + //construct the duplicate key check + string dupKey = (httpAlias + "/" + tabPathSimple).ToLower(); + if (dupKey[dupKey.Length - 1] != '/') + { + dupKey += "/"; + } + + //now make sure there is NEVER a duplicate key exception by testing for existence first + using (tabIndex.GetWriteLock()) + { + if (tabIndex.ContainsKey(tabKey)) + { + //it's possible for a tab to be deleted and the tab path repeated. + //the dictionary must be checked to ascertain whether the existing tab + //should be replaced or not. If the action is 'TabOK' it means + //replace the entry regardless. If the action is 'TabRedirected' it means + //replace the existing dictionary ONLY if the existing dictionary entry is a + //deleted tab. + bool replaceTab = (keyDupAction == UrlEnums.TabKeyPreference.TabOK); //default, replace the tab + if (replaceTab == false) + { + //ok, the tab to be added is either a redirected or deleted tab + //get the existing entry + //775 : don't assume that the duplicate check dictionary has the key + if (dupCheckDict.ContainsKey(dupKey)) + { + DupKeyCheck foundTab = dupCheckDict[dupKey]; + //a redirected tab will replace a deleted tab + if (foundTab.IsDeleted && keyDupAction == UrlEnums.TabKeyPreference.TabRedirected) + { + replaceTab = true; + } + if (foundTab.TabIdOriginal == "-1") + { + replaceTab = true; + } + } + } + if (replaceTab && !isDeleted) //don't replace if the incoming tab is deleted + { + //remove the previous one + tabIndex.Remove(tabKey); + //add the new one + tabIndex.Add(tabKey, Globals.glbDefaultPage + rewrittenPath); + } + } + else + { + //just add the tabkey into the dictionary + tabIndex.Add(tabKey, Globals.glbDefaultPage + rewrittenPath); + } + } + + //checking for duplicates means throwing an exception when one is found, but this is just logged to the event log + if (dupCheckDict.ContainsKey(dupKey)) + { + DupKeyCheck foundTAb = dupCheckDict[dupKey]; + if ((foundTAb.IsDeleted == false && isDeleted == false) //found is not deleted, this tab is not deleted + && keyDupAction == UrlEnums.TabKeyPreference.TabOK + && foundTAb.TabIdOriginal != "-1") + //-1 tabs are login, register, privacy etc + { + //check whether to log for this or not + if (checkForDupUrls && foundTAb.TabIdOriginal != tabId.ToString()) + //dont' show message for where same tab is being added twice) + { + //there is a naming conflict where this alias/tab path could be mistaken + int tabIdOriginal; + string tab1Name = "", tab2Name = ""; + if (int.TryParse(foundTAb.TabIdOriginal, out tabIdOriginal)) + { + Dictionary portalDic = PortalController.GetPortalDictionary(); + int portalId = -1; + if (portalDic != null && portalDic.ContainsKey(tabId)) + { + portalId = portalDic[tabId]; + } + + var tc = new TabController(); + TabInfo tab1 = tc.GetTab(tabIdOriginal, portalId, false); + TabInfo tab2 = tc.GetTab(tabId, portalId, false); + if (tab1 != null) + { + tab1Name = tab1.TabName + " [" + tab1.TabPath + "]"; + } + if (tab2 != null) + { + tab2Name = tab2.TabName + " [" + tab2.TabPath + "]"; + } + } + + string msg = "Page naming conflict. Url of (" + foundTAb.TabPath + + ") resolves to two separate pages (" + tab1Name + " [tabid = " + + foundTAb.TabIdOriginal + "], " + tab2Name + " [tabid = " + tabId.ToString() + + "]). Only the second page will be shown for the url."; + const string msg2 = "PLEASE NOTE : this is an information message only, this message does not affect site operations in any way."; + + //771 : change to admin alert instead of exception + var elc = new EventLogController(); + //log a host alert + var logValue = new LogInfo { LogTypeKey = "HOST_ALERT" }; + logValue.AddProperty("Advanced Friendly URL Provider Duplicate URL Warning", "Page Naming Conflict"); + logValue.AddProperty("Duplicate Page Details", msg); + logValue.AddProperty("Warning Information", msg2); + logValue.AddProperty("Suggested Action", "Rename one or both of the pages to ensure a unique URL"); + logValue.AddProperty("Hide this message", "To stop this message from appearing in the log, uncheck the option for 'Produce an Exception in the Site Log if two pages have the same name/path?' in the Advanced Url Rewriting settings."); + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + elc.AddLog(logValue); + } + } + else + { + dupCheckDict.Remove(dupKey); + //add this tab to the duplicate key dictionary + dupCheckDict.Add(dupKey, new DupKeyCheck(dupKey, tabId.ToString(), dupKey, isDeleted)); + } + } + else + { + //add this tab to the duplicate key dictionary - the dup key check dict is always maintained + //regardless of whether checking is employed or not + dupCheckDict.Add(dupKey, new DupKeyCheck(dupKey, tabId.ToString(), dupKey, isDeleted)); + } + } + + private static OrderedDictionary BuildPortalAliasesRegexDictionary() + { + IDictionary aliases = TestablePortalAliasController.Instance.GetPortalAliases(); + //create a new OrderedDictionary. We use this because we + //want to key by the correct regex pattern and return the + //portalAlias that matches, and we want to preserve the + //order of the items, such that the item with the most path separators (/) + //is at the front of the list. + var regexList = new OrderedDictionary(aliases.Count); + //this regex pattern, when formatted with the httpAlias, will match a request + //for this portalAlias + const string aliasRegexPattern = @"(?:^(?http[s]{0,1}://){0,1})(?:(?_ALIAS_)(?$|\?[\w]*|/[\w]*))"; + var pathLengths = new List(); + foreach (string aliasKey in aliases.Keys) + { + PortalAliasInfo alias = aliases[aliasKey]; + //regex escape the portal alias for inclusion into a regex pattern + string plainAlias = alias.HTTPAlias; + string escapedAlias = Regex.Escape(plainAlias); + var aliasesToAdd = new List { escapedAlias }; + //check for existence of www. version of domain, if it doesn't have a www. + if (plainAlias.ToLower().StartsWith("www.")) + { + if (plainAlias.Length > 4) + { + string noWWWVersion = plainAlias.Substring(4); + if (!aliases.ContainsKey(noWWWVersion)) + { + //there is no no-www version of the alias + aliasesToAdd.Add(Regex.Escape(noWWWVersion)); + } + } + } + else + { + string wwwVersion = "www." + plainAlias; + if (!aliases.ContainsKey(wwwVersion)) + { + aliasesToAdd.Add(Regex.Escape(wwwVersion)); + } + } + int count = 0; + foreach (string aliasToAdd in aliasesToAdd) + { + //set flag on object to know whether to redirect or not + count++; + var aliasObject = new PortalAliasInfo(alias) { Redirect = count != 1 }; + + //format up the regex pattern by replacing the alias portion with the portal alias name + string regexPattern = aliasRegexPattern.Replace("_ALIAS_", aliasToAdd); + //work out how many path separators there are in the portalAlias (ie myalias/mychild = 1 path) + int pathLength = plainAlias.Split('/').GetUpperBound(0); + //now work out where in the list we should put this portalAlias regex pattern + //the list is to be sorted so that those aliases with the most paths + //are at the front of the list : ie, they are tested first + int insertPoint = pathLengths.Count - 1; + //walk through the existing list of path lengths, + //and ascertain where in the list this one falls + //if they are all the same path length, then place them in portal alias order + for (int i = 0; i < pathLengths.Count; i++) + { + insertPoint = i; + if (pathLength > pathLengths[i]) + { + //larger than this position, insert at this value + break; + } + insertPoint++; //next one along (if at end, means add) + } + if (pathLengths.Count > 0 && insertPoint <= pathLengths.Count - 1) + { + //put the new regex pattern into the correct position + regexList.Insert(insertPoint, regexPattern, aliasObject); + pathLengths.Insert(insertPoint, pathLength); + } + else + { + //put the new regex pattern on the end of the list + regexList.Add(regexPattern, aliasObject); + pathLengths.Add(pathLength); + } + } + } + return regexList; + } + + private static SharedDictionary BuildTabDictionary(out PathSizes pathSizes, + FriendlyUrlSettings settings, + int buildPortalId, + SharedDictionary tabIndex, + out Hashtable homePageSkins, + out SharedDictionary portalTabPathDictionary, + Guid parentTraceId) + { + if (tabIndex == null) + { + tabIndex = new SharedDictionary(); + } + + homePageSkins = new Hashtable(); + pathSizes = new PathSizes { MinAliasDepth = 10, MinTabPathDepth = 10, MaxAliasDepth = 0, MaxTabPathDepth = 0 }; + + portalTabPathDictionary = null; + if (buildPortalId >= 0) + { + //dictioanry for storing the tab paths in + portalTabPathDictionary = new SharedDictionary(); + + //init the duplicate key check dictionary - disposed after the tab dictionary is built + var dupCheck = new Dictionary(); + + //get the list of tabs for all portals + //new for 2.0 : only get tabs by portal + //770 : keep track of custom alias tabs + Dictionary tabs = FriendlyUrlController.GetTabs(buildPortalId, false, settings); + + const bool hasSiteRootRedirect = true; + + /* for the requested build portal, add in the standard urls and special rules */ + //735 : switch to custom method for getting portal + PortalInfo thisPortal = CacheController.GetPortal(buildPortalId, true); + List chosenAliases; + Dictionary chosenAliasesCultures; + var aliasSpecificCultures = new List(); + var usingHttpAliases = new List(); + var customHttpAliasesUsed = new List(); + GetAliasFromSettings(buildPortalId, out chosenAliases, out chosenAliasesCultures); + FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings); + + //keep a list of cultures specific to an alias + foreach (string culture in chosenAliasesCultures.Values.Where(culture => aliasSpecificCultures.Contains(culture) == false)) + { + aliasSpecificCultures.Add(culture); + } + + //the home tabid of the portal - should be the home page for the default language (all others will get page path) + int homeTabId = thisPortal.HomeTabId; + + //Add site root redirects + AddSiteRootRedirects(pathSizes, tabIndex, chosenAliases, hasSiteRootRedirect, dupCheck, usingHttpAliases); + + //add in any internal aliases as valid aliase + AddInternalAliases(settings, usingHttpAliases); + + //loop through each tab and add all of the various Url paths that the tab can be found with, + //for all aliases the tab will be used with + foreach (TabInfo tab in tabs.Values) + { + int tabPathDepth = 0; + + //935 : get the tab path and add to the tab path dictionary if it's not just a straight conversion of the TabPath value + //bool modified; + string tabPath = TabPathHelper.GetFriendlyUrlTabPath(tab, options, parentTraceId); + string tabKey = tab.TabID.ToString(); + + using (portalTabPathDictionary.GetWriteLock()) + { + if (portalTabPathDictionary.ContainsKey(tabKey) == false) + { + portalTabPathDictionary.Add(tabKey, tabPath); + } + } + + //now, go through the list of tabs for this portal and build up the dictionary + if ((settings.FriendlyAdminHostUrls && tab.PortalID == -1) || tab.PortalID == buildPortalId) + { + //check if this value has been excluded from being a friendly url + bool isExcluded = RewriteController.IsExcludedFromFriendlyUrls(tab, settings, true); + string tabCulture = tab.CultureCode; + + //770 : custom alias per tab (and culture) + bool customAliasUsed; + var customHttpAlias = ManageCustomAliases(tabCulture, + thisPortal, + tab, + usingHttpAliases, + customHttpAliasesUsed, + out customAliasUsed); + + //process each entry for the alias + foreach (string httpAlias in usingHttpAliases) + { + //string httpAlias = portalAlias.HTTPAlias; + //761 : allow duplicate tab paths between culture-specific aliases + //this is done by ascertaining which culture a particular alias belongs to + //then checking tab cultures as they are added to the dictionary + string aliasCulture = ""; + if (chosenAliasesCultures.ContainsKey(httpAlias.ToLowerInvariant())) + { + aliasCulture = chosenAliasesCultures[httpAlias.ToLowerInvariant()]; + } + bool ignoreTabWrongCulture = false; + //the tab is the wrong culture, so don't add it to the dictionary + + if (aliasCulture != "") + { + if (tabCulture != aliasCulture + //this is a language-specific alias that's different to the culture for this alias + && !string.IsNullOrEmpty(tabCulture) //and the tab culture is set + && aliasSpecificCultures.Contains(tabCulture)) + //and there is a specific alias for this tab culture + { + ignoreTabWrongCulture = true; + } + } + if (!ignoreTabWrongCulture) + { + if (!isExcluded) + { + //Add this tab to the dictionary + //750 : user profile action not returned as buildPortalId not used + tabPathDepth = AddTabToTabDict(tabIndex, + dupCheck, + httpAlias, + aliasCulture, + customHttpAlias, + thisPortal, + tabPath, + ref customHttpAliasesUsed, + tab, + settings, + options, + homeTabId, + ref homePageSkins, + parentTraceId); + } + else + { + //589 : custom redirects added as 200 status not causing base urls to redirect + bool excludeFriendlyUrls = true; + //549 : detect excluded friendly urls by putting a known pattern into the dictionary + //add this tab to the dictionary, but with the hack pattern [UseBase] to capture the fact it's a base Url + //then, if there's redirects for it, add those as well. It's possible to exclude a tab from friendly urls, but + //give it custom redirects + string rewritePath = null; + if (tab.TabUrls.Count > 0) + { + rewritePath = CreateRewritePath(tab.TabID, ""); + string rewritePathKeep = rewritePath; //remember this value to compare + AddCustomRedirectsToDictionary(tabIndex, + dupCheck, + httpAlias, + tab, + settings, + options, + ref rewritePath, + out tabPathDepth, + ref customHttpAliasesUsed, + tab.IsDeleted, + parentTraceId); + if (rewritePath != rewritePathKeep) + //check to see the rewrite path is still the same, or did it get changed? + { + //OK, the rewrite path was modifed by the custom redirects dictionary add + excludeFriendlyUrls = false; + } + } + + if (excludeFriendlyUrls) + { + rewritePath = "[UseBase]"; + //use hack pattern to indicate not to rewrite on this Url + } + + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tab.TabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + true, + false); + } + } + else + { + //ignoring this tab because the alias culture doesn't match to the tab culture + //however, we need to add it to the dictionary in case there's an old link (pre-translation/pre-friendly url/pre-alias&culture linked) + string rewritePath = CreateRewritePath(tab.TabID, tabCulture); + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + tab.TabPath, + rewritePath, + tab.TabID, + UrlEnums.TabKeyPreference.TabRedirected, + ref tabPathDepth, + true, + tab.IsDeleted); + } + pathSizes.SetTabPathDepth(tabPathDepth); + } + if (customHttpAlias != "" && customAliasUsed == false && + usingHttpAliases.Contains(customHttpAlias)) + { + //this was using a custom Http Alias, so remove this from the using list if it wasn't already there + usingHttpAliases.Remove(customHttpAlias); + } + } + } + //now build the standard Urls for all of the aliases that are used + foreach (string httpAlias in usingHttpAliases) + { + //750 : using -1 instead of buildPortalId + //850 : set culture code based on httpALias, where specific culture + //is being associated with httpAlias + string cultureCode = null; + if (chosenAliasesCultures.ContainsKey(httpAlias)) + { + cultureCode = chosenAliasesCultures[httpAlias]; + } + AddStandardPagesToDict(tabIndex, dupCheck, httpAlias, buildPortalId, cultureCode); + } + //and for any custom urls being used + foreach (string httpAlias in customHttpAliasesUsed) + { + //750 : using -1 instead of buildPortalId + //is being associated with httpAlias + string cultureCode = null; + if (chosenAliasesCultures.ContainsKey(httpAlias)) + { + cultureCode = chosenAliasesCultures[httpAlias]; + } + AddStandardPagesToDict(tabIndex, dupCheck, httpAlias, buildPortalId, cultureCode); + //if any site root, add those as well. So if any module providers or rules work + //on the custom http aliases, they will work as well. + if (hasSiteRootRedirect) + { + int tempPathDepth = 0; + AddToTabDict(tabIndex, + dupCheck, + httpAlias, + "*", + "", + -1, + UrlEnums.TabKeyPreference.TabOK, + ref tempPathDepth, + false, + false); + } + } + + //do a check of the rebuildData object, to see if there is anything we needed to add to the dictionary + var rebuildData = (PageIndexData)DataCache.GetCache("rebuildData"); + if (rebuildData != null) + { + //there was rebuild data stored so we could do things post-dictionary rebuild + if (rebuildData.LastPageKey != null && rebuildData.LastPageValue != null) + { + if (tabIndex.ContainsKey(rebuildData.LastPageKey) == false) + { + //add this item to the list of pages, even though it no longer exists + tabIndex.Add(rebuildData.LastPageKey, rebuildData.LastPageValue); + } + } + //now clear out the rebuildData object, because we've checked and used it + DataCache.RemoveCache("rebuildData"); + } + } + return tabIndex; + } + + private static SharedDictionary FetchTabPathDictionary(int portalId) + { + SharedDictionary tabPathDict; + lock (tabPathDictBuildLock) + { + tabPathDict = CacheController.GetTabPathsFromCache(portalId); + } + return tabPathDict; + } + + private static void GetAliasFromSettings(int portalId, + out List useAliases, + out Dictionary aliasCultures) + { + useAliases = new List(); + aliasCultures = new Dictionary(); + //761 : return list of chosen aliases as well, so that Urls can be d + var aliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + //list of portal aliases for this portal + List chosenAliases = null; + var primaryAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + if (primaryAliases.Count > 0) + { + chosenAliases = primaryAliases.GetAliasesForPortalId(portalId); + aliasCultures = primaryAliases.GetAliasesAndCulturesForPortalId(portalId); + } + if (chosenAliases != null && chosenAliases.Count > 0) + { + //add the chosen alias in based on the usePortalAlias setting + useAliases.AddRange(aliases.Where(a => chosenAliases.Contains(a.HTTPAlias.ToLowerInvariant()))); + } + + if (useAliases.Count == 0) + { + //nothing found to match, + //add all aliases in + useAliases.AddRange(aliases); + } + } + + private static string ManageCustomAliases(string tabCulture, + PortalInfo thisPortal, + TabInfo tab, + List httpAliases, + List customHttpAliasesUsed, + out bool customAliasUsed) + { + string customHttpAlias = ""; + string currentCulture = tabCulture; + if (string.IsNullOrEmpty(tabCulture)) + { + currentCulture = thisPortal.DefaultLanguage; + } + + if (tab.CustomAliases.ContainsKey(currentCulture)) + { + customHttpAlias = tab.CustomAliases[currentCulture].ToLower(); + } + customAliasUsed = httpAliases.Contains(customHttpAlias); + //if there is a custom alias for this tab, and it's not one of the ones in the alias list, put it in + //so that this tab will be put into the dictionary with not only the standard alias(es) but also + //the custom alias. Other logic will decide if to redirect the 'wrong' alias if requested with this tab. + if (customAliasUsed == false && customHttpAlias != "") + { + httpAliases.Add(customHttpAlias); + if (customHttpAliasesUsed.Contains(customHttpAlias) == false) + { + customHttpAliasesUsed.Add(customHttpAlias); + } + } + return customHttpAlias; + } + + #endregion + + #region Internal Methods + + internal static string CreateRewritePath(int tabId, string cultureCode, params string[] keyValuePair) + { + string rewritePath = "?TabId=" + tabId.ToString(); + //736 : 5.5 compatibility - identify tab rewriting at source by tab culture code + RewriteController.AddLanguageCodeToRewritePath(ref rewritePath, cultureCode); + return keyValuePair.Aggregate(rewritePath, (current, keyValue) => current + ("&" + keyValue)); + } + + internal static string CreateRewritePath(int tabId, string cultureCode, ActionType action, RedirectReason reason) + { + string rewritePath = CreateRewritePath(tabId, cultureCode); + rewritePath = RedirectTokens.AddRedirectReasonToRewritePath(rewritePath, action, reason); + return rewritePath; + } + + /// + /// Gets the Tab Dictionary from the DataCache memory location, if it's empty or missing, builds a new one + /// + /// + /// ByRef parameter to return the minimum tab path depth (the number of '/' in the tab path) + /// ByRef parameter to return the maximum tab path depth (the number of '/' in the tab path) + /// ByRef parameter to return the minimum alias path depth (the number of '/' in the alias path + /// ByRef parameter to return the maximum alias path depth (the number of '/' in the alias path) + /// + /// + /// + /// + /// Dictionary (string, string) of Tab paths in tab key, with the rewrite path as the value + /// + /// Changes + /// Task 608 : Incrementally build tab dictionary instead of building entire dicitionary all at once + /// Task 609 : If usePortalAlias is specified, only build dictionary with specific portal alias : ignore others + /// Task 791 : allow for specification of true/false for using thread locking to prevent multiple rebuilds on threads + /// + internal static SharedDictionary FetchTabDictionary(int portalId, + out int minTabPathDepth, + out int maxTabPathDepth, + out int minAliasPathDepth, + out int maxAliasPathDepth, + FriendlyUrlSettings settings, + bool forceRebuild, + bool bypassCache, + Guid parentTraceId) + { + SharedDictionary portalDepths; + SharedDictionary dict; + + //place threadlock to prevent two threads getting a null object + //check for the tab dictionary in the DataCache + var cc = new CacheController(); + cc.GetPageIndexFromCache(out dict, out portalDepths, settings); + + string reason = ""; + if (dict == null) + { + reason += "No Page index in cache;"; + } + if (forceRebuild) + { + reason += "Force Rebuild;"; + } + if (bypassCache) + { + reason += "Bypass Cache;"; + } + if (dict != null) + { + using (dict.GetReadLock()) + { + reason += "Existing Page Index=" + dict.Count.ToString() + " items;"; + } + } + + Hashtable homePageSkins; //keeps a list of skins set per home page and culture + SharedDictionary portalTabPathDictionary; + if (dict != null && portalDepths != null && forceRebuild == false && bypassCache == false) + { + PathSizes depthInfo; + bool changed = false; + using (portalDepths.GetWriteLock()) + { + if (!portalDepths.ContainsKey(portalId)) + { + reason += "Portal " + portalId.ToString() + " added to index;"; + + //tab dictionary built, but portal not in it + dict = BuildTabDictionary(out depthInfo, + settings, + portalId, + dict, + out homePageSkins, + out portalTabPathDictionary, + parentTraceId); + + //recheck portal add, when running with locks can get duplicate key exceptions + if (portalDepths.ContainsKey(portalId) == false) + { + portalDepths.Add(portalId, depthInfo); + changed = true; + } + + cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings); + CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins); + } + else + { + depthInfo = portalDepths[portalId]; + } + } + if (changed) + { + //restash dictionary + cc.StorePageIndexInCache(dict, portalDepths, settings, reason); + } + + if (depthInfo != null) + { + minTabPathDepth = depthInfo.MinTabPathDepth; + maxTabPathDepth = depthInfo.MaxTabPathDepth; + minAliasPathDepth = depthInfo.MinAliasDepth; + maxAliasPathDepth = depthInfo.MaxAliasDepth; + } + else + { + //fallback values, should never get here: mainly for compiler wranings + minTabPathDepth = 1; + maxTabPathDepth = 10; + minAliasPathDepth = 1; + maxAliasPathDepth = 4; + } + } + else + { + //the cached dictionary was null or forceRebuild = true or bypassCache = true, so go get a new dictionary + PathSizes depthInfo; + dict = BuildTabDictionary(out depthInfo, + settings, + portalId, + null, + out homePageSkins, + out portalTabPathDictionary, + parentTraceId); + + //store the fact that this portal has been built + portalDepths = new SharedDictionary(); + using (portalDepths.GetWriteLock()) + { + portalDepths.Add(portalId, depthInfo); + } + if (bypassCache == false) //only cache if bypass not switched on + { + cc.StorePageIndexInCache(dict, portalDepths, settings, reason); + } + cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings); + CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins); + minTabPathDepth = depthInfo.MinTabPathDepth; + maxTabPathDepth = depthInfo.MaxTabPathDepth; + minAliasPathDepth = depthInfo.MinAliasDepth; + maxAliasPathDepth = depthInfo.MaxAliasDepth; + } + return dict; + } + + + /// + /// Returns a list of aliases that are used in custom tab/alias association. + /// + /// + /// + internal static List GetCustomPortalAliases(FriendlyUrlSettings settings) + { + List aliases = CacheController.GetCustomAliasesFromCache(); + if (aliases == null) + { + aliases = FriendlyUrlController.GetCustomAliasesForTabs(); + CacheController.StoreCustomAliasesInCache(aliases, settings); + } + return aliases; + } + + /// + /// Gets the portal alias by portal. + /// + /// The portal id. + /// The portal alias. + /// Portal alias. + internal static PortalAliasInfo GetPortalAliasByPortal(int portalId, string portalAlias) + { + PortalAliasInfo retValue = null; + + //get the portal alias collection from the cache + var portalAliasCollection = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId).ToList(); + + bool foundAlias = false; + + //Do a specified PortalAlias check first + PortalAliasInfo portalAliasInfo = portalAliasCollection.SingleOrDefault(a => a.HTTPAlias ==portalAlias.ToLower()); + if (portalAliasInfo != null) + { + if (portalAliasInfo.PortalID == portalId) + { + //set the alias + retValue = portalAliasInfo; + foundAlias = true; + } + } + + if (!foundAlias) + { + //collection to hold aliases sorted by length, longest first + var aliases = (from p in portalAliasCollection + select p.HTTPAlias).ToList(); + + //get aliases sorted by length of alias + aliases.Sort(new StringLengthComparer()); + + //searching from longest to shortest alias ensures that the most specific portal is matched first + //In some cases this method has been called with "portalaliases" that were not exactly the real portal alias + //the startswith behaviour is preserved here to support those non-specific uses + //IEnumerable aliases = portalAliasCollection.Keys.Cast().OrderByDescending(k => k.Length); + foreach (string currentAlias in aliases) + { + // check if the alias key starts with the portal alias value passed in - we use + // StartsWith because child portals are redirected to the parent portal domain name + // eg. child = 'www.domain.com/child' and parent is 'www.domain.com' + // this allows the parent domain name to resolve to the child alias ( the tabid still identifies the child portalid ) + portalAliasInfo = portalAliasCollection.SingleOrDefault(a => a.HTTPAlias == currentAlias); + if (portalAliasInfo != null) + { + string httpAlias = portalAliasInfo.HTTPAlias.ToLower(); + if (httpAlias.StartsWith(portalAlias.ToLower()) && portalAliasInfo.PortalID == portalId) + { + retValue = portalAliasInfo; + break; + } + httpAlias = httpAlias.StartsWith("www.") ? httpAlias.Replace("www.", "") : string.Concat("www.", httpAlias); + if (httpAlias.StartsWith(portalAlias.ToLower()) && portalAliasInfo.PortalID == portalId) + { + retValue = portalAliasInfo; + break; + } + } + } + } + return retValue; + } + + /// + /// Returns an ordered dictionary of alias regex patterns. These patterns are used to identify a portal alias by getting a match. + /// + /// + internal static OrderedDictionary GetPortalAliasRegexes(FriendlyUrlSettings settings) + { + //object to return + OrderedDictionary regexList = CacheController.GetPortalAliasesRegexesFromCache(); + if (regexList == null) + { + regexList = BuildPortalAliasesRegexDictionary(); + CacheController.StorePortalAliasesRegexesInCache(regexList, settings); + } + return regexList; + } + + /// + /// Returns the tab path of the base DNN tab. Ie /Home or /Somepage/SomeOtherPage + /// + /// + /// + /// + /// Will remove // from the tabPath as stored in the Tabs object/table + /// + internal static string GetTabPath(TabInfo tab, FriendlyUrlOptions options, Guid parentTraceId) + { + string tabPath = null; + if (options.CanGenerateNonStandardPath) + { + var tpd = FetchTabPathDictionary(tab.PortalID); + + if (tpd != null) + { + using (tpd.GetReadLock()) + { + if (tpd.Count > 0) + { + //get the path from the dictionary + string tabKey = tab.TabID.ToString(); + if (tpd.ContainsKey(tabKey)) + { + tabPath = tpd[tabKey]; + } + } + } + } + } + + return tabPath ?? (TabPathHelper.GetFriendlyUrlTabPath(tab, options, parentTraceId)); + } + + #endregion + + #region Public Methods + + public static void InvalidateDictionary(string reason, PageIndexData rebuildData, int portalId) + { + //if supplied, store the rebuildData for when the dictionary gets rebuilt + //this is a way of storing data between dictionary rebuilds + if (rebuildData != null) + { + DataCache.SetCache("rebuildData", rebuildData); + } + + //add log entry for cache clearance + var elc = new EventLogController(); + var logValue = new LogInfo {LogTypeKey = "HOST_ALERT"}; + try + { + //817 : not clearing items correctly from dictionary + CacheController.FlushPageIndexFromCache(); + } + catch (Exception ex) + { + //do nothing ; can be from trying to access cache after system restart + Services.Exceptions.Exceptions.LogException(ex); + } + + logValue.AddProperty("Url Rewriting Caching Message", "Page Index Cache Cleared. Reason: " + reason); + logValue.AddProperty("Thread Id", Thread.CurrentThread.ManagedThreadId.ToString()); + elc.AddLog(logValue); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/TabPathController.cs b/DNN Platform/Library/Entities/Urls/TabPathController.cs new file mode 100644 index 00000000000..200abf9727c --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/TabPathController.cs @@ -0,0 +1,413 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The TabPathHelper class provides helper methods for working with tab urls + /// + public class TabPathHelper + { + #region Private Methods + + private static string AppendToTabPath(string path, TabInfo tab, FriendlyUrlOptions options, out bool modified) + { + string tabName = tab.TabName; + var result = new StringBuilder(tabName.Length); + //922 : change to harmonise cleaning of tab + other url name items + tabName = FriendlyUrlController.CleanNameForUrl(tabName, options, out modified); + if (!modified + && string.IsNullOrEmpty(options.PunctuationReplacement) == false + && tab.TabName.Contains(" ") + && tabName.Contains(" ") == false) + { + modified = true; + //spaces replaced - the modified parameter is for all other replacements but space replacements + } + result.Append(tabName); + result.Insert(0, "//"); + result.Insert(0, path); //effectively adds result to the end of the path + return result.ToString(); + } + + #endregion + + #region Internal Methods + + /// + /// Get the tab path for the supplied Tab + /// + /// + /// + /// + /// + internal static string GetFriendlyUrlTabPath(TabInfo tab, FriendlyUrlOptions options, Guid parentTraceId) + { + string baseTabPath = tab.TabPath.Replace("//", "/").TrimStart('/'); + if (options.CanGenerateNonStandardPath) + { + //build up a non-space version of the tab path + baseTabPath = BuildTabPathWithReplacement(tab, options, parentTraceId); + baseTabPath = baseTabPath.Replace("//", "/"); + + //automatic diacritic conversion + if (options.ConvertDiacriticChars) + { + bool diacriticsChanged; + baseTabPath = ReplaceDiacritics(baseTabPath, out diacriticsChanged); + } + } + return baseTabPath; + } + + /// + /// Finds a culture-specific homepage tabid for a non-default language + /// + /// The default culture of the portal + /// + /// The default home page tab id + /// + /// THe valid home page tabid for the portalid and culture + /// Note if no specific home page found for the culture, will return defaultHomeTabId back + internal static int GetHomePageTabIdForCulture(string defaultCulture, int portalId, string cultureCode, + int defaultHomeTabId) + { + int homeTabId = defaultHomeTabId; + if (String.Compare(defaultCulture, cultureCode, StringComparison.OrdinalIgnoreCase) != 0) + { + //not the default culture, so there could be a different home page for the different cultulre in 5.5+ builds + var tc = new TabController(); + var cultureLocale = new Locale { Code = cultureCode, Fallback = cultureCode, Text = cultureCode }; + TabInfo tab = tc.GetTabByCulture(defaultHomeTabId, portalId, cultureLocale); + if (tab != null) + { + //this is the culture specific tab of the home page + homeTabId = tab.TabID; + } + } + return homeTabId; + } + + internal static string GetTabAliasSkinForTabAndAlias(int portalId, string httpAlias, string culture) + { + string skin = null; + Hashtable homePageSkins = CacheController.GetHomePageSkinsFromCache(portalId); + if (homePageSkins != null) + { + string key = httpAlias + "::" + culture; + string key2 = httpAlias; + if (homePageSkins.ContainsKey(key)) + { + skin = (string)homePageSkins[key]; + } + else if (homePageSkins.ContainsKey(key2)) + { + skin = (string)homePageSkins[key2]; + } + } + return skin; + } + + /// + /// For the supplied options, return a tab path for the specified tab + /// + /// TabInfo object of selected tab + /// FriendlyUrlSettings + /// + /// Whether to add in the customised Tab redirects or not + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// 751 : include isDefaultCultureCode flag to determine when using the portal default language + /// 770 : include custom http alias output for when the Url uses a specific alias due to custom Url rules + /// : include new out parameter 'isCustomPath' to return whether the Url was generated from Url-Master custom url + /// + /// The tab path as specified + internal static string GetTabPath(TabInfo tab, + FriendlyUrlSettings settings, + FriendlyUrlOptions options, + bool ignoreCustomRedirects, + bool homePageSiteRoot, + bool isHomeTab, + string cultureCode, + bool isDefaultCultureCode, + bool hasPath, + out bool dropLangParms, + out string customHttpAlias, + out bool isCustomPath, + Guid parentTraceId) + { + string newTabPath; + dropLangParms = false; + customHttpAlias = null; + isCustomPath = false; + if (homePageSiteRoot && isHomeTab && !hasPath) + // && !isDefaultCultureCode - not working for non-language specifc custom root urls + { + newTabPath = "/"; //site root for home page + } + else + { + //build the tab path and check for space replacement + string baseTabPath = TabIndexController.GetTabPath(tab, options, parentTraceId); + + //this is the new tab path + newTabPath = baseTabPath; + //871 : case insensitive compare for culture code, all lookups done on lower case + string cultureCodeKey = ""; + if (cultureCode != null) + { + cultureCodeKey = cultureCode.ToLower(); + } + + bool checkForCustomHttpAlias = false; + //get a custom tab name if redirects are being used + SharedDictionary customAliasForTabs = null; + SharedDictionary> urlDict; + //886 : don't fetch custom urls for host tabs (host tabs can't have redirects or custom Urls) + if (tab.PortalID > -1) + { + urlDict = CustomUrlDictController.FetchCustomUrlDictionary(tab.PortalID, false, false, settings, out customAliasForTabs, parentTraceId); + } + else + { + urlDict = new SharedDictionary>(); + //create dummy dictionary for this tab + } + + if (ignoreCustomRedirects == false) + { + //if not ignoring the custom redirects, look for the Url of the page in this list + //this will be used as the page path if there is one. + + using (urlDict.GetReadLock()) + { + if (urlDict.ContainsKey(tab.TabID)) + { + //we want the custom value + string customTabPath = null; + SharedDictionary tabpaths = urlDict[tab.TabID]; + + using (tabpaths.GetReadLock()) + { + if (tabpaths.ContainsKey(cultureCodeKey)) + { + customTabPath = tabpaths[cultureCodeKey]; + dropLangParms = true; + //the url is based on a custom value which has embedded language parms, therefore don't need them in the url + } + else + { + if (isDefaultCultureCode && tabpaths.ContainsKey("")) + { + customTabPath = tabpaths[""]; + //dropLangParms = true;//drop the language parms if they exist, because this is the default language + } + } + } + if (customTabPath != null) + { + //770 : pull out custom http alias if in string + int aliasSeparator = customTabPath.IndexOf("::", StringComparison.Ordinal); + if (aliasSeparator > 0) + { + customHttpAlias = customTabPath.Substring(0, aliasSeparator); + newTabPath = customTabPath.Substring(aliasSeparator + 2); + } + else + { + newTabPath = customTabPath; + } + } + if (newTabPath == "" && hasPath) + { + //can't pass back a custom path which is blank if there are path segments to the requested final Url + newTabPath = baseTabPath; //revert back to the standard DNN page path + } + else + { + isCustomPath = true; //we are providing a custom Url + } + } + else + { + checkForCustomHttpAlias = true; + } + } + } + else + { + checkForCustomHttpAlias = true; + //always want to check for custom alias, even when we don't want to see any custom redirects + } + + //770 : check for custom alias in these tabs + if (checkForCustomHttpAlias && customAliasForTabs != null) + { + string key = tab.TabID.ToString() + ":" + cultureCodeKey; + using (customAliasForTabs.GetReadLock()) + { + if (customAliasForTabs.ContainsKey(key)) + { + //this tab uses a custom alias + customHttpAlias = customAliasForTabs[key]; + isCustomPath = true; //using custom alias + } + } + } + + if (!dropLangParms) + { + string tabCultureCode = tab.CultureCode; + if (!string.IsNullOrEmpty(tabCultureCode)) + { + dropLangParms = true; + //if the tab has a specified culture code, then drop the language parameters from the friendly Url + } + } + //make lower case if necessary + newTabPath = AdvancedFriendlyUrlProvider.ForceLowerCaseIfAllowed(tab, newTabPath, settings); + } + return newTabPath; + } + + internal static bool IsTabHomePage(TabInfo tab, PortalSettings portalSettings) + { + bool isTabHomePage = (tab.TabID == portalSettings.HomeTabId); + if (!isTabHomePage) + { + //756: check if content localization is switched on before checking for other languages + if (Host.Host.EnableBrowserLanguage) + { + //check the localised versions of the tab + TabInfo defaultLangTab = tab.DefaultLanguageTab; + if (defaultLangTab != null) + { + //is the default language tab the home tab? + if (defaultLangTab.TabID == portalSettings.HomeTabId) + { + isTabHomePage = true; + } + else + { + //iterate through the other localised versions of this tab and check if they are the same + //as the home tabid + Dictionary localizedTabs = tab.LocalizedTabs; + if (localizedTabs.Values.Any(localTab => localTab.TabID == portalSettings.HomeTabId)) + { + isTabHomePage = true; + } + } + } + else + { + //check if this tab belongs to the default language, in which case it is already the default language tab + string cultureCode = tab.CultureCode; + if (String.Compare(cultureCode, portalSettings.DefaultLanguage, StringComparison.OrdinalIgnoreCase) == 0) + { + //get the localized versions and see if this matches + Dictionary localizedTabs = tab.LocalizedTabs; + if (localizedTabs.Values.Any(localTab => localTab.TabID == portalSettings.HomeTabId)) + { + isTabHomePage = true; + } + } + } + } + } + return isTabHomePage; + } + + #endregion + + #region Public Methods + + public static string BuildTabPathWithReplacement(TabInfo tab, FriendlyUrlOptions options, Guid parentTraceId) + { + string path = ""; + if ((tab.ParentId > -1)) + { + var tc = new TabController(); + TabInfo parentTab = tc.GetTab(tab.ParentId, tab.PortalID, false); + //822 : don't assume parent tab is going to exist - database might be corrupted + //896 : check to make sure tabid and parentid are different - or stack overflow occurs with terminal loop + if (parentTab != null && parentTab.TabID != tab.TabID) + { + path = BuildTabPathWithReplacement(parentTab, options, parentTraceId); + } + } + bool modified; + path = AppendToTabPath(path, tab, options, out modified); + + return path; + } + + /// + /// Replaces the diacritic characters in a path with other values + /// + /// + /// + /// + public static string ReplaceDiacritics(string tabPath, out bool replacedDiacritic) + { + string nmTabPath = tabPath.Normalize(NormalizationForm.FormD); + var sb = new StringBuilder(); + for (int i = 0; i < nmTabPath.Length; i++) + { + char c = nmTabPath[i]; + if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) + { + sb.Append(c); + } + } + string result = sb.ToString(); + replacedDiacritic = String.CompareOrdinal(tabPath, result) != 0; + return sb.ToString(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlAction.cs b/DNN Platform/Library/Entities/Urls/UrlAction.cs new file mode 100644 index 00000000000..4db422138b7 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlAction.cs @@ -0,0 +1,295 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The UrlAction class keeps state of the current Request throughout the rewriting process + /// + public class UrlAction + { + //829 add in constructor that works around physical path length restriction + public UrlAction(HttpRequest request) + { + BrowserType = BrowserTypes.Normal; + CanRewrite = StateBoolean.NotSet; + Action = ActionType.Continue; + string physicalPath = ""; + try + { + physicalPath = request.PhysicalPath; + } + catch (PathTooLongException) + { + //don't handle exception, but put something into the physical path + physicalPath = request.ApplicationPath; //will be no file for this location + VirtualPath = StateBoolean.True; + } + finally + { + Constructor(request.Url.Scheme, request.ApplicationPath, physicalPath); + } + } + + public UrlAction(string scheme, string applicationPath, string physicalPath) + { + BrowserType = BrowserTypes.Normal; + CanRewrite = StateBoolean.NotSet; + Action = ActionType.Continue; + Constructor(scheme, applicationPath, physicalPath); + } + + private void Constructor(string scheme, string applicationPath, string physicalPath) + { + if (scheme.EndsWith("://") == false) + { + Scheme = scheme + "://"; + } + else + { + Scheme = scheme; + } + ApplicationPath = applicationPath; + string domainPath = applicationPath.Replace(scheme, ""); + DomainName = domainPath.Contains("/") ? domainPath.Substring(0, domainPath.IndexOf('/')) : domainPath; + PhysicalPath = physicalPath; + PortalId = -1; + TabId = -1; + Reason = RedirectReason.Not_Redirected; + FriendlyRewrite = false; + BypassCachedDictionary = false; + VirtualPath = StateBoolean.NotSet; + IsSecureConnection = false; + IsSSLOffloaded = false; + DebugMessages = new List(); + CultureCode = null; + } + + #region Private Members + + private List _licensedProviders; + private PortalAliasInfo _portalAlias; + + #endregion + + #region Public Properties + + public Uri Url { get; set; } + public bool DoRewrite { get; set; } + public bool FriendlyRewrite { get; set; } + //friendlyRewrite means it was rewritten without looking up the tabid in the url + public bool BypassCachedDictionary { get; set; } + public string RewritePath { get; set; } + public string RawUrl { get; set; } + public string DebugData { get; set; } + public string PhysicalPath { get; set; } + public StateBoolean VirtualPath { get; set; } + public string ApplicationPath { get; set; } + public bool RebuildRequested { get; set; } + public string FinalUrl { get; set; } + public string Scheme { get; set; } + public bool IsSecureConnection { get; set; } + public bool IsSSLOffloaded { get; set; } + public string DomainName { get; set; } + public Exception Ex { get; set; } + public string dictKey { get; set; } + public string dictVal { get; set; } + public List DebugMessages { get; set; } + + public int TabId { get; set; } + + public int PortalId { get; set; } + + public RedirectReason Reason { get; set; } + + public string HttpAlias { get; set; } + + public ActionType Action { get; set; } + + public string CultureCode { get; set; } + + public string OriginalPath { get; private set; } + + public string OriginalPathNoAlias { get; private set; } + + public bool RedirectAllowed { get; private set; } + + public StateBoolean CanRewrite { get; set; } + + //the alias for the current request + public PortalAliasInfo PortalAlias + { + get { return _portalAlias; } + set + { + if (value != null) + { + PortalId = value.PortalID; + HttpAlias = value.HTTPAlias; + } + _portalAlias = value; + } + } + //the primary alias, if different to the current alias + public PortalAliasInfo PrimaryAlias { get; set; } + public DotNetNuke.Entities.Portals.PortalSettings.PortalAliasMapping PortalAliasMapping {get; set;} + public bool CustomParmRewrite { get; set; } + + //737 : mobile browser identificatino + public BrowserTypes BrowserType { get; private set; } + + public bool IsPhysicalResource { get; set; } + + #endregion + + #region public methods + + public string UnlicensedProviderMessage { get; set; } + + public bool UnlicensedProviderCalled { get; set; } + + /// + /// Sets the action value, but checks to ensure that the action is + /// not being 'downgraded' (example: cannot set 'Redirect301' to 'CheckFor301') + /// + /// + public void SetActionWithNoDowngrade(ActionType newAction) + { + switch (newAction) + { + case ActionType.CheckFor301: + if (Action != ActionType.Redirect301 + && Action != ActionType.Redirect302 + && Action != ActionType.Redirect302Now + && Action != ActionType.Output404) + { + Action = newAction; + } + break; + default: + Action = newAction; + break; + } + } + + + public void AddLicensedProviders(List licensedProviders) + { + if (_licensedProviders == null) + { + _licensedProviders = new List(); + } + foreach (string lp in licensedProviders) + { + if (_licensedProviders.Contains(lp.ToLower()) == false) + { + _licensedProviders.Add(lp.ToLower()); + } + } + } + + public void AddLicensedProvider(string providerName) + { + if (_licensedProviders == null) + { + _licensedProviders = new List(); + } + if (_licensedProviders.Contains(providerName.ToLower()) == false) + { + _licensedProviders.Add(providerName.ToLower()); + } + } + + public bool IsProviderLicensed(string providerName) + { + if (_licensedProviders == null) + { + return false; + } + return _licensedProviders.Contains(providerName.ToLower()); + } + + /// + /// Copies the original request path to the OriginalPath variables (originalPath, originanPathNoAlias) + /// + /// + /// + public void SetOriginalPath(string path, FriendlyUrlSettings settings) + { + OriginalPath = path; + OriginalPathNoAlias = path; + if (!string.IsNullOrEmpty(HttpAlias) && path.Contains(HttpAlias)) + { + OriginalPathNoAlias = path.Substring(path.IndexOf(HttpAlias, StringComparison.Ordinal) + HttpAlias.Length); + } + } + + public void SetBrowserType(HttpRequest request, HttpResponse response, FriendlyUrlSettings settings) + { + //set the mobile browser type + if (request != null && response != null && settings != null) + { + BrowserType = FriendlyUrlController.GetBrowserType(request, response, settings); + } + } + + public void SetRedirectAllowed(string path, FriendlyUrlSettings settings) + { + string regexExpr = settings.DoNotRedirectRegex; + try + { + if (!string.IsNullOrEmpty(regexExpr)) + { + //if a regex match, redirect Not allowed + RedirectAllowed = !Regex.IsMatch(path, regexExpr, RegexOptions.IgnoreCase); + } + else + { + RedirectAllowed = true; + } + } + catch (Exception ex) + { + RedirectAllowed = true; //default : true, unless regex allows it. So if regex causes an exception + //then we should allow the redirect + + UrlRewriterUtils.LogExceptionInRequest(ex, "Not Set", this); + Ex = ex; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlEnumHelpers.cs b/DNN Platform/Library/Entities/Urls/UrlEnumHelpers.cs new file mode 100644 index 00000000000..5cc08a360f4 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlEnumHelpers.cs @@ -0,0 +1,40 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class UrlEnumHelpers + { + public static BrowserTypes FromString(string value) + { + var result = BrowserTypes.Normal; + switch (value.ToLower()) + { + case "mobile": + result = BrowserTypes.Mobile; + break; + } + return result; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlEnums.cs b/DNN Platform/Library/Entities/Urls/UrlEnums.cs new file mode 100644 index 00000000000..d0016fd992f --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlEnums.cs @@ -0,0 +1,35 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + internal static class UrlEnums + { + internal enum TabKeyPreference + { + TabOK, + TabRedirected, + TabDeleted + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlFormatType.cs b/DNN Platform/Library/Entities/Urls/UrlFormatType.cs new file mode 100644 index 00000000000..2a6745c932c --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlFormatType.cs @@ -0,0 +1,32 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum UrlFormatType + { + SearchFriendly, + HumanFriendly, + Advanced + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlProcessType.cs b/DNN Platform/Library/Entities/Urls/UrlProcessType.cs new file mode 100644 index 00000000000..aced5dfb3dd --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlProcessType.cs @@ -0,0 +1,34 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public enum UrlProcessType + { + Rewriting + , + Redirecting + , + Replacing + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlRewriterBase.cs b/DNN Platform/Library/Entities/Urls/UrlRewriterBase.cs new file mode 100644 index 00000000000..f14d18721cb --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlRewriterBase.cs @@ -0,0 +1,66 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + /// + /// Abstract class to allow derived classes of different implementations of Url Rewriter + /// + public abstract class UrlRewriterBase + { + internal abstract void RewriteUrl(object sender, EventArgs e); + + protected static void AutoAddAlias(HttpContext context) + { + var portalId = Host.Host.HostPortalID; + //the domain name was not found so try using the host portal's first alias + if (portalId > Null.NullInteger) + { + var portalAliasInfo = new PortalAliasInfo { PortalID = portalId, HTTPAlias = Globals.GetDomainName(context.Request, true) }; + TestablePortalAliasController.Instance.AddPortalAlias(portalAliasInfo); + + context.Response.Redirect(context.Request.Url.ToString(), true); + } + } + + protected static bool CanAutoAddPortalAlias() + { + bool autoAddPortalAlias = HostController.Instance.GetBoolean("AutoAddPortalAlias"); + autoAddPortalAlias = autoAddPortalAlias && (new PortalController().GetPortals().Count == 1); + return autoAddPortalAlias; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/UrlRewriterUtils.cs b/DNN Platform/Library/Entities/Urls/UrlRewriterUtils.cs new file mode 100644 index 00000000000..779591180a1 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/UrlRewriterUtils.cs @@ -0,0 +1,183 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Reflection; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Urls +{ + public class UrlRewriterUtils + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(UrlRewriterUtils)); + + /// + /// Return a FriendlyUrlOptions object from the provider settings + /// + /// + /// + public static FriendlyUrlOptions GetOptionsFromSettings(FriendlyUrlSettings settings) + { + var options = new FriendlyUrlOptions + { + PunctuationReplacement = (settings.ReplaceSpaceWith != FriendlyUrlSettings.ReplaceSpaceWithNothing) + ? settings.ReplaceSpaceWith + : String.Empty, + SpaceEncoding = settings.SpaceEncodingValue, + MaxUrlPathLength = 200, + ConvertDiacriticChars = settings.AutoAsciiConvert, + RegexMatch = settings.RegexMatch, + IllegalChars = settings.IllegalChars, + ReplaceChars = settings.ReplaceChars, + ReplaceDoubleChars = settings.ReplaceDoubleChars, + ReplaceCharWithChar = settings.ReplaceCharacterDictionary, + PageExtension = (settings.PageExtensionUsageType == PageExtensionUsageType.Never) + ? "" + : settings.PageExtension + }; + return options; + } + + /// + /// Logs the 404 error to a table for later checking + /// + /// + /// + /// + public static void Log404(HttpRequest request, FriendlyUrlSettings settings, UrlAction result) + { + var controller = new LogController(); + var log = new LogInfo + { + LogTypeKey = EventLogController.EventLogType.PAGE_NOT_FOUND_404.ToString(), + LogPortalID = (result.PortalAlias != null) ? result.PortalId : -1 + }; + log.LogProperties.Add(new LogDetailInfo("TabId", (result.TabId > 0) ? result.TabId.ToString() : String.Empty)); + log.LogProperties.Add(new LogDetailInfo("PortalAlias", (result.PortalAlias != null) ? result.PortalAlias.HTTPAlias : String.Empty)); + log.LogProperties.Add(new LogDetailInfo("OriginalUrl", result.RawUrl)); + + if (request != null) + { + if (request.UrlReferrer != null) + { + log.LogProperties.Add(new LogDetailInfo("Referer", request.UrlReferrer.AbsoluteUri)); + } + log.LogProperties.Add(new LogDetailInfo("Url", request.Url.AbsoluteUri)); + log.LogProperties.Add(new LogDetailInfo("UserAgent", request.UserAgent)); + log.LogProperties.Add(new LogDetailInfo("HostAddress", request.UserHostAddress)); + log.LogProperties.Add(new LogDetailInfo("HostName", request.UserHostName)); + } + + controller.AddLog(log); + } + + /// + /// logs an exception once per cache-lifetime + /// + /// + /// + /// + public static void LogExceptionInRequest(Exception ex, string status, UrlAction result) + { + if (ex != null) + { + //831 : improve exception logging by logging custom properties instead of just the raw exception + //this logic prevents a site logging an exception for every request made. Instead + //the exception will be logged once for the life of the cache / application restart or 1 hour, whichever is shorter. + //create a cache key for this exception type + string cacheKey = ex.GetType().ToString(); + //see if there is an existing object logged for this exception type + object existingEx = DataCache.GetCache(cacheKey); + if (existingEx == null) + { + //if there was no existing object logged for this exception type, this is a new exception + DateTime expire = DateTime.Now.AddHours(1); + DataCache.SetCache(cacheKey, cacheKey, expire); + //just store the cache key - it doesn't really matter + //create a log event + var elc = new EventLogController(); + var logEntry = new LogInfo { LogTypeKey = "GENERAL_EXCEPTION" }; + logEntry.AddProperty("Url Processing Exception", "Exception in Url Rewriting Process"); + logEntry.AddProperty("Http Status", status); + if (result != null) + { + logEntry.AddProperty("Original Path", result.OriginalPath ?? "null"); + logEntry.AddProperty("Raw Url", result.RawUrl ?? "null"); + logEntry.AddProperty("Final Url", result.FinalUrl ?? "null"); + + logEntry.AddProperty("Rewrite Result", !string.IsNullOrEmpty(result.RewritePath) + ? result.RewritePath + : "[no rewrite]"); + logEntry.AddProperty("Redirect Location", string.IsNullOrEmpty(result.FinalUrl) + ? "[no redirect]" + : result.FinalUrl); + logEntry.AddProperty("Action", result.Action.ToString()); + logEntry.AddProperty("Reason", result.Reason.ToString()); + logEntry.AddProperty("Portal Id", result.PortalId.ToString()); + logEntry.AddProperty("Tab Id", result.TabId.ToString()); + logEntry.AddProperty("Http Alias", result.PortalAlias != null + ? result.PortalAlias.HTTPAlias + : "Null"); + + if (result.DebugMessages != null) + { + int i = 1; + foreach (string msg in result.DebugMessages) + { + logEntry.AddProperty("Debug Message " + i.ToString(), msg); + i++; + } + } + } + else + { + logEntry.AddProperty("Result", "Result value null"); + } + logEntry.AddProperty("Exception Type", ex.GetType().ToString()); + logEntry.AddProperty("Message", ex.Message); + logEntry.AddProperty("Stack Trace", ex.StackTrace); + if (ex.InnerException != null) + { + logEntry.AddProperty("Inner Exception Message", ex.InnerException.Message); + logEntry.AddProperty("Inner Exception Stacktrace", ex.InnerException.StackTrace); + } + logEntry.BypassBuffering = true; + elc.AddLog(logEntry); + + //Log this error in lig4net + Logger.Error(ex); + } + } + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Urls/XmlHelpers.cs b/DNN Platform/Library/Entities/Urls/XmlHelpers.cs new file mode 100644 index 00000000000..fb572e15d15 --- /dev/null +++ b/DNN Platform/Library/Entities/Urls/XmlHelpers.cs @@ -0,0 +1,109 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; + +using DotNetNuke.Entities.Tabs; + +namespace DotNetNuke.Entities.Urls +{ + /// + /// The Xml Helpers class is used to read in parameter rewrite/replace/redirect rules from the friendlyUrlParms.config file + /// + internal static class XmlHelpers + { + /// + /// Returns a tab id from either a raw tabId, or a list of tab names delimited by ';' + /// + /// + /// + /// + /// + /// + internal static List TabIdsFromAttributes(string tabIdsRaw, string tabNames, int portalId, ref List messages) + { + if (messages == null) + { + messages = new List(); + } + var tabIds = new List(); + if (!string.IsNullOrEmpty(tabIdsRaw)) + { + string[] rawTabids = tabIdsRaw.Split(';'); + foreach (string rawTabId in rawTabids) + { + int tabId; + if (Int32.TryParse(rawTabId, out tabId)) + { + tabIds.Add(tabId); + } + } + } + if (tabNames != null) + { + //get the portal by name + if (tabNames == "All") + { + tabIds.Add(-1); + } + else + { + var tc = new TabController(); + //loop through all specified tab names + foreach (string tabName in tabNames.Split(';')) + { + if (String.Compare(tabName, "default.aspx", StringComparison.OrdinalIgnoreCase) == 0) + { + //default.aspx is marked with a -2 tabid + tabIds.Add(-2); + } + else + { + //593 : add in site root rewriting processing + if (tabName == "/") + { + //site root marked with a -3 tabid + tabIds.Add(-3); + } + else + { + //portal id specified : specific portal + TabInfo tab = tc.GetTabByName(tabName, portalId); + if (tab != null) + { + tabIds.Add(tab.TabID); + } + else + { + messages.Add("TabName " + tabName + " not found for portalId " + portalId.ToString()); + } + } + } + } + } + } + return tabIds; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Exceptions/InvalidVerificationCodeException.cs b/DNN Platform/Library/Entities/Users/Exceptions/InvalidVerificationCodeException.cs new file mode 100644 index 00000000000..b9eabe8d5f7 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Exceptions/InvalidVerificationCodeException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class InvalidVerificationCodeException : Exception + { + public InvalidVerificationCodeException() + { + } + + public InvalidVerificationCodeException(string message) + : base(message) + { + } + + public InvalidVerificationCodeException(string message, Exception inner) + : base(message, inner) + { + } + + public InvalidVerificationCodeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Exceptions/UserAlreadyVerifiedException.cs b/DNN Platform/Library/Entities/Users/Exceptions/UserAlreadyVerifiedException.cs new file mode 100644 index 00000000000..f7d737a82aa --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Exceptions/UserAlreadyVerifiedException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserAlreadyVerifiedException : Exception + { + public UserAlreadyVerifiedException() + { + } + + public UserAlreadyVerifiedException(string message) + : base(message) + { + } + + public UserAlreadyVerifiedException(string message, Exception inner) + : base(message, inner) + { + } + + public UserAlreadyVerifiedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Exceptions/UserDoesNotExistException.cs b/DNN Platform/Library/Entities/Users/Exceptions/UserDoesNotExistException.cs new file mode 100644 index 00000000000..5a344d17d62 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Exceptions/UserDoesNotExistException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserDoesNotExistException : Exception + { + public UserDoesNotExistException() + { + } + + public UserDoesNotExistException(string message) + : base(message) + { + } + + public UserDoesNotExistException(string message, Exception inner) + : base(message, inner) + { + } + + public UserDoesNotExistException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Internal/IUserController.cs b/DNN Platform/Library/Entities/Users/Internal/IUserController.cs new file mode 100644 index 00000000000..d8931bbc218 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Internal/IUserController.cs @@ -0,0 +1,49 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Users.Internal +{ + public interface IUserController + { + UserInfo GetUserByDisplayname(int portalId, string displayName); + + /// + /// GetUser retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The Id of the user being retrieved from the Data Store. + /// The User as a UserInfo object + UserInfo GetUserById(int portalId, int userId); + + IList GetUsersAdvancedSearch(int portalId, int userId, int filterUserId, int filterRoleId, int relationTypeId, + bool isAdmin, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyNames, string propertyValues); + + IList GetUsersBasicSearch(int portalId, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyName, string propertyValue); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Internal/TestableUserController.cs b/DNN Platform/Library/Entities/Users/Internal/TestableUserController.cs new file mode 100644 index 00000000000..02f79d5562b --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Internal/TestableUserController.cs @@ -0,0 +1,41 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Entities.Users.Internal +{ + public class TestableUserController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new UserControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Internal/UserControllerImpl.cs b/DNN Platform/Library/Entities/Users/Internal/UserControllerImpl.cs new file mode 100644 index 00000000000..c6485ad30b8 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Internal/UserControllerImpl.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Membership; + +namespace DotNetNuke.Entities.Users.Internal +{ + internal class UserControllerImpl : IUserController + { + public UserInfo GetUserByDisplayname(int portalId, string displayName) + { + return MembershipProvider.Instance().GetUserByDisplayName(PortalController.GetEffectivePortalId(portalId), displayName); + } + + public UserInfo GetUserById(int portalId, int userId) + { + return UserController.GetUserById(PortalController.GetEffectivePortalId(portalId), userId); + } + + public IList GetUsersAdvancedSearch(int portalId, int userId, int filterUserId, int filterRoleId, int relationshipTypeId, + bool isAdmin, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyNames, string propertyValues) + { + return MembershipProvider.Instance().GetUsersAdvancedSearch(PortalController.GetEffectivePortalId(portalId), userId, filterUserId, filterRoleId, relationshipTypeId, + isAdmin, pageIndex, pageSize, sortColumn, + sortAscending, propertyNames, propertyValues); + } + + public IList GetUsersBasicSearch(int portalId, int pageIndex, int pageSize, string sortColumn, bool sortAscending, string propertyName, string propertyValue) + { + return MembershipProvider.Instance().GetUsersBasicSearch(PortalController.GetEffectivePortalId(portalId), pageIndex, pageSize, sortColumn, + sortAscending, propertyName, propertyValue); + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordController.cs b/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordController.cs new file mode 100644 index 00000000000..a11dda459ae --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordController.cs @@ -0,0 +1,76 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Entities.Users.Membership +{ + public class MembershipPasswordController + { + private static readonly DataProvider Provider = DataProvider.Instance(); + + public List GetPasswordHistory() + { + List history = CBO.FillCollection(Provider.GetPasswordHistory(UserController.GetCurrentUserInfo().UserID)); + return history; + } + + + public bool IsValidToken(int userId, Guid resetToken) + { + if (UserController.GetCurrentUserInfo().PasswordResetToken == resetToken && UserController.GetCurrentUserInfo().PasswordResetExpiration <= DateTime.Now) + { + return true; + } + return false; + } + + public bool FoundBannedPassword(string inputString) + { + const string listName = "BannedPasswords"; + + var listController = new ListController(); + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + + IEnumerable listEntryHostInfos = listController.GetListEntryInfoItems(listName, "", Null.NullInteger); + IEnumerable listEntryPortalInfos = listController.GetListEntryInfoItems(listName + "-" + settings.PortalId, "", settings.PortalId); + + IEnumerable query2 = listEntryHostInfos.Where(test => test.Text == inputString); + IEnumerable query3 = listEntryPortalInfos.Where(test => test.Text == inputString); + + if (query2.Any() || query3.Any()) + { + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordSettings.cs b/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordSettings.cs new file mode 100644 index 00000000000..314974f28a6 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Membership/MembershipPasswordSettings.cs @@ -0,0 +1,109 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Web.Security; + +using DotNetNuke.Security.Membership; + +namespace DotNetNuke.Entities.Users.Membership +{ + public class MembershipPasswordSettings + { + #region Public Properties + + public bool EnableBannedList { get; set; } + public bool EnableStrengthMeter { get; set; } + public bool EnableIPChecking { get; set; } + public bool EnablePasswordHistory { get; set; } + + public int NumberOfPasswordsStored { get; set; } + public int ResetLinkValidity { get; set; } + + /// + /// minimum number of non-alphanumeric characters setting for password strength indicator + /// + public int MinNonAlphanumericCharacters + { + get + { + return System.Web.Security.Membership.MinRequiredNonAlphanumericCharacters; + } + } + + /// + /// minimum length of password setting for password strength indicator + /// + public int MinPasswordLength + { + get + { + return System.Web.Security.Membership.MinRequiredPasswordLength; + } + } + + /// + /// currently configured password format for installation + /// + public PasswordFormat PasswordFormat + { + get + { + switch (System.Web.Security.Membership.Provider.PasswordFormat) + { + case MembershipPasswordFormat.Encrypted: + return PasswordFormat.Encrypted; + case MembershipPasswordFormat.Hashed: + return PasswordFormat.Hashed; + default: + return PasswordFormat.Clear; + } + } + } + + #endregion + + #region initialization methods + + /// + /// Initialiser for MembershipPasswordSettings provider object. + /// + public MembershipPasswordSettings(int portalId) + { + //portalId not used currently - left in place for potential site specific settings + PortalId = portalId; + + EnableBannedList = Host.Host.EnableBannedList; + EnableStrengthMeter = Host.Host.EnableStrengthMeter; + EnableIPChecking = Host.Host.EnableIPChecking; + EnablePasswordHistory = Host.Host.EnablePasswordHistory; + + ResetLinkValidity = Host.Host.MembershipResetLinkValidity; + NumberOfPasswordsStored = Host.Host.MembershipNumberPasswords; + } + + public int PortalId { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Membership/MembershipPropertyAccess.cs b/DNN Platform/Library/Entities/Users/Membership/MembershipPropertyAccess.cs new file mode 100644 index 00000000000..49a90ba0bc8 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Membership/MembershipPropertyAccess.cs @@ -0,0 +1,110 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; + +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + public class MembershipPropertyAccess : IPropertyAccess + { + private readonly UserInfo objUser; + + public MembershipPropertyAccess(UserInfo User) + { + objUser = User; + } + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope CurrentScope, ref bool PropertyNotFound) + { + UserMembership objMembership = objUser.Membership; + bool UserQueriesHimself = (objUser.UserID == AccessingUser.UserID && objUser.UserID != -1); + if (CurrentScope < Scope.DefaultSettings || (CurrentScope == Scope.DefaultSettings && !UserQueriesHimself) || + ((CurrentScope != Scope.SystemMessages || objUser.IsSuperUser) + && (propertyName.ToLower() == "password" || propertyName.ToLower() == "passwordanswer" || propertyName.ToLower() == "passwordquestion") + )) + { + PropertyNotFound = true; + return PropertyAccess.ContentLocked; + } + string OutputFormat = string.Empty; + if (format == string.Empty) + { + OutputFormat = "g"; + } + switch (propertyName.ToLower()) + { + case "approved": + return (PropertyAccess.Boolean2LocalizedYesNo(objMembership.Approved, formatProvider)); + case "createdondate": + return (objMembership.CreatedDate.ToString(OutputFormat, formatProvider)); + case "isonline": + return (PropertyAccess.Boolean2LocalizedYesNo(objMembership.IsOnLine, formatProvider)); + case "lastactivitydate": + return (objMembership.LastActivityDate.ToString(OutputFormat, formatProvider)); + case "lastlockoutdate": + return (objMembership.LastLockoutDate.ToString(OutputFormat, formatProvider)); + case "lastlogindate": + return (objMembership.LastLoginDate.ToString(OutputFormat, formatProvider)); + case "lastpasswordchangedate": + return (objMembership.LastPasswordChangeDate.ToString(OutputFormat, formatProvider)); + case "lockedout": + return (PropertyAccess.Boolean2LocalizedYesNo(objMembership.LockedOut, formatProvider)); + case "objecthydrated": + return (PropertyAccess.Boolean2LocalizedYesNo(true, formatProvider)); + case "password": + return PropertyAccess.FormatString(objMembership.Password, format); + case "passwordanswer": + return PropertyAccess.FormatString(objMembership.PasswordAnswer, format); + case "passwordquestion": + return PropertyAccess.FormatString(objMembership.PasswordQuestion, format); + case "passwordresettoken": + return PropertyAccess.FormatString(Convert.ToString(objUser.PasswordResetToken), format); + case "passwordresetexpiration": + return PropertyAccess.FormatString(objUser.PasswordResetExpiration.ToString(formatProvider), format); + case "updatepassword": + return (PropertyAccess.Boolean2LocalizedYesNo(objMembership.UpdatePassword, formatProvider)); + case "username": + return (PropertyAccess.FormatString(objUser.Username, format)); + case "email": + return (PropertyAccess.FormatString(objUser.Email, format)); + } + return PropertyAccess.GetObjectProperty(objMembership, propertyName, format, formatProvider, ref PropertyNotFound); + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Membership/PasswordHistory.cs b/DNN Platform/Library/Entities/Users/Membership/PasswordHistory.cs new file mode 100644 index 00000000000..7ca21da2ce7 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Membership/PasswordHistory.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using DotNetNuke.Common.Utilities; +using System; +using System.Data; + +namespace DotNetNuke.Entities.Users.Membership +{ + public class PasswordHistory : BaseEntityInfo + { + public int PasswordHistoryId { get; set; } + public int UserId { get; set; } + public string Password { get; set; } + public string PasswordSalt { get; set; } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.PasswordHistoryId = Convert.ToInt32(dr["PasswordHistoryID"]); + this.UserId = Null.SetNullInteger(dr["UserID"]); + this.Password = (dr["Password"]).ToString(); + this.PasswordSalt = (dr["PasswordSalt"]).ToString(); + + //add audit column data + FillInternal(dr); + } + + } +} diff --git a/DNN Platform/Library/Entities/Users/Membership/UserMembership.cs b/DNN Platform/Library/Entities/Users/Membership/UserMembership.cs new file mode 100644 index 00000000000..925b603d6ab --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Membership/UserMembership.cs @@ -0,0 +1,245 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; + +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserMembership + /// ----------------------------------------------------------------------------- + /// + /// The UserMembership class provides Business Layer model for the Users Membership + /// related properties + /// + /// + /// + /// + /// [cnurse] 12/22/2005 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserMembership + { + private readonly UserInfo _user; + private bool _objectHydrated; + + public UserMembership(UserInfo user) + { + Approved = true; + _user = user; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the User is Approved + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public bool Approved { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's Creation Date + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime CreatedDate { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Whether is deleted. + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsDeleted { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the User Is Online + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsOnLine { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Activity Date of the User + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime LastActivityDate { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Lock Out Date of the User + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime LastLockoutDate { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Login Date of the User + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime LastLoginDate { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Password Change Date of the User + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime LastPasswordChangeDate { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the user is locked out + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public bool LockedOut { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's Password + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Password { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's Password Answer + /// + /// + /// [cnurse] 08/04/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string PasswordAnswer { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's Password Confirm value + /// + /// ----------------------------------------------------------------------------- + public string PasswordConfirm { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's Password Question + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string PasswordQuestion { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a flag that determines whether the password should be updated + /// + /// + /// [cnurse] 03/14/2006 Created + /// + /// ----------------------------------------------------------------------------- + public bool UpdatePassword { get; set; } + + [Obsolete("Deprecated in DNN 5.1")] + public UserMembership() + { + Approved = true; + _user = new UserInfo(); + } + + [Obsolete("Deprecated in DNN 5.1")] + [Browsable(false)] + public string Email + { + get + { + return _user.Email; + } + set + { + _user.Email = value; + } + } + + [Obsolete("Deprecated in DNN 5.1")] + [Browsable(false)] + public bool ObjectHydrated + { + get + { + return _objectHydrated; + } + set + { + _objectHydrated = true; + } + } + + [Obsolete("Deprecated in DNN 5.1")] + [Browsable(false)] + public string Username + { + get + { + return _user.Username; + } + set + { + _user.Username = value; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Profile/ProfilePropertyAccess.cs b/DNN Platform/Library/Entities/Users/Profile/ProfilePropertyAccess.cs new file mode 100644 index 00000000000..575ee2c0a5c --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Profile/ProfilePropertyAccess.cs @@ -0,0 +1,266 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Icons; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Security; +using DotNetNuke.Services.Tokens; + +#endregion + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Entities.Users +// ReSharper restore CheckNamespace +{ + public class ProfilePropertyAccess : IPropertyAccess + { + private readonly UserInfo user; + private string administratorRoleName; + + public ProfilePropertyAccess(UserInfo user) + { + this.user = user; + } + + #region Private Members + + private static string DisplayDataType(ProfilePropertyDefinition definition) + { + string cacheKey = string.Format("DisplayDataType:{0}", definition.DataType); + string strDataType = Convert.ToString(DataCache.GetCache(cacheKey)) + ""; + if (strDataType == string.Empty) + { + var objListController = new ListController(); + strDataType = objListController.GetListEntryInfo(definition.DataType).Value; + DataCache.SetCache(cacheKey, strDataType); + } + return strDataType; + } + + private bool CheckAccessLevel(ProfilePropertyDefinition property, UserInfo accessingUser) + { + var isAdminUser = IsAdminUser(accessingUser); + + //Use properties visible property but admins and hosts can always see the property + var isVisible = property.Visible || isAdminUser; + + if (isVisible && !isAdminUser) + { + switch (property.ProfileVisibility.VisibilityMode) + { + case UserVisibilityMode.FriendsAndGroups: + isVisible = IsUser(accessingUser); + if(!isVisible) + { + //Relationships + foreach (Relationship relationship in property.ProfileVisibility.RelationshipVisibilities) + { + if (user.Social.UserRelationships.Any(userRelationship => + (userRelationship.RelationshipId == relationship.RelationshipId + && accessingUser.UserID == userRelationship.RelatedUserId) + )) + { + isVisible = true; + break; + } + } + //Groups/Roles + if (property.ProfileVisibility.RoleVisibilities.Any(role => accessingUser.IsInRole(role.RoleName))) + { + isVisible = true; + } + } + break; + case UserVisibilityMode.AllUsers: + // property is visible to everyone so do nothing + break; + case UserVisibilityMode.MembersOnly: + // property visible if accessing user is a member + isVisible = IsMember(accessingUser); + break; + case UserVisibilityMode.AdminOnly: + //accessing user not admin user so property is hidden (unless it is the user him/herself) + isVisible = IsUser(accessingUser); + break; + } + } + + return isVisible; + } + + private bool IsAdminUser(UserInfo accessingUser) + { + bool isAdmin = false; + + if (accessingUser != null) + { + //Is Super User? + isAdmin = accessingUser.IsSuperUser; + + if (!isAdmin && user.PortalID != -1) + { + //Is Administrator + if (String.IsNullOrEmpty(administratorRoleName)) + { + PortalInfo ps = new PortalController().GetPortal(user.PortalID); + administratorRoleName = ps.AdministratorRoleName; + } + + isAdmin = accessingUser.IsInRole(administratorRoleName); + } + } + + return isAdmin; + } + + private bool IsMember(UserInfo accessingUser) + { + return (accessingUser != null && accessingUser.UserID != -1); + } + + private bool IsUser(UserInfo accessingUser) + { + return (accessingUser != null && accessingUser.UserID == user.UserID); + } + + #endregion + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope currentScope, ref bool propertyNotFound) + { + if (currentScope >= Scope.DefaultSettings && user != null && user.Profile != null) + { + var profile = user.Profile; + var property = profile.ProfileProperties.Cast() + .SingleOrDefault(p => p.PropertyName.ToLower() == propertyName.ToLower()); + + if(property != null) + { + if (CheckAccessLevel(property, accessingUser)) + { + if (property.PropertyName.ToLower() == "photo") + { + return user.Profile.PhotoURL; + } + else + { + return GetRichValue(property, format, formatProvider); + } + } + } + + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + propertyNotFound = true; + return string.Empty; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + + public static string GetRichValue(ProfilePropertyDefinition property, string formatString, CultureInfo formatProvider) + { + string result = ""; + if (!String.IsNullOrEmpty(property.PropertyValue) || DisplayDataType(property).ToLower() == "image") + { + switch (DisplayDataType(property).ToLower()) + { + case "truefalse": + result = PropertyAccess.Boolean2LocalizedYesNo(Convert.ToBoolean(property.PropertyValue), formatProvider); + break; + case "date": + case "datetime": + if (formatString == string.Empty) + { + formatString = "g"; + } + result = DateTime.Parse(property.PropertyValue, CultureInfo.InvariantCulture).ToString(formatString, formatProvider); + break; + case "integer": + if (formatString == string.Empty) + { + formatString = "g"; + } + result = int.Parse(property.PropertyValue).ToString(formatString, formatProvider); + break; + case "page": + var tabCtrl = new TabController(); + int tabid; + if (int.TryParse(property.PropertyValue, out tabid)) + { + TabInfo tab = tabCtrl.GetTab(tabid, Null.NullInteger, false); + if (tab != null) + { + result = string.Format("{1}", Globals.NavigateURL(tabid), tab.LocalizedTabName); + } + } + break; + case "image": + //File is stored as a FileID + int fileID; + if (Int32.TryParse(property.PropertyValue, out fileID) && fileID > 0) + { + result = Globals.LinkClick(String.Format("fileid={0}", fileID), Null.NullInteger, Null.NullInteger); + } + else + { + result = IconController.IconURL("Spacer","1X1"); + } + break; + case "richtext": + var objSecurity = new PortalSecurity(); + result = PropertyAccess.FormatString(objSecurity.InputFilter(HttpUtility.HtmlDecode(property.PropertyValue), PortalSecurity.FilterFlag.NoScripting), formatString); + break; + default: + result = HttpUtility.HtmlEncode(PropertyAccess.FormatString(property.PropertyValue, formatString)); + break; + } + } + return result; + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Profile/UserProfile.cs b/DNN Platform/Library/Entities/Users/Profile/UserProfile.cs new file mode 100644 index 00000000000..694455005bf --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Profile/UserProfile.cs @@ -0,0 +1,795 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + + +using DotNetNuke.Common.Internal; + +#region Usings + +using System; +using System.ComponentModel; +using System.Globalization; + +using DotNetNuke.Collections; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Services.FileSystem; + +using System.Xml.Serialization; + +#endregion + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Entities.Users +// ReSharper restore CheckNamespace +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserProfile + /// ----------------------------------------------------------------------------- + /// + /// The UserProfile class provides a Business Layer entity for the Users Profile + /// + /// + /// + /// + /// [cnurse] 01/31/2006 documented + /// [cnurse] 02/10/2006 updated with extensible profile enhancment + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserProfile: IIndexable + { + #region Private Constants + + //Name properties + private const string cFirstName = "FirstName"; + private const string cLastName = "LastName"; + private const string cTitle = "Title"; + + //Address Properties + private const string cUnit = "Unit"; + private const string cStreet = "Street"; + private const string cCity = "City"; + private const string cRegion = "Region"; + private const string cCountry = "Country"; + private const string cPostalCode = "PostalCode"; + + //Phone contact + private const string cTelephone = "Telephone"; + private const string cCell = "Cell"; + private const string cFax = "Fax"; + + //Online contact + private const string cWebsite = "Website"; + private const string cIM = "IM"; + + //Preferences + private const string cPhoto = "Photo"; + private const string cTimeZone = "TimeZone"; + private const string cPreferredLocale = "PreferredLocale"; + private const string cPreferredTimeZone = "PreferredTimeZone"; + private const string cBiography = "Biography"; + + #endregion + + #region Private Members + + private bool _IsDirty; + + private UserInfo _user; + + //collection to store all profile properties. + private ProfilePropertyDefinitionCollection _profileProperties; + + #endregion + + public UserProfile() + { + } + + public UserProfile(UserInfo user) + { + _user = user; + } + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Cell/Mobile Phone + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Cell + { + get + { + return GetPropertyValue(cCell); + } + set + { + SetProfileProperty(cCell, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the City part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string City + { + get + { + return GetPropertyValue(cCity); + } + set + { + SetProfileProperty(cCity, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Country part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Country + { + get + { + return GetPropertyValue(cCountry); + } + set + { + SetProfileProperty(cCountry, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Fax Phone + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Fax + { + get + { + return GetPropertyValue(cFax); + } + set + { + SetProfileProperty(cFax, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the First Name + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string FirstName + { + get + { + return GetPropertyValue(cFirstName); + } + set + { + SetProfileProperty(cFirstName, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Full Name + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string FullName + { + get + { + return FirstName + " " + LastName; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Instant Messenger Handle + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string IM + { + get + { + return GetPropertyValue(cIM); + } + set + { + SetProfileProperty(cIM, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets whether the property has been changed + /// + /// + /// [cnurse] 02/10/2006 created + /// + /// ----------------------------------------------------------------------------- + public bool IsDirty + { + get + { + return _IsDirty; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Name + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string LastName + { + get + { + return GetPropertyValue(cLastName); + } + set + { + SetProfileProperty(cLastName, value); + } + } + + public string Photo + { + get + { + return GetPropertyValue(cPhoto); + } + set + { + SetProfileProperty(cPhoto, value); + } + } + + /// + /// property will return a URL for the photourl - if the path contains invalid url characters it will return a fileticket + /// + public string PhotoURL + { + get + { + string photoURL = Globals.ApplicationPath + "/images/no_avatar.gif"; + ProfilePropertyDefinition photoProperty = GetProperty(cPhoto); + if ((photoProperty != null)) + { + UserInfo user = UserController.GetCurrentUserInfo(); + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + + bool isVisible = (user.UserID == _user.UserID); + if (!isVisible) + { + switch (photoProperty.ProfileVisibility.VisibilityMode) + { + case UserVisibilityMode.AllUsers: + isVisible = true; + break; + case UserVisibilityMode.MembersOnly: + isVisible = user.UserID > 0; + break; + case UserVisibilityMode.AdminOnly: + isVisible = user.IsInRole(settings.AdministratorRoleName); + break; + case UserVisibilityMode.FriendsAndGroups: + break; + } + } + if (!string.IsNullOrEmpty(photoProperty.PropertyValue) && isVisible) + { + var fileInfo = FileManager.Instance.GetFile(int.Parse(photoProperty.PropertyValue)); + if ((fileInfo != null)) + { + photoURL = FileManager.Instance.GetUrl(fileInfo); + } + } + } + return photoURL; + } + } + + /// + /// property will return the file path of the photo url (designed to be used when files are loaded via the filesystem e.g for caching) + /// + public string PhotoURLFile + { + get + { + string photoURLFile = Globals.ApplicationPath + "/images/no_avatar.gif"; + ProfilePropertyDefinition photoProperty = GetProperty(cPhoto); + if ((photoProperty != null)) + { + UserInfo user = UserController.GetCurrentUserInfo(); + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + + bool isVisible = (user.UserID == _user.UserID); + if (!isVisible) + { + switch (photoProperty.ProfileVisibility.VisibilityMode) + { + case UserVisibilityMode.AllUsers: + isVisible = true; + break; + case UserVisibilityMode.MembersOnly: + isVisible = user.UserID > 0; + break; + case UserVisibilityMode.AdminOnly: + isVisible = user.IsInRole(settings.AdministratorRoleName); + break; + case UserVisibilityMode.FriendsAndGroups: + break; + } + } + if (!string.IsNullOrEmpty(photoProperty.PropertyValue) && isVisible) + { + var fileInfo = FileManager.Instance.GetFile(int.Parse(photoProperty.PropertyValue)); + if ((fileInfo != null)) + { + string rootFolder=""; + if (fileInfo.PortalId == Null.NullInteger) + { + //Host + rootFolder = Globals.HostPath; + } + else + { + rootFolder = settings.HomeDirectory; + } + photoURLFile = TestableGlobals.Instance.ResolveUrl(rootFolder + fileInfo.Folder + fileInfo.FileName); + } + } + } + return photoURLFile; + } + } + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the PostalCode part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string PostalCode + { + get + { + return GetPropertyValue(cPostalCode); + } + set + { + SetProfileProperty(cPostalCode, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Preferred Locale + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string PreferredLocale + { + get + { + return GetPropertyValue(cPreferredLocale); + } + set + { + SetProfileProperty(cPreferredLocale, value); + } + } + + [XmlIgnore] + public TimeZoneInfo PreferredTimeZone + { + get + { + //First set to Server + TimeZoneInfo _TimeZone = TimeZoneInfo.Local; + + //Next check if there is a Property Setting + string _TimeZoneId = GetPropertyValue(cPreferredTimeZone); + if (!string.IsNullOrEmpty(_TimeZoneId)) + { + _TimeZone = TimeZoneInfo.FindSystemTimeZoneById(_TimeZoneId); + } + //Next check if there is a Portal Setting + else + { + PortalSettings _PortalSettings = PortalController.GetCurrentPortalSettings(); + if (_PortalSettings != null) + { + _TimeZone = _PortalSettings.TimeZone; + } + } + + //still we can't find it or it's somehow set to null + return _TimeZone ?? (TimeZoneInfo.Local); + } + set + { + if (value != null) + { + SetProfileProperty(cPreferredTimeZone, value.Id); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Collection of Profile Properties + /// + /// + /// [cnurse] 02/10/2006 Documented + /// [cnurse] 03/28/2006 Converted to a ProfilePropertyDefinitionCollection + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinitionCollection ProfileProperties + { + get { return _profileProperties ?? (_profileProperties = new ProfilePropertyDefinitionCollection()); } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Region part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Region + { + get + { + return GetPropertyValue(cRegion); + } + set + { + SetProfileProperty(cRegion, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Street part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Street + { + get + { + return GetPropertyValue(cStreet); + } + set + { + SetProfileProperty(cStreet, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Telephone + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Telephone + { + get + { + return GetPropertyValue(cTelephone); + } + set + { + SetProfileProperty(cTelephone, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Title + /// + /// ----------------------------------------------------------------------------- + public string Title + { + get + { + return GetPropertyValue(cTitle); + } + set + { + SetProfileProperty(cTitle, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Unit part of the Address + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Unit + { + get + { + return GetPropertyValue(cUnit); + } + set + { + SetProfileProperty(cUnit, value); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Website + /// + /// + /// [cnurse] 02/10/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string Website + { + get + { + return GetPropertyValue(cWebsite); + } + set + { + SetProfileProperty(cWebsite, value); + } + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Clears the IsDirty Flag + /// + /// + /// [cnurse] 02/29/2006 created + /// + /// ----------------------------------------------------------------------------- + public void ClearIsDirty() + { + _IsDirty = false; + foreach (ProfilePropertyDefinition profProperty in ProfileProperties) + { + profProperty.ClearIsDirty(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Profile Property from the Profile + /// + /// + /// The name of the property to retrieve. + /// + /// [cnurse] 02/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + public ProfilePropertyDefinition GetProperty(string propName) + { + return ProfileProperties[propName]; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Profile Property Value from the Profile + /// + /// + /// The name of the propoerty to retrieve. + /// + /// [cnurse] 02/10/2006 Created + /// + /// ----------------------------------------------------------------------------- + public string GetPropertyValue(string propName) + { + string propValue = Null.NullString; + ProfilePropertyDefinition profileProp = GetProperty(propName); + if (profileProp != null) + { + propValue = profileProp.PropertyValue; + } + return propValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Initialises the Profile with an empty collection of profile properties + /// + /// + /// The name of the property to retrieve. + /// + /// [cnurse] 05/18/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void InitialiseProfile(int portalId) + { + InitialiseProfile(portalId, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Initialises the Profile with an empty collection of profile properties + /// + /// + /// The name of the property to retrieve. + /// A flag that indicates whether the profile default values should be + /// copied to the Profile. + /// + /// [cnurse] 08/04/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void InitialiseProfile(int portalId, bool useDefaults) + { + _profileProperties = ProfileController.GetPropertyDefinitionsByPortal(portalId, true, false); + if (useDefaults) + { + foreach (ProfilePropertyDefinition ProfileProperty in _profileProperties) + { + ProfileProperty.PropertyValue = ProfileProperty.DefaultValue; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets a Profile Property Value in the Profile + /// + /// + /// The name of the propoerty to set. + /// The value of the propoerty to set. + /// + /// [cnurse] 02/10/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void SetProfileProperty(string propName, string propValue) + { + ProfilePropertyDefinition profileProp = GetProperty(propName); + if (profileProp != null) + { + profileProp.PropertyValue = propValue; + + //Set the IsDirty flag + if (profileProp.IsDirty) + { + _IsDirty = true; + } + } + } + + #endregion + + #region Obsolete + + [Obsolete("Deprecated in DNN 6.0. Replaced by PreferredTimeZone.")] + [Browsable(false)] + public int TimeZone + { + get + { + Int32 retValue = Null.NullInteger; + string propValue = GetPropertyValue(cTimeZone); + if (!string.IsNullOrEmpty(propValue)) + { + retValue = int.Parse(propValue); + } + return retValue; + } + set + { + SetProfileProperty(cTimeZone, value.ToString(CultureInfo.InvariantCulture)); + } + } + + public string Biography + { + get + { + return GetPropertyValue(cBiography); + } + set + { + SetProfileProperty(cBiography, value); + } + } + + #endregion + + #region Implement IIndexable + + public object this[string name] + { + get + { + return GetPropertyValue(name); + } + set + { + string stringValue; + if (value is DateTime) + { + var dateValue = (DateTime)value; + stringValue = dateValue.ToString(CultureInfo.InvariantCulture); + } + else + { + stringValue = Convert.ToString(value); + } + SetProfileProperty(name, stringValue); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Data/DataService.cs b/DNN Platform/Library/Entities/Users/Social/Data/DataService.cs new file mode 100644 index 00000000000..856eb28c6d3 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Data/DataService.cs @@ -0,0 +1,150 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Entities.Users.Social.Data +{ + internal class DataService : ComponentBase, IDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + + #region RelationshipType CRUD + + public IDataReader GetAllRelationshipTypes() + { + return _provider.ExecuteReader("GetAllRelationshipTypes"); + } + + public IDataReader GetRelationshipType(int relationshipTypeId) + { + return _provider.ExecuteReader("GetRelationshipType", relationshipTypeId); + } + + public void DeleteRelationshipType(int relationshipTypeId) + { + _provider.ExecuteNonQuery("DeleteRelationshipType", relationshipTypeId); + } + + public int SaveRelationshipType(RelationshipType relationshipType, int createUpdateUserId) + { + return _provider.ExecuteScalar("SaveRelationshipType", relationshipType.RelationshipTypeId, relationshipType.Direction, relationshipType.Name, relationshipType.Description, createUpdateUserId); + } + + #endregion + + #region Relationship CRUD + + public void DeleteRelationship(int relationshipId) + { + _provider.ExecuteNonQuery("DeleteRelationship", relationshipId); + } + + public IDataReader GetRelationship(int relationshipId) + { + return _provider.ExecuteReader("GetRelationship", relationshipId); + } + + public IDataReader GetRelationshipsByUserId(int userId) + { + return _provider.ExecuteReader("GetRelationshipsByUserID", userId); + } + + public IDataReader GetRelationshipsByPortalId(int portalId) + { + return _provider.ExecuteReader("GetRelationshipsByPortalID", portalId); + } + + public int SaveRelationship(Relationship relationship, int createUpdateUserId) + { + return _provider.ExecuteScalar("SaveRelationship", relationship.RelationshipId, relationship.RelationshipTypeId, relationship.Name, relationship.Description, _provider.GetNull(relationship.UserId), _provider.GetNull(relationship.PortalId), relationship.DefaultResponse, createUpdateUserId); + } + + #endregion + + #region UserRelationship CRUD + + public void DeleteUserRelationship(int userRelationshipId) + { + _provider.ExecuteNonQuery("DeleteUserRelationship", userRelationshipId); + } + + public IDataReader GetUserRelationship(int userRelationshipId) + { + return _provider.ExecuteReader("GetUserRelationship", userRelationshipId); + } + + public IDataReader GetUserRelationship(int userId, int relatedUserId, int relationshipId, RelationshipDirection relationshipDirection) + { + return _provider.ExecuteReader("GetUserRelationshipsByMultipleIDs", userId, relatedUserId, relationshipId, relationshipDirection); + } + + public IDataReader GetUserRelationships(int userId) + { + return _provider.ExecuteReader("GetUserRelationships", userId); + } + + public IDataReader GetUserRelationshipsByRelationshipId(int relationshipId) + { + return _provider.ExecuteReader("GetUserRelationshipsByRelationshipID", relationshipId); + } + + public int SaveUserRelationship(UserRelationship userRelationship, int createUpdateUserId) + { + return _provider.ExecuteScalar("SaveUserRelationship", userRelationship.UserRelationshipId, userRelationship.UserId, userRelationship.RelatedUserId, userRelationship.RelationshipId, userRelationship.Status, createUpdateUserId); + } + + #endregion + + #region UserRelationshipPreference CRUD + + public IDataReader GetUserRelationshipPreferenceById(int preferenceId) + { + return _provider.ExecuteReader("GetUserRelationshipPreferenceByID", preferenceId); + } + + public IDataReader GetUserRelationshipPreference(int userId, int relationshipId) + { + return _provider.ExecuteReader("GetUserRelationshipPreference", userId, relationshipId); + } + + public void DeleteUserRelationshipPreference(int preferenceId) + { + _provider.ExecuteNonQuery("DeleteUserRelationshipPreference", preferenceId); + } + + public int SaveUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference, int createUpdateUserId) + { + return _provider.ExecuteScalar("SaveUserRelationshipPreference", userRelationshipPreference.PreferenceId, userRelationshipPreference.UserId, userRelationshipPreference.RelationshipId, userRelationshipPreference.DefaultResponse, createUpdateUserId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/Data/IDataService.cs b/DNN Platform/Library/Entities/Users/Social/Data/IDataService.cs new file mode 100644 index 00000000000..736799f0822 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Data/IDataService.cs @@ -0,0 +1,73 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; + +#endregion + +namespace DotNetNuke.Entities.Users.Social.Data +{ + public interface IDataService + { + #region RelationshipType CRUD + + void DeleteRelationshipType(int relationshipTypeId); + IDataReader GetAllRelationshipTypes(); + IDataReader GetRelationshipType(int relationshipTypeId); + int SaveRelationshipType(RelationshipType relationshipType, int createUpdateUserId); + + #endregion + + #region Relationship CRUD + + void DeleteRelationship(int relationshipId); + IDataReader GetRelationship(int relationshipId); + IDataReader GetRelationshipsByUserId(int userId); + IDataReader GetRelationshipsByPortalId(int portalId); + int SaveRelationship(Relationship relationship, int createUpdateUserId); + + #endregion + + #region UserRelationship CRUD + + void DeleteUserRelationship(int userRelationshipId); + IDataReader GetUserRelationship(int userRelationshipId); + IDataReader GetUserRelationship(int userId, int relatedUserId, int relationshipId, RelationshipDirection relationshipDirection); + IDataReader GetUserRelationships(int userId); + IDataReader GetUserRelationshipsByRelationshipId(int relationshipId); + int SaveUserRelationship(UserRelationship userRelationship, int createUpdateUserId); + + #endregion + + #region UserRelationshipPreference CRUD + + void DeleteUserRelationshipPreference(int preferenceId); + IDataReader GetUserRelationshipPreferenceById(int preferenceId); + IDataReader GetUserRelationshipPreference(int userId, int relationshipId); + int SaveUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference, int createUpdateUserId); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/DefaultRelationshipTypes.cs b/DNN Platform/Library/Entities/Users/Social/DefaultRelationshipTypes.cs new file mode 100644 index 00000000000..37e88070229 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/DefaultRelationshipTypes.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// + /// DefaultRelationshipType defined in system + /// + public enum DefaultRelationshipTypes + { + /// + /// Friends Relationship Type + /// + Friends = 1, + + /// + /// Followers Relationship Type + /// + Followers = 2, + + /// + /// A user-owned custom-list, e.g. my best friends + /// + CustomList = 3 + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/InvalidRelationshipTypeException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/InvalidRelationshipTypeException.cs new file mode 100644 index 00000000000..09e1e1c088b --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/InvalidRelationshipTypeException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class InvalidRelationshipTypeException : Exception + { + public InvalidRelationshipTypeException() + { + } + + public InvalidRelationshipTypeException(string message) + : base(message) + { + } + + public InvalidRelationshipTypeException(string message, Exception inner) + : base(message, inner) + { + } + + public InvalidRelationshipTypeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipBlockedException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipBlockedException.cs new file mode 100644 index 00000000000..9a1a3f08816 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipBlockedException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserRelationshipBlockedException : Exception + { + public UserRelationshipBlockedException() + { + } + + public UserRelationshipBlockedException(string message) + : base(message) + { + } + + public UserRelationshipBlockedException(string message, Exception inner) + : base(message, inner) + { + } + + public UserRelationshipBlockedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipDoesNotExistException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipDoesNotExistException.cs new file mode 100644 index 00000000000..eeba1770ef6 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipDoesNotExistException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserRelationshipDoesNotExistException : Exception + { + public UserRelationshipDoesNotExistException() + { + } + + public UserRelationshipDoesNotExistException(string message) + : base(message) + { + } + + public UserRelationshipDoesNotExistException(string message, Exception inner) + : base(message, inner) + { + } + + public UserRelationshipDoesNotExistException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipExistsException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipExistsException.cs new file mode 100644 index 00000000000..74db82f0256 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipExistsException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserRelationshipExistsException : Exception + { + public UserRelationshipExistsException() + { + } + + public UserRelationshipExistsException(string message) + : base(message) + { + } + + public UserRelationshipExistsException(string message, Exception inner) + : base(message, inner) + { + } + + public UserRelationshipExistsException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForDifferentPortalException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForDifferentPortalException.cs new file mode 100644 index 00000000000..be89da50970 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForDifferentPortalException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserRelationshipForDifferentPortalException : Exception + { + public UserRelationshipForDifferentPortalException() + { + } + + public UserRelationshipForDifferentPortalException(string message) + : base(message) + { + } + + public UserRelationshipForDifferentPortalException(string message, Exception inner) + : base(message, inner) + { + } + + public UserRelationshipForDifferentPortalException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForSameUsersException.cs b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForSameUsersException.cs new file mode 100644 index 00000000000..a58056031ff --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Exceptions/UserRelationshipForSameUsersException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Entities.Users +{ + [Serializable] + public class UserRelationshipForSameUsersException : Exception + { + public UserRelationshipForSameUsersException() + { + } + + public UserRelationshipForSameUsersException(string message) + : base(message) + { + } + + public UserRelationshipForSameUsersException(string message, Exception inner) + : base(message, inner) + { + } + + public UserRelationshipForSameUsersException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/FollowersController.cs b/DNN Platform/Library/Entities/Users/Social/FollowersController.cs new file mode 100644 index 00000000000..9c6aff0be2b --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/FollowersController.cs @@ -0,0 +1,42 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Entities.Users.Social.Internal; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + public class FollowersController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new FollowersControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/FollowersControllerImpl.cs b/DNN Platform/Library/Entities/Users/Social/FollowersControllerImpl.cs new file mode 100644 index 00000000000..c91f40ce8c6 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/FollowersControllerImpl.cs @@ -0,0 +1,118 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.Globalization; + +using DotNetNuke.Common; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Social.Notifications; + +namespace DotNetNuke.Entities.Users.Social.Internal +{ + internal class FollowersControllerImpl : IFollowersController + { + internal const string FollowerRequest = "FollowerRequest"; + internal const string FollowBackRequest = "FollowBackRequest"; + + /// ----------------------------------------------------------------------------- + /// + /// FollowUser - Current User initiates a Follow Request to the Target User + /// + /// UserInfo for Target User + /// UserRelationship object + /// If the Follow Relationship is setup for auto-acceptance (default) at the Portal level, the UserRelationship + /// status is set as Accepted, otherwise it is set as Initiated. + /// + /// ----------------------------------------------------------------------------- + public void FollowUser(UserInfo targetUser) + { + FollowUser(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// FollowUser - Initiating User initiates a Follow Request to the Target User + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// UserRelationship object + /// If the Follow Relationship is setup for auto-acceptance (default) at the Portal level, the UserRelationship + /// status is set as Accepted, otherwise it is set as Initiated. + /// + /// ----------------------------------------------------------------------------- + public void FollowUser(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + + var userRelationship = RelationshipController.Instance.InitiateUserRelationship(initiatingUser, targetUser, + RelationshipController.Instance.GetFollowersRelationshipByPortal(initiatingUser.PortalID)); + + AddFollowerRequestNotification(initiatingUser, targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// UnFollowUser - Current User initiates an UnFollow Request to the Target User + /// + /// UserInfo for Target User + /// ----------------------------------------------------------------------------- + public void UnFollowUser(UserInfo targetUser) + { + var followRelationship = RelationshipController.Instance.GetFollowerRelationship(UserController.GetCurrentUserInfo(), targetUser); + + RelationshipController.Instance.DeleteUserRelationship(followRelationship); + } + + private void AddFollowerRequestNotification(UserInfo initiatingUser, UserInfo targetUser) + { + var notificationType = NotificationsController.Instance.GetNotificationType(IsFollowing(targetUser, initiatingUser) ? FollowerRequest : FollowBackRequest); + var subject = string.Format(Localization.GetString("AddFollowerRequestSubject", Localization.GlobalResourceFile), + initiatingUser.DisplayName); + + var body = string.Format(Localization.GetString("AddFollowerRequestBody", Localization.GlobalResourceFile), + initiatingUser.DisplayName); + + var notification = new Notification + { + NotificationTypeID = notificationType.NotificationTypeId, + Subject = subject, + Body = body, + IncludeDismissAction = true, + Context = initiatingUser.UserID.ToString(CultureInfo.InvariantCulture), + SenderUserID = initiatingUser.UserID + }; + + NotificationsController.Instance.SendNotification(notification, initiatingUser.PortalID, null, new List { targetUser }); + } + + private bool IsFollowing(UserInfo user1, UserInfo user2) + { + UserRelationship userRelationship = RelationshipController.Instance.GetFollowerRelationship(user1, user2); + + return (userRelationship != null && userRelationship.Status == RelationshipStatus.Accepted); + } + + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/FriendsController.cs b/DNN Platform/Library/Entities/Users/Social/FriendsController.cs new file mode 100644 index 00000000000..a2017d94ecd --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/FriendsController.cs @@ -0,0 +1,42 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Entities.Users.Social.Internal; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + public class FriendsController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new FriendsControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/FriendsControllerImpl.cs b/DNN Platform/Library/Entities/Users/Social/FriendsControllerImpl.cs new file mode 100644 index 00000000000..141edb186f7 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/FriendsControllerImpl.cs @@ -0,0 +1,141 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.Globalization; + +using DotNetNuke.Common; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Social.Notifications; + +namespace DotNetNuke.Entities.Users.Social.Internal +{ + internal class FriendsControllerImpl : IFriendsController + { + internal const string FriendRequest = "FriendRequest"; + + /// ----------------------------------------------------------------------------- + /// + /// AcceptFriend - Current User accepts a Friend Request to the Target User + /// + /// UserInfo for Target User + /// UserRelationship object + /// ----------------------------------------------------------------------------- + public void AcceptFriend(UserInfo targetUser) + { + var friendRelationship = RelationshipController.Instance.GetFriendRelationship(UserController.GetCurrentUserInfo(), targetUser); + + RelationshipController.Instance.AcceptUserRelationship(friendRelationship.UserRelationshipId); + NotificationsController.Instance.DeleteNotificationRecipient(NotificationsController.Instance.GetNotificationType(FriendRequest).NotificationTypeId, + friendRelationship.UserRelationshipId.ToString(CultureInfo.InvariantCulture), + UserController.GetCurrentUserInfo().UserID); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddFriend - Current User initiates a Friend Request to the Target User + /// + /// UserInfo for Target User + /// UserRelationship object + /// If the Friend Relationship is setup for auto-acceptance at the Portal level, the UserRelationship + /// status is set as Accepted, otherwise it is set as Initiated. + /// + /// ----------------------------------------------------------------------------- + public void AddFriend(UserInfo targetUser) + { + AddFriend(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddFriend - Initiating User initiates a Friend Request to the Target User + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// UserRelationship object + /// If the Friend Relationship is setup for auto-acceptance at the Portal level, the UserRelationship + /// status is set as Accepted, otherwise it is set as Initiated. + /// + /// ----------------------------------------------------------------------------- + public void AddFriend(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + + var userRelationship = RelationshipController.Instance.InitiateUserRelationship(initiatingUser, targetUser, + RelationshipController.Instance.GetFriendsRelationshipByPortal(initiatingUser.PortalID)); + + AddFriendRequestNotification(initiatingUser, targetUser, userRelationship); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteFriend - Current User deletes a friend relationship with the target User + /// + /// UserInfo for Target User + /// ----------------------------------------------------------------------------- + public void DeleteFriend(UserInfo targetUser) + { + DeleteFriend(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteFriend - Initiating User deletes a friend relationship with the target User + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// ----------------------------------------------------------------------------- + public void DeleteFriend(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + + UserRelationship friend = RelationshipController.Instance.GetUserRelationship(initiatingUser, targetUser, + RelationshipController.Instance.GetFriendsRelationshipByPortal(initiatingUser.PortalID)); + + RelationshipController.Instance.DeleteUserRelationship(friend); + } + + private void AddFriendRequestNotification(UserInfo initiatingUser, UserInfo targetUser, UserRelationship userRelationship) + { + var notificationType = NotificationsController.Instance.GetNotificationType(FriendRequest); + var subject = string.Format(Localization.GetString("AddFriendRequestSubject", Localization.GlobalResourceFile), + initiatingUser.DisplayName); + + var body = string.Format(Localization.GetString("AddFriendRequestBody", Localization.GlobalResourceFile), + initiatingUser.DisplayName); + + var notification = new Notification + { + NotificationTypeID = notificationType.NotificationTypeId, + Subject = subject, + Body = body, + IncludeDismissAction = true, + Context = userRelationship.UserRelationshipId.ToString(CultureInfo.InvariantCulture), + SenderUserID = initiatingUser.UserID + }; + + NotificationsController.Instance.SendNotification(notification, initiatingUser.PortalID, null, new List { targetUser }); + + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/IFollowersController.cs b/DNN Platform/Library/Entities/Users/Social/IFollowersController.cs new file mode 100644 index 00000000000..d338dbc0c2e --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/IFollowersController.cs @@ -0,0 +1,33 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + public interface IFollowersController + { + void FollowUser(UserInfo targetUser); + void FollowUser(UserInfo initiatingUser, UserInfo targetUser); + + void UnFollowUser(UserInfo targetUser); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/IFriendsController.cs b/DNN Platform/Library/Entities/Users/Social/IFriendsController.cs new file mode 100644 index 00000000000..aac208f9966 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/IFriendsController.cs @@ -0,0 +1,37 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + public interface IFriendsController + { + void AcceptFriend(UserInfo targetUser); + + void AddFriend(UserInfo targetUser); + void AddFriend(UserInfo initiatingUser, UserInfo targetUser); + + void DeleteFriend(UserInfo targetUser); + void DeleteFriend(UserInfo initiatingUser, UserInfo targetUser); + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/IRelationshipController.cs b/DNN Platform/Library/Entities/Users/Social/IRelationshipController.cs new file mode 100644 index 00000000000..6eb433fb49d --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/IRelationshipController.cs @@ -0,0 +1,234 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Entities.Users.Social +{ + public interface IRelationshipController + { + #region RelationshipType + + /// ----------------------------------------------------------------------------- + /// + /// Delete RelationshipType + /// + /// RelationshipType + /// ----------------------------------------------------------------------------- + void DeleteRelationshipType(RelationshipType relationshipType); + + /// ----------------------------------------------------------------------------- + /// + /// Get list of All RelationshipTypes defined in system + /// + /// ----------------------------------------------------------------------------- + IList GetAllRelationshipTypes(); + + /// ----------------------------------------------------------------------------- + /// + /// Get RelationshipType By RelationshipTypeId + /// + /// RelationshipTypeId + /// ----------------------------------------------------------------------------- + RelationshipType GetRelationshipType(int relationshipTypeId); + + /// ----------------------------------------------------------------------------- + /// + /// Save RelationshipType + /// + /// RelationshipType object + /// + /// If RelationshipTypeId is -1 (Null.NullIntger), then a new RelationshipType is created, + /// else existing RelationshipType is updated + /// + /// ----------------------------------------------------------------------------- + void SaveRelationshipType(RelationshipType relationshipType); + + #endregion + + #region Relationship + + /// ----------------------------------------------------------------------------- + /// + /// Delete Relationship + /// + /// Relationship + /// ----------------------------------------------------------------------------- + void DeleteRelationship(Relationship relationship); + + /// ----------------------------------------------------------------------------- + /// + /// Get Relationship By RelationshipId + /// + /// RelationshipId + /// ----------------------------------------------------------------------------- + Relationship GetRelationship(int relationshipId); + + /// ----------------------------------------------------------------------------- + /// + /// Get Relationships By UserId + /// + /// UserId + /// ----------------------------------------------------------------------------- + IList GetRelationshipsByUserId(int userId); + + /// ----------------------------------------------------------------------------- + /// + /// Get Relationships By PortalId + /// + /// PortalId + /// ----------------------------------------------------------------------------- + IList GetRelationshipsByPortalId(int portalId); + + /// ----------------------------------------------------------------------------- + /// + /// Save Relationship + /// + /// Relationship object + /// + /// If RelationshipId is -1 (Null.NullIntger), then a new Relationship is created, + /// else existing Relationship is updated + /// + /// ----------------------------------------------------------------------------- + void SaveRelationship(Relationship relationship); + + #endregion + + #region UserRelationship + + /// ----------------------------------------------------------------------------- + /// + /// Delete UserRelationship + /// + /// UserRelationship to delete + /// ----------------------------------------------------------------------------- + void DeleteUserRelationship(UserRelationship userRelationship); + + /// ----------------------------------------------------------------------------- + /// + /// Get UserRelationship By UserRelationshipId + /// + /// UserRelationshipId + /// ----------------------------------------------------------------------------- + UserRelationship GetUserRelationship(int userRelationshipId); + + /// ----------------------------------------------------------------------------- + /// + /// Get UserRelationship by its members + /// + /// User + /// Related User + /// Relationship Object + /// ----------------------------------------------------------------------------- + UserRelationship GetUserRelationship(UserInfo user, UserInfo relatedUser, Relationship relationship); + + /// + /// This method gets a Dictionary of all the relationships that a User belongs to and the members of thase relationships. + /// + /// The user + /// A Dictionary of Lists of UserRelationship, keyed by the Relationship + IList GetUserRelationships(UserInfo user); + + /// ----------------------------------------------------------------------------- + /// + /// Save UserRelationship + /// + /// UserRelationship object + /// + /// If UserRelationshipId is -1 (Null.NullIntger), then a new UserRelationship is created, + /// else existing UserRelationship is updated + /// + /// ----------------------------------------------------------------------------- + void SaveUserRelationship(UserRelationship userRelationship); + + #endregion + + #region UserRelationshipPreference + + /// ----------------------------------------------------------------------------- + /// + /// Delete UserRelationshipPreference + /// + /// UserRelationshipPreference to delete + /// ----------------------------------------------------------------------------- + void DeleteUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference); + + /// ----------------------------------------------------------------------------- + /// + /// Get UserRelationshipPreference By RelationshipTypeId + /// + /// PreferenceId + /// ----------------------------------------------------------------------------- + UserRelationshipPreference GetUserRelationshipPreference(int preferenceId); + + /// ----------------------------------------------------------------------------- + /// + /// Get UserRelationshipPreference By UserId and RelationshipId + /// + /// UserId + /// RelationshipId + /// ----------------------------------------------------------------------------- + UserRelationshipPreference GetUserRelationshipPreference(int userId, int relationshipId); + + /// ----------------------------------------------------------------------------- + /// + /// Save UserRelationshipPreference + /// + /// UserRelationshipPreference object + /// + /// If PreferenceId is -1 (Null.NullIntger), then a new UserRelationshipPreference is created, + /// else existing UserRelationshipPreference is updated + /// + /// ----------------------------------------------------------------------------- + void SaveUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference); + + #endregion + + #region Relationship Business APIs + + UserRelationship InitiateUserRelationship(UserInfo initiatingUser, UserInfo targetUser, Relationship relationship); + + void AcceptUserRelationship(int userRelationshipId); + + void RemoveUserRelationship(int userRelationshipId); + + #endregion + + #region Easy Wrapper APIs + + UserRelationship GetFollowerRelationship(UserInfo targetUser); + UserRelationship GetFollowerRelationship(UserInfo initiatingUser, UserInfo targetUser); + + UserRelationship GetFollowingRelationship(UserInfo targetUser); + UserRelationship GetFollowingRelationship(UserInfo initiatingUser, UserInfo targetUser); + + UserRelationship GetFriendRelationship(UserInfo targetUser); + UserRelationship GetFriendRelationship(UserInfo initiatingUser, UserInfo targetUser); + + #endregion + + void CreateDefaultRelationshipsForPortal(int portalId); + + Relationship GetFriendsRelationshipByPortal(int portalId); + + Relationship GetFollowersRelationshipByPortal(int portalId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/Relationship.cs b/DNN Platform/Library/Entities/Users/Social/Relationship.cs new file mode 100644 index 00000000000..fd61f9a70e1 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/Relationship.cs @@ -0,0 +1,168 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Users.Social; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: Relationship + /// ----------------------------------------------------------------------------- + /// + /// The Relationship class describes the relationships that a user or portal owns. + /// A handful of default Portal-Level Relationships will be be present for every portal (e.g. Friends, Followers, Family). + /// Portal-Level Relationship will have a -1 in UserId field. + /// Any custom User-Level Relationship created by user will also be defined by this class (e.g. My InLaws, Engineering Group). + /// User-Relationship will always have an associcated PortalId. User-Level Relationship will always be tied to a specific Portal. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class Relationship : BaseEntityInfo, IHydratable + { + public Relationship() + { + RelationshipId = -1; + } + + /// + /// RelationshipId - The primary key + /// + [XmlAttribute] + public int RelationshipId { get; set; } + + /// + /// Relationship Name. + /// + [XmlAttribute] + public string Name { get; set; } + + /// + /// Relationship Description. + /// + [XmlAttribute] + public string Description { get; set; } + + /// + /// UserId of the User that owns the Relationship. A value of -1 indicates that it's a Portal-Level Relationship + /// + [XmlAttribute] + public int UserId { get; set; } + + /// + /// PortalId of the User that owns the Relationship. A value of -1 in UserID field indicates that it's a Portal-Level Relationship + /// + [XmlAttribute] + public int PortalId { get; set; } + + /// + /// The ID of the Relationship to which this Relation belongs to (e.g. Friend List or Coworkers) + /// + [XmlAttribute] + public int RelationshipTypeId { get; set; } + + /// + /// Default Relationship Status to be provided to any new Relationship Request + /// + [XmlAttribute] + public RelationshipStatus DefaultResponse { get; set; } + + /// + /// Is this a Portal-Level Relationship + /// + [XmlIgnore] + public bool IsPortalList + { + get + { + return UserId == Null.NullInteger && PortalId >= 0; + } + } + + /// + /// Is this a Host-Level Relationship (very uncommon) + /// + [XmlIgnore] + public bool IsHostList + { + get + { + return UserId == Null.NullInteger && PortalId == Null.NullInteger; + } + } + + /// + /// Is this a USer-Level Relationship + /// + [XmlIgnore] + public bool IsUserList + { + get + { + return UserId > 0 && PortalId >= 0; + } + } + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.RelationshipId; + } + set + { + this.RelationshipId = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.RelationshipId = Convert.ToInt32(dr["RelationshipID"]); + this.UserId = Null.SetNullInteger(dr["UserID"]); + this.PortalId = Null.SetNullInteger(dr["PortalID"]); + this.Name = dr["Name"].ToString(); + this.Description = dr["Description"].ToString(); + this.DefaultResponse = (RelationshipStatus)Convert.ToInt32(dr["DefaultResponse"]); + this.RelationshipTypeId = Convert.ToInt32(dr["RelationshipTypeID"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/RelationshipController.cs b/DNN Platform/Library/Entities/Users/Social/RelationshipController.cs new file mode 100644 index 00000000000..24ee87b021b --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/RelationshipController.cs @@ -0,0 +1,54 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users.Social.Data; +using DotNetNuke.Entities.Users.Social.Internal; +using DotNetNuke.Framework; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// + /// Business Layer to manage Relationships. Also contains CRUD methods. + /// + public class RelationshipController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new RelationshipControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/RelationshipControllerImpl.cs b/DNN Platform/Library/Entities/Users/Social/RelationshipControllerImpl.cs new file mode 100644 index 00000000000..2906a09f725 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/RelationshipControllerImpl.cs @@ -0,0 +1,699 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users.Social.Data; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Social.Notifications; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + internal class RelationshipControllerImpl : IRelationshipController + { + #region Constants + + internal const string FriendRequest = "FriendRequest"; + internal const string FollowerRequest = "FollowerRequest"; + internal const string FollowBackRequest = "FollowBackRequest"; + + #endregion + + #region Private Variables + + private readonly IDataService _dataService; + private readonly IEventLogController _eventLogController; + + #endregion + + #region Constructors + + public RelationshipControllerImpl() : this(DataService.Instance, new EventLogController()) + { + } + + public RelationshipControllerImpl(IDataService dataService, IEventLogController eventLogController) + { + //Argument Contract + Requires.NotNull("dataService", dataService); + Requires.NotNull("eventLogController", eventLogController); + + _dataService = dataService; + _eventLogController = eventLogController; + } + + #endregion + + #region IRelationshipController Implementation + + #region RelationshipType CRUD + + public void DeleteRelationshipType(RelationshipType relationshipType) + { + Requires.NotNull("relationshipType", relationshipType); + + _dataService.DeleteRelationshipType(relationshipType.RelationshipTypeId); + + //log event + string logContent = + string.Format(Localization.GetString("RelationshipType_Deleted", Localization.GlobalResourceFile), + relationshipType.Name, relationshipType.RelationshipTypeId); + AddLog(logContent); + + //clear cache + DataCache.RemoveCache(DataCache.RelationshipTypesCacheKey); + } + + public IList GetAllRelationshipTypes() + { + var cacheArgs = new CacheItemArgs(DataCache.RelationshipTypesCacheKey, + DataCache.RelationshipTypesCacheTimeOut, + DataCache.RelationshipTypesCachePriority); + return CBO.GetCachedObject>(cacheArgs, + c => + CBO.FillCollection( + _dataService.GetAllRelationshipTypes())); + } + + public RelationshipType GetRelationshipType(int relationshipTypeId) + { + return GetAllRelationshipTypes().FirstOrDefault(r => r.RelationshipTypeId == relationshipTypeId); + } + + public void SaveRelationshipType(RelationshipType relationshipType) + { + Requires.NotNull("relationshipType", relationshipType); + + string localizationKey = (relationshipType.RelationshipTypeId == Null.NullInteger) + ? "RelationshipType_Added" + : "RelationshipType_Updated"; + + relationshipType.RelationshipTypeId = _dataService.SaveRelationshipType(relationshipType, + UserController.GetCurrentUserInfo(). + UserID); + + //log event + string logContent = string.Format(Localization.GetString(localizationKey, Localization.GlobalResourceFile), + relationshipType.Name); + AddLog(logContent); + + //clear cache + DataCache.RemoveCache(DataCache.RelationshipTypesCacheKey); + } + + #endregion + + #region Relationship CRUD + + public void DeleteRelationship(Relationship relationship) + { + Requires.NotNull("relationship", relationship); + + _dataService.DeleteRelationship(relationship.RelationshipId); + + //log event + string logContent = + string.Format(Localization.GetString("Relationship_Deleted", Localization.GlobalResourceFile), + relationship.Name, relationship.RelationshipId); + AddLog(logContent); + + //clear cache + ClearRelationshipCache(relationship); + } + + public Relationship GetRelationship(int relationshipId) + { + return CBO.FillCollection(_dataService.GetRelationship(relationshipId)).FirstOrDefault(); + } + + public IList GetRelationshipsByUserId(int userId) + { + return CBO.FillCollection(_dataService.GetRelationshipsByUserId(userId)); + } + + public IList GetRelationshipsByPortalId(int portalId) + { + var pid = portalId; + if (PortalController.IsMemberOfPortalGroup(portalId)) + { + pid = PortalController.GetEffectivePortalId(portalId); + } + var cacheArgs = new CacheItemArgs(string.Format(DataCache.RelationshipByPortalIDCacheKey, pid), + DataCache.RelationshipByPortalIDCacheTimeOut, + DataCache.RelationshipByPortalIDCachePriority, + pid); + return CBO.GetCachedObject>(cacheArgs, + c => + CBO.FillCollection( + _dataService.GetRelationshipsByPortalId( + (int) c.ParamList[0]))); + } + + public void SaveRelationship(Relationship relationship) + { + Requires.NotNull("relationship", relationship); + + string localizationKey = (relationship.RelationshipId == Null.NullInteger) + ? "Relationship_Added" + : "Relationship_Updated"; + + relationship.RelationshipId = _dataService.SaveRelationship(relationship, + UserController.GetCurrentUserInfo().UserID); + + //log event + string logContent = string.Format(Localization.GetString(localizationKey, Localization.GlobalResourceFile), + relationship.Name); + AddLog(logContent); + + //clear cache + ClearRelationshipCache(relationship); + } + + #endregion + + #region UserRelationship CRUD + + public void DeleteUserRelationship(UserRelationship userRelationship) + { + Requires.NotNull("userRelationship", userRelationship); + + _dataService.DeleteUserRelationship(userRelationship.UserRelationshipId); + + //log event + string logContent = + string.Format(Localization.GetString("UserRelationship_Deleted", Localization.GlobalResourceFile), + userRelationship.UserRelationshipId, userRelationship.UserId, + userRelationship.RelatedUserId); + AddLog(logContent); + + //cache clear + ClearUserCache(userRelationship); + } + + public UserRelationship GetUserRelationship(int userRelationshipId) + { + return CBO.FillObject(_dataService.GetUserRelationship(userRelationshipId)); + } + + public UserRelationship GetUserRelationship(UserInfo user, UserInfo relatedUser, Relationship relationship) + { + UserRelationship userRelationship = null; + if (relationship != null) + { + userRelationship = CBO.FillObject(_dataService.GetUserRelationship(user.UserID, relatedUser.UserID, + relationship.RelationshipId, + GetRelationshipType( + relationship.RelationshipTypeId). + Direction)); + } + return userRelationship; + + } + + public IList GetUserRelationships(UserInfo user) + { + return CBO.FillCollection(_dataService.GetUserRelationships(user.UserID)); + } + + public void SaveUserRelationship(UserRelationship userRelationship) + { + Requires.NotNull("userRelationship", userRelationship); + + string localizationKey = (userRelationship.UserRelationshipId == Null.NullInteger) + ? "UserRelationship_Added" + : "UserRelationship_Updated"; + + userRelationship.UserRelationshipId = _dataService.SaveUserRelationship(userRelationship, + UserController.GetCurrentUserInfo(). + UserID); + + //log event + string logContent = string.Format(Localization.GetString(localizationKey, Localization.GlobalResourceFile), + userRelationship.UserRelationshipId, userRelationship.UserId, + userRelationship.RelatedUserId); + AddLog(logContent); + + //cache clear + ClearUserCache(userRelationship); + } + + #endregion + + #region UserRelationshipPreference CRUD + + public void DeleteUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference) + { + Requires.NotNull("userRelationshipPreference", userRelationshipPreference); + + _dataService.DeleteUserRelationshipPreference(userRelationshipPreference.PreferenceId); + + //log event + string logContent = + string.Format( + Localization.GetString("UserRelationshipPreference_Deleted", Localization.GlobalResourceFile), + userRelationshipPreference.PreferenceId, userRelationshipPreference.UserId, + userRelationshipPreference.RelationshipId); + AddLog(logContent); + } + + public UserRelationshipPreference GetUserRelationshipPreference(int preferenceId) + { + return + CBO.FillObject(_dataService.GetUserRelationshipPreferenceById(preferenceId)); + } + + public UserRelationshipPreference GetUserRelationshipPreference(int userId, int relationshipId) + { + return + CBO.FillObject(_dataService.GetUserRelationshipPreference(userId, + relationshipId)); + } + + public void SaveUserRelationshipPreference(UserRelationshipPreference userRelationshipPreference) + { + Requires.NotNull("userRelationshipPreference", userRelationshipPreference); + + string localizationKey = (userRelationshipPreference.PreferenceId == Null.NullInteger) + ? "UserRelationshipPreference_Added" + : "UserRelationshipPreference_Updated"; + + userRelationshipPreference.PreferenceId = + _dataService.SaveUserRelationshipPreference(userRelationshipPreference, + UserController.GetCurrentUserInfo().UserID); + + //log event + string logContent = string.Format(Localization.GetString(localizationKey, Localization.GlobalResourceFile), + userRelationshipPreference.PreferenceId, userRelationshipPreference.UserId, + userRelationshipPreference.RelationshipId); + AddLog(logContent); + } + + #endregion + + #region Relationship Business APIs + + /// ----------------------------------------------------------------------------- + /// + /// Initiate an UserRelationship Request + /// + /// UserInfo of the user initiating the request + /// UserInfo of the user being solicited for initiating the request + /// Relationship to associate this request to (Portal-Level Relationship or User-Level Relationship) + /// + /// If all conditions are met UserRelationship object belonging to Initiating User is returned. + /// + /// + /// Relationship object belonging to the initiating user + /// + /// Target user has Blocked any relationship request from Initiating user + /// Relationship type does not exist + /// ----------------------------------------------------------------------------- + public UserRelationship InitiateUserRelationship(UserInfo initiatingUser, UserInfo targetUser, + Relationship relationship) + { + Requires.NotNull("user1", initiatingUser); + Requires.NotNull("user2", targetUser); + Requires.NotNull("relationship", relationship); + + Requires.PropertyNotNegative("user1", "UserID", initiatingUser.UserID); + Requires.PropertyNotNegative("user2", "UserID", targetUser.UserID); + + Requires.PropertyNotNegative("user1", "PortalID", initiatingUser.PortalID); + Requires.PropertyNotNegative("user2", "PortalID", targetUser.PortalID); + + Requires.PropertyNotNegative("relationship", "RelationshipId", relationship.RelationshipId); + + //cannot be same user + if (initiatingUser.UserID == targetUser.UserID) + { + throw new UserRelationshipForSameUsersException( + Localization.GetExceptionMessage("UserRelationshipForSameUsersError", + "Initiating and Target Users cannot have same UserID '{0}'.", + initiatingUser.UserID)); + } + + //users must be from same portal + if (initiatingUser.PortalID != targetUser.PortalID) + { + throw new UserRelationshipForDifferentPortalException( + Localization.GetExceptionMessage("UserRelationshipForDifferentPortalError", + "Portal ID '{0}' of Initiating User is different from Portal ID '{1}' of Target User.", + initiatingUser.PortalID, targetUser.PortalID)); + } + + //check for existing UserRelationship record + UserRelationship existingRelationship = GetUserRelationship(initiatingUser, targetUser, relationship); + if (existingRelationship != null) + { + throw new UserRelationshipExistsException(Localization.GetExceptionMessage( + "UserRelationshipExistsError", + "Relationship already exists for Initiating User '{0}' Target User '{1}' RelationshipID '{2}'.", + initiatingUser.UserID, targetUser.UserID, relationship.RelationshipId)); + } + + //no existing UserRelationship record found + + + //use Relationship DefaultResponse as status + RelationshipStatus status = relationship.DefaultResponse; + + //check if there is a custom relationship status setting for the user. + //TODO - Is this check only applicable for portal or host list + //if (relationship.IsPortalList || relationship.IsHostList) + { + UserRelationshipPreference preference = GetUserRelationshipPreference(targetUser.UserID, + relationship.RelationshipId); + if (preference != null) + { + status = preference.DefaultResponse; + } + } + + if (status == RelationshipStatus.None) + { + status = RelationshipStatus.Pending; + } + + var userRelationship = new UserRelationship + { + UserRelationshipId = Null.NullInteger, + UserId = initiatingUser.UserID, + RelatedUserId = targetUser.UserID, + RelationshipId = relationship.RelationshipId, + Status = status + }; + + SaveUserRelationship(userRelationship); + + return userRelationship; + } + + /// ----------------------------------------------------------------------------- + /// + /// Accept an existing UserRelationship Request + /// + /// UserRelationshipId of the UserRelationship + /// + /// Method updates the status of the UserRelationship to Accepted. + /// + /// ----------------------------------------------------------------------------- + public void AcceptUserRelationship(int userRelationshipId) + { + ManageUserRelationshipStatus(userRelationshipId, RelationshipStatus.Accepted); + } + + /// ----------------------------------------------------------------------------- + /// + /// Remove an existing UserRelationship Request + /// + /// UserRelationshipId of the UserRelationship + /// + /// UserRelationship record is physically removed. + /// + /// ----------------------------------------------------------------------------- + public void RemoveUserRelationship(int userRelationshipId) + { + UserRelationship userRelationship = VerifyUserRelationshipExist(userRelationshipId); + if (userRelationship != null) + { + DeleteUserRelationship(userRelationship); + } + } + + #endregion + + #region Easy Wrapper APIs + + /// ----------------------------------------------------------------------------- + /// + /// GetFollowerRelationship - Get the UserRelationship between Current User and the Target Users in Follower Relationship + /// + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Follower Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). Follower Relationship can be initited by either of the Users. + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFollowerRelationship(UserInfo targetUser) + { + return GetFollowerRelationship(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFollowerRelationship - Get the UserRelationship between InitiatingUser User and the Target Users in Follower Relationship + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Follower Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). Follower Relationship can be initited by either of the Users. + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFollowerRelationship(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + Requires.NotNull("user2", targetUser); + + return GetUserRelationship(initiatingUser, targetUser, + GetFollowersRelationshipByPortal(initiatingUser.PortalID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFollowingRelationship - Get the UserRelationship between Current User and the Target Users in Following Relationship + /// + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Following Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFollowingRelationship(UserInfo targetUser) + { + return GetFollowingRelationship(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFollowingRelationship - Get the UserRelationship between InitiatingUser User and the Target Users in Following Relationship + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Following Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFollowingRelationship(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + Requires.NotNull("user2", targetUser); + + return GetUserRelationship(targetUser, initiatingUser, + GetFollowersRelationshipByPortal(initiatingUser.PortalID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFriendRelationship - Get the UserRelationship between Current User and the Target Users in Friend Relationship + /// + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Friend Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). Friend Relationship can be initited by either of the Users. + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFriendRelationship(UserInfo targetUser) + { + return GetFriendRelationship(UserController.GetCurrentUserInfo(), targetUser); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetFriendRelationship - Get the UserRelationship between InitiatingUser User and the Target Users in Friend Relationship + /// + /// UserInfo for Initiating User + /// UserInfo for Target User + /// UserRelationship + /// UserRelationship object is returned if a Friend Relationship exists between the two Users. + /// The relation status can be Any (Initiated / Accepted / Blocked). Friend Relationship can be initited by either of the Users. + /// + /// ----------------------------------------------------------------------------- + public UserRelationship GetFriendRelationship(UserInfo initiatingUser, UserInfo targetUser) + { + Requires.NotNull("user1", initiatingUser); + Requires.NotNull("user2", targetUser); + + return GetUserRelationship(initiatingUser, targetUser, + GetFriendsRelationshipByPortal(initiatingUser.PortalID)); + } + + #endregion + + public void CreateDefaultRelationshipsForPortal(int portalId) + { + //create default Friend Relationship + if (GetFriendsRelationshipByPortal(portalId) == null) + { + var friendRelationship = new Relationship + { + RelationshipId = Null.NullInteger, + Name = DefaultRelationshipTypes.Friends.ToString(), + Description = DefaultRelationshipTypes.Friends.ToString(), + PortalId = portalId, + UserId = Null.NullInteger, + DefaultResponse = RelationshipStatus.None, + //default response is None + RelationshipTypeId = (int) DefaultRelationshipTypes.Friends + }; + SaveRelationship(friendRelationship); + } + + //create default Follower Relationship + if (GetFollowersRelationshipByPortal(portalId) == null) + { + var followerRelationship = new Relationship + { + RelationshipId = Null.NullInteger, + Name = DefaultRelationshipTypes.Followers.ToString(), + Description = DefaultRelationshipTypes.Followers.ToString(), + PortalId = portalId, + UserId = Null.NullInteger, + DefaultResponse = RelationshipStatus.Accepted, + //default response is Accepted + RelationshipTypeId = (int) DefaultRelationshipTypes.Followers + }; + SaveRelationship(followerRelationship); + } + } + + public Relationship GetFriendsRelationshipByPortal(int portalId) + { + return GetRelationshipsByPortalId(portalId).FirstOrDefault(re => re.RelationshipTypeId == (int)DefaultRelationshipTypes.Friends); + } + + public Relationship GetFollowersRelationshipByPortal(int portalId) + { + + return GetRelationshipsByPortalId(portalId).FirstOrDefault(re => re.RelationshipTypeId == (int)DefaultRelationshipTypes.Followers); + } + + + #endregion + + #region Private Methods + + private void AddLog(string logContent) + { + _eventLogController.AddLog("Message", logContent, EventLogController.EventLogType.ADMIN_ALERT); + } + + private void ClearRelationshipCache(Relationship relationship) + { + if (relationship.UserId == Null.NullInteger) + { + DataCache.RemoveCache(string.Format(DataCache.RelationshipByPortalIDCacheKey, relationship.PortalId)); + } + } + + private void ClearUserCache(UserRelationship userRelationship) + { + //Get Portal + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + + if (settings != null) + { + //Get User + UserInfo user = UserController.GetUserById(settings.PortalId, userRelationship.UserId); + + if (user != null) + { + DataCache.ClearUserCache(settings.PortalId, user.Username); + } + + //Get Related User + UserInfo relatedUser = UserController.GetUserById(settings.PortalId, userRelationship.RelatedUserId); + + if (relatedUser != null) + { + DataCache.ClearUserCache(settings.PortalId, relatedUser.Username); + } + } + } + + private void ManageUserRelationshipStatus(int userRelationshipId, RelationshipStatus newStatus) + { + UserRelationship userRelationship = VerifyUserRelationshipExist(userRelationshipId); + if (userRelationship == null) + { + return; + } + + //TODO - apply business rules - throw exception if newStatus requested is not allowed + bool save = false; + switch (newStatus) + { + case RelationshipStatus.None: + save = true; + break; + case RelationshipStatus.Pending: + save = true; + break; + case RelationshipStatus.Accepted: + save = true; + break; + } + + if (save) + { + userRelationship.Status = newStatus; + SaveUserRelationship(userRelationship); + } + } + + private UserRelationship VerifyUserRelationshipExist(int userRelationshipId) + { + UserRelationship userRelationship = GetUserRelationship(userRelationshipId); + if (userRelationship == null) + { + throw new UserRelationshipDoesNotExistException( + Localization.GetExceptionMessage("UserRelationshipDoesNotExistError", + "UserRelationshipID '{0}' does not exist.", userRelationshipId)); + } + + return userRelationship; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Social/RelationshipDirection.cs b/DNN Platform/Library/Entities/Users/Social/RelationshipDirection.cs new file mode 100644 index 00000000000..bf832ab89e1 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/RelationshipDirection.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + public enum RelationshipDirection + { + /// + /// One way relationship, e.g. Follower, where user 1 is following user 2, but user 2 is not following user 1. + /// + OneWay = 1, + + /// + /// Two way relationship, e.g. Friend, where user 1 and user 2 are both friends and mutually following each other. + /// + TwoWay = 2 + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/RelationshipStatus.cs b/DNN Platform/Library/Entities/Users/Social/RelationshipStatus.cs new file mode 100644 index 00000000000..70293dfff08 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/RelationshipStatus.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Enum: RelationshipStatus + /// ----------------------------------------------------------------------------- + /// + /// The RelationshipStatus enum describes various UserRelationship statuses. E.g. Accepted, Pending. + /// + /// ----------------------------------------------------------------------------- + public enum RelationshipStatus + { + /// + /// Relationship Request is not present (lack of any other status) + /// + None = 0, + + /// + /// Relationship Request is Initiated. E.g. User 1 sent a friend request to User 2. + /// + Pending = 1, + + /// + /// Relationship Request is Accepted. E.g. User 2 has accepted User 1's friend request. + /// + Accepted = 2, + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/RelationshipType.cs b/DNN Platform/Library/Entities/Users/Social/RelationshipType.cs new file mode 100644 index 00000000000..dc4bce7820f --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/RelationshipType.cs @@ -0,0 +1,111 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: RelationshipType + /// ----------------------------------------------------------------------------- + /// + /// The RelationshipType defines the core relationship types (Friend (2-way), Follower (1-way)) + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class RelationshipType : BaseEntityInfo, IHydratable + { + private int _relationshipTypeId = -1; + + /// + /// RelationshipId - The primary key + /// + [XmlAttribute] + public int RelationshipTypeId + { + get + { + return _relationshipTypeId; + } + set + { + _relationshipTypeId = value; + } + } + + /// + /// Relationship Type Name. + /// + [XmlAttribute] + public string Name { get; set; } + + /// + /// Relationship Description. + /// + [XmlAttribute] + public string Description { get; set; } + + /// + /// Relationship Direction. + /// + [XmlAttribute] + public RelationshipDirection Direction { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.RelationshipTypeId; + } + set + { + this.RelationshipTypeId = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.RelationshipTypeId = Convert.ToInt32(dr["RelationshipTypeID"]); + this.Name = dr["Name"].ToString(); + this.Description = dr["Description"].ToString(); + this.Direction = (RelationshipDirection)Convert.ToInt32(dr["Direction"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/UserRelationship.cs b/DNN Platform/Library/Entities/Users/Social/UserRelationship.cs new file mode 100644 index 00000000000..f1649b7721d --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/UserRelationship.cs @@ -0,0 +1,115 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserRelationship + /// ----------------------------------------------------------------------------- + /// + /// The UserRelationship class defines the membership of the relationship. + /// The user initiating the relationship is UserId. + /// The target of the relationship is RelatedUserId. + /// Status tracks relationship status as Initiated, Approved, Rejected etc. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserRelationship : BaseEntityInfo, IHydratable + { + public UserRelationship() + { + this.UserRelationshipId = -1; + } + + /// + /// UserRelationshipId - The primary key + /// + [XmlAttribute] + public int UserRelationshipId { get; set; } + + /// + /// UserId of the User that owns the relationship + /// + [XmlAttribute] + public int UserId { get; set; } + + /// + /// The UserId of the Related User + /// + [XmlAttribute] + public int RelatedUserId { get; set; } + + /// + /// The ID of the Relationship to which this Relation belongs to (e.g. Friend List or Coworkers) + /// + [XmlAttribute] + public int RelationshipId { get; set; } + + /// + /// The Status of the Relationship (e.g. Initiated, Accepted, Rejected) + /// + [XmlAttribute] + public RelationshipStatus Status { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.UserRelationshipId; + } + set + { + this.UserRelationshipId = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.UserRelationshipId = Convert.ToInt32(dr["UserRelationshipID"]); + this.UserId = Convert.ToInt32(dr["UserID"]); + this.RelatedUserId = Convert.ToInt32(dr["RelatedUserID"]); + this.RelationshipId = Convert.ToInt32(dr["RelationshipID"]); + this.Status = (RelationshipStatus)Convert.ToInt32(dr["Status"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/UserRelationshipPreference.cs b/DNN Platform/Library/Entities/Users/Social/UserRelationshipPreference.cs new file mode 100644 index 00000000000..7d71c2e0aef --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/UserRelationshipPreference.cs @@ -0,0 +1,104 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; +using DotNetNuke.Entities.Modules; +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserRelationshipPreference + /// ----------------------------------------------------------------------------- + /// + /// The UserRelationshipPreference class defines the relationship preference per user + /// The user initiating the relationship is UserId. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserRelationshipPreference : BaseEntityInfo, IHydratable + { + public UserRelationshipPreference() + { + PreferenceId = -1; + } + + /// + /// PreferenceId - The primary key + /// + [XmlAttribute] + public int PreferenceId { get; set; } + + /// + /// UserId of the User that owns the relationship + /// + [XmlAttribute] + public int UserId { get; set; } + + /// + /// The ID of the Relationship to which this Relation belongs to (e.g. Friend List or Coworkers) + /// + [XmlAttribute] + public int RelationshipId { get; set; } + + /// + /// Default Relationship Status to be provided to any new Relationship Request + /// + [XmlAttribute] + public RelationshipStatus DefaultResponse { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return PreferenceId; + } + set + { + PreferenceId = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + PreferenceId = Convert.ToInt32(dr["PreferenceID"]); + UserId = Convert.ToInt32(dr["UserID"]); + RelationshipId = Convert.ToInt32(dr["RelationshipID"]); + DefaultResponse = (RelationshipStatus)Convert.ToInt32(dr["DefaultResponse"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Social/UserSocial.cs b/DNN Platform/Library/Entities/Users/Social/UserSocial.cs new file mode 100644 index 00000000000..2368335cdcf --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Social/UserSocial.cs @@ -0,0 +1,174 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml.Serialization; + +using DotNetNuke.Security.Roles; + +#endregion + +namespace DotNetNuke.Entities.Users.Social +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserSocial + /// ----------------------------------------------------------------------------- + /// + /// The UserSocial is a high-level class describing social details of a user. + /// As an example, this class contains Friends, Followers, Follows lists. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserSocial + { + #region Private + + private IList _relationships; + private IList _userRelationships; + private IList _roles; + private readonly UserInfo _userInfo; + private readonly RoleController _roleController; + + #endregion + + #region Constructor + + public UserSocial(UserInfo userInfo) + { + _roleController = new RoleController(); + _userInfo = userInfo; + } + + #endregion + + #region Public Properties + + /// + /// Returns the Friend Relationship (if it exists with the current User) + /// + public UserRelationship Friend + { + get + { + var _friendsRelationship = RelationshipController.Instance.GetFriendsRelationshipByPortal(_userInfo.PortalID); + var currentUser = UserController.GetCurrentUserInfo(); + return UserRelationships.SingleOrDefault(ur => (ur.RelationshipId == _friendsRelationship.RelationshipId + && + (ur.UserId == _userInfo.UserID && + ur.RelatedUserId == currentUser.UserID + || + (ur.UserId == currentUser.UserID && + ur.RelatedUserId == _userInfo.UserID) + ))); + } + } + + /// + /// Returns the Follower Relationship. Does the user in object Follow the current User (with any status) + /// + public UserRelationship Follower + { + get + { + var _followerRelationship = RelationshipController.Instance.GetFollowersRelationshipByPortal(_userInfo.PortalID); + var currentUser = UserController.GetCurrentUserInfo(); + return UserRelationships.SingleOrDefault(ur => (ur.RelationshipId == _followerRelationship.RelationshipId + && + (ur.UserId == _userInfo.UserID && + ur.RelatedUserId == currentUser.UserID + ))); + } + } + + /// + /// Returns the Following Relationship (if it exists with the current User) + /// + public UserRelationship Following + { + get + { + var _followerRelationship = RelationshipController.Instance.GetFollowersRelationshipByPortal(_userInfo.PortalID); + var currentUser = UserController.GetCurrentUserInfo(); + return UserRelationships.SingleOrDefault(ur => (ur.RelationshipId == _followerRelationship.RelationshipId + && + (ur.UserId == currentUser.UserID && + ur.RelatedUserId == _userInfo.UserID + ))); + } + } + + /// + /// A collection of all the relationships the user is a member of. + /// + public IList UserRelationships + { + get { return _userRelationships ?? (_userRelationships = RelationshipController.Instance.GetUserRelationships(_userInfo)); } + } + + /// + /// List of Relationships for the User + /// + [XmlAttribute] + public IList Relationships + { + get + { + if (_relationships == null) + { + _relationships = RelationshipController.Instance.GetRelationshipsByPortalId(_userInfo.PortalID); + + foreach (var r in RelationshipController.Instance.GetRelationshipsByUserId(_userInfo.UserID)) + { + _relationships.Add(r); + } + } + + return _relationships; + } + } + + /// + /// List of Roles/Groups for the User + /// + [XmlAttribute] + public IList Roles + { + get + { + return _roles ?? (_roles = (_userInfo.PortalID == -1 && _userInfo.UserID == -1) + ? new List() + : _roleController.GetUserRoles(_userInfo, true) + ); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Users/UserController.cs b/DNN Platform/Library/Entities/Users/UserController.cs new file mode 100644 index 00000000000..3fe4264d893 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/UserController.cs @@ -0,0 +1,2128 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.Security; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users.Membership; +using DotNetNuke.Security; +using DotNetNuke.Security.Membership; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Messaging.Data; + +using MembershipProvider = DotNetNuke.Security.Membership.MembershipProvider; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserController + /// ----------------------------------------------------------------------------- + /// + /// The UserController class provides Business Layer methods for Users + /// + /// + /// DotNetNuke user management is base on asp.net membership provider, but the default implementation of these providers + /// do not satisfy the broad set of use cases which we need to support in DotNetNuke. so The dependency of DotNetNuke on the + /// MemberRole (ASP.NET 2 Membership) components will be abstracted into a DotNetNuke Membership Provider, in order to allow + /// developers complete flexibility in implementing alternate Membership approaches. + /// + /// This will allow for a number of enhancements to be added + /// Removal of dependence on the HttpContext + /// Support for Hashed Passwords + /// Support for Password Question and Answer + /// Enforce Password Complexity + /// Password Aging (Expiry) + /// Force Password Update + /// Enable/Disable Password Retrieval/Reset + /// CAPTCHA Support + /// Redirect after registration/login/logout + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class UserController + { + #region Public Properties + + public string DisplayFormat { get; set; } + + public int PortalId { get; set; } + + #endregion + + #region Private Methods + + private static void AddEventLog(int portalId, string username, int userId, string portalName, string ip, UserLoginStatus loginStatus) + { + var objEventLog = new EventLogController(); + + //initialize log record + var objEventLogInfo = new LogInfo(); + var objSecurity = new PortalSecurity(); + objEventLogInfo.AddProperty("IP", ip); + objEventLogInfo.LogPortalID = portalId; + objEventLogInfo.LogPortalName = portalName; + objEventLogInfo.LogUserName = objSecurity.InputFilter(username, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoAngleBrackets | PortalSecurity.FilterFlag.NoMarkup); + objEventLogInfo.LogUserID = userId; + + //create log record + objEventLogInfo.LogTypeKey = loginStatus.ToString(); + objEventLog.AddLog(objEventLogInfo); + } + + private static void AutoAssignUsersToPortalRoles(UserInfo user, int portalId) + { + var roleController = new RoleController(); + + foreach (var role in TestableRoleController.Instance.GetRoles(portalId, role => role.AutoAssignment && role.Status == RoleStatus.Approved)) + { + roleController.AddUserRole(portalId, user.UserID, role.RoleID, Null.NullDate, Null.NullDate); + } + + //Clear the roles cache - so the usercount is correct + TestableRoleController.Instance.ClearRoleCache(portalId); + } + + private static void AutoAssignUsersToRoles(UserInfo user, int portalId) + { + var roleController = new RoleController(); + var portalController = new PortalController(); + var thisPortal = portalController.GetPortal(portalId); + + if (IsMemberOfPortalGroup(portalId)) + { + foreach (var portal in PortalGroupController.Instance.GetPortalsByGroup(thisPortal.PortalGroupID)) + { + if (!user.Membership.Approved && portal.UserRegistration == (int)Globals.PortalRegistrationType.VerifiedRegistration) + { + var role = TestableRoleController.Instance.GetRole(portal.PortalID, r => r.RoleName == "Unverified Users"); + roleController.AddUserRole(portal.PortalID, user.UserID, role.RoleID, Null.NullDate, Null.NullDate); + } + else + { + AutoAssignUsersToPortalRoles(user, portal.PortalID); + } + } + } + else + { + if (!user.Membership.Approved && thisPortal.UserRegistration == (int)Globals.PortalRegistrationType.VerifiedRegistration) + { + var role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleName == "Unverified Users"); + roleController.AddUserRole(portalId, user.UserID, role.RoleID, Null.NullDate, Null.NullDate); + } + else + { + AutoAssignUsersToPortalRoles(user, portalId); + } + } + } + + //TODO - Handle Portal Groups + private static void DeleteUserPermissions(UserInfo user) + { + FolderPermissionController.DeleteFolderPermissionsByUser(user); + + //Delete Module Permissions + ModulePermissionController.DeleteModulePermissionsByUser(user); + + //Delete Tab Permissions + TabPermissionController.DeleteTabPermissionsByUser(user); + } + + private static void FixMemberPortalId(UserInfo user, int portalId) + { + if (user != null) + { + user.PortalID = portalId; + } + } + + private static object GetCachedUserByPortalCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + var username = (string)cacheItemArgs.ParamList[1]; + return MembershipProvider.Instance().GetUserByUserName(portalId, username); + } + + private static int GetEffectivePortalId(int portalId) + { + return PortalController.GetEffectivePortalId(portalId); + } + + private static object GetUserCountByPortalCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + var portalUserCount = MembershipProvider.Instance().GetUserCountByPortal(portalId); + DataCache.SetCache(cacheItemArgs.CacheKey, portalUserCount); + return portalUserCount; + } + + private static Dictionary GetUserLookupDictionary(int portalId) + { + var masterPortalId = GetEffectivePortalId(portalId); + var cacheKey = string.Format(DataCache.UserLookupCacheKey, masterPortalId); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.UserLookupCacheTimeOut, + DataCache.UserLookupCachePriority), (c) => new Dictionary()); + } + + internal static Hashtable GetUserSettings(int portalId, Hashtable settings) + { + portalId = GetEffectivePortalId(portalId); + + if (settings["Column_FirstName"] == null) + { + settings["Column_FirstName"] = false; + } + if (settings["Column_LastName"] == null) + { + settings["Column_LastName"] = false; + } + if (settings["Column_DisplayName"] == null) + { + settings["Column_DisplayName"] = true; + } + if (settings["Column_Address"] == null) + { + settings["Column_Address"] = true; + } + if (settings["Column_Telephone"] == null) + { + settings["Column_Telephone"] = true; + } + if (settings["Column_Email"] == null) + { + settings["Column_Email"] = false; + } + if (settings["Column_CreatedDate"] == null) + { + settings["Column_CreatedDate"] = true; + } + if (settings["Column_LastLogin"] == null) + { + settings["Column_LastLogin"] = false; + } + if (settings["Column_Authorized"] == null) + { + settings["Column_Authorized"] = true; + } + if (settings["Display_Mode"] == null) + { + settings["Display_Mode"] = DisplayMode.All; + } + else + { + settings["Display_Mode"] = (DisplayMode)Convert.ToInt32(settings["Display_Mode"]); + } + if (settings["Display_SuppressPager"] == null) + { + settings["Display_SuppressPager"] = false; + } + if (settings["Records_PerPage"] == null) + { + settings["Records_PerPage"] = 10; + } + if (settings["Profile_DefaultVisibility"] == null) + { + settings["Profile_DefaultVisibility"] = UserVisibilityMode.AdminOnly; + } + else + { + settings["Profile_DefaultVisibility"] = (UserVisibilityMode)Convert.ToInt32(settings["Profile_DefaultVisibility"]); + } + if (settings["Profile_DisplayVisibility"] == null) + { + settings["Profile_DisplayVisibility"] = true; + } + if (settings["Profile_ManageServices"] == null) + { + settings["Profile_ManageServices"] = true; + } + if (settings["Redirect_AfterLogin"] == null) + { + settings["Redirect_AfterLogin"] = -1; + } + if (settings["Redirect_AfterRegistration"] == null) + { + settings["Redirect_AfterRegistration"] = -1; + } + if (settings["Redirect_AfterLogout"] == null) + { + settings["Redirect_AfterLogout"] = -1; + } + if (settings["Security_CaptchaLogin"] == null) + { + settings["Security_CaptchaLogin"] = false; + } + if (settings["Security_CaptchaRegister"] == null) + { + settings["Security_CaptchaRegister"] = false; + } + if (settings["Security_CaptchaRetrivePassword"] == null) + { + settings["Security_CaptchaRetrivePassword"] = false; + } + if (settings["Security_EmailValidation"] == null) + { + settings["Security_EmailValidation"] = Globals.glbEmailRegEx; + } + if (settings["Security_UserNameValidation"] == null) + { + settings["Security_UserNameValidation"] = Globals.glbUserNameRegEx; + } + //Forces a valid profile on registration + if (settings["Security_RequireValidProfile"] == null) + { + settings["Security_RequireValidProfile"] = false; + } + //Forces a valid profile on login + if (settings["Security_RequireValidProfileAtLogin"] == null) + { + settings["Security_RequireValidProfileAtLogin"] = true; + } + if (settings["Security_UsersControl"] == null) + { + var portal = new PortalController().GetPortal(portalId); + + if (portal != null && portal.Users > 1000) + { + settings["Security_UsersControl"] = UsersControl.TextBox; + } + else + { + settings["Security_UsersControl"] = UsersControl.Combo; + } + } + else + { + settings["Security_UsersControl"] = (UsersControl)Convert.ToInt32(settings["Security_UsersControl"]); + } + //Display name format + if (settings["Security_DisplayNameFormat"] == null) + { + settings["Security_DisplayNameFormat"] = ""; + } + if (settings["Registration_RequireConfirmPassword"] == null) + { + settings["Registration_RequireConfirmPassword"] = true; + } + if (settings["Registration_RandomPassword"] == null) + { + settings["Registration_RandomPassword"] = false; + } + if (settings["Registration_UseEmailAsUserName"] == null) + { + settings["Registration_UseEmailAsUserName"] = false; + } + if (settings["Registration_UseAuthProviders"] == null) + { + settings["Registration_UseAuthProviders"] = false; + } + if (settings["Registration_UseProfanityFilter"] == null) + { + settings["Registration_UseProfanityFilter"] = false; + } + if (settings["Registration_RegistrationFormType"] == null) + { + settings["Registration_RegistrationFormType"] = 0; + } + if (settings["Registration_RegistrationFields"] == null) + { + settings["Registration_RegistrationFields"] = String.Empty; + } + if (settings["Registration_ExcludeTerms"] == null) + { + settings["Registration_ExcludeTerms"] = String.Empty; + } + if (settings["Registration_RequireUniqueDisplayName"] == null) + { + settings["Registration_RequireUniqueDisplayName"] = false; + } + return settings; + } + + private static bool IsMemberOfPortalGroup(int portalId) + { + return PortalController.IsMemberOfPortalGroup(portalId); + } + + private static void SendDeleteEmailNotifications(UserInfo user, PortalSettings portalSettings) + { + var message = new Message(); + message.FromUserID = portalSettings.AdministratorId; + message.ToUserID = portalSettings.AdministratorId; + message.Subject = Localization.GetSystemMessage(user.Profile.PreferredLocale, + portalSettings, + "EMAIL_USER_UNREGISTER_SUBJECT", + user, + Localization.GlobalResourceFile, + null, + "", + portalSettings.AdministratorId); + message.Body = Localization.GetSystemMessage(user.Profile.PreferredLocale, + portalSettings, + "EMAIL_USER_UNREGISTER_BODY", + user, + Localization.GlobalResourceFile, + null, + "", + portalSettings.AdministratorId); + message.Status = MessageStatusType.Unread; + Mail.SendEmail(portalSettings.Email, portalSettings.Email, message.Subject, message.Body); + } + + #endregion + + #region Public Methods + /// + /// add new userportal record (used for creating sites with existing user) + /// + /// portalid + /// userid + public static void AddUserPortal(int portalId, int userId) + { + Requires.NotNullOrEmpty("portalId", portalId.ToString()); + Requires.NotNullOrEmpty("userId", userId.ToString()); + + MembershipProvider.Instance().AddUserPortal(portalId,userId); + } + + /// + /// ApproveUser removes the Unverified Users role from the user and adds the auto assigned roles. + /// + /// The user to update. + public static void ApproveUser(UserInfo user) + { + Requires.NotNull("user", user); + + var settings = PortalController.GetCurrentPortalSettings(); + var role = TestableRoleController.Instance.GetRole(settings.PortalId, r => r.RoleName == "Unverified Users"); + + RoleController.DeleteUserRole(user, role, settings, false); + + AutoAssignUsersToRoles(user, settings.PortalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// ChangePassword attempts to change the users password + /// + /// + /// + /// The user to update. + /// The old password. + /// The new password. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public static bool ChangePassword(UserInfo user, string oldPassword, string newPassword) + { + bool retValue; + + //Although we would hope that the caller has already validated the password, + //Validate the new Password + if (ValidatePassword(newPassword)) + { + retValue = MembershipProvider.Instance().ChangePassword(user, oldPassword, newPassword); + + //Update User + user.Membership.UpdatePassword = false; + UpdateUser(user.PortalID, user); + } + else + { + throw new Exception("Invalid Password"); + } + return retValue; + } + + /// + /// overload will validate the token and if valid change the password + /// it does not require an old password as it supports hashed passwords + /// + /// The new password. + /// /// The reset token, typically supplied through a password reset email. + /// A Boolean indicating success or failure. + public static bool ChangePasswordByToken(int portalid, string username, string newPassword, string resetToken) + { + bool retValue; + + Guid resetTokenGuid = new Guid(resetToken); + + var user=GetUserByName(portalid, username); + //if user does not exist return false + if (user==null) + { + return false; + } + //check if the token supplied is the same as the users and is still valid + if (user.PasswordResetToken != resetTokenGuid || user.PasswordResetExpiration < DateTime.Now) + { + return false; + } + + //Although we would hope that the caller has already validated the password, + //Validate the new Password + if (ValidatePassword(newPassword)) + { + retValue = MembershipProvider.Instance().ResetAndChangePassword(user, newPassword); + + //update reset token values to ensure token is 1-time use + user.PasswordResetExpiration = DateTime.MinValue; + user.PasswordResetToken = Guid.NewGuid(); + + //Update User + user.Membership.UpdatePassword = false; + UpdateUser(user.PortalID, user); + } + else + { + throw new Exception("Invalid Password"); + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// ChangePasswordQuestionAndAnswer attempts to change the users password Question + /// and PasswordAnswer + /// + /// + /// + /// The user to update. + /// The password. + /// The new password question. + /// The new password answer. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public static bool ChangePasswordQuestionAndAnswer(UserInfo user, string password, string passwordQuestion, string passwordAnswer) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(user, PortalController.GetCurrentPortalSettings(), GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_UPDATED); + return MembershipProvider.Instance().ChangePasswordQuestionAndAnswer(user, password, passwordQuestion, passwordAnswer); + } + + /// + /// update username in the system + /// works around membershipprovider limitation + /// + /// user id + /// new one + public static void ChangeUsername(int userId, string newUsername) + { + MembershipProvider.Instance().ChangeUsername(userId, newUsername); + } + + public static void CheckInsecurePassword(string username, string password, ref UserLoginStatus loginStatus) + { + if (username == "admin" && (password == "admin" || password == "dnnadmin")) + { + loginStatus = UserLoginStatus.LOGIN_INSECUREADMINPASSWORD; + } + if (username == "host" && (password == "host" || password == "dnnhost")) + { + loginStatus = UserLoginStatus.LOGIN_INSECUREHOSTPASSWORD; + } + } + + /// + /// Copys a user to a different portal. + /// + /// The user to copy + /// The destination portal + /// A flag that indicates whether to merge the original user + /// A flag that indicates whether to delete the original user + public static void CopyUserToPortal(UserInfo user, PortalInfo portal, bool mergeUser, bool deleteUser) + { + //Check if user already exists in target portal + UserInfo targetUser = GetUserById(portal.PortalID, user.UserID); + + if (targetUser == null || !mergeUser) + { + //add user to new portal + AddUserPortal(portal.PortalID, user.UserID); + } + else + { + //Set Portal ID to new Portal + targetUser.PortalID = portal.PortalID; + + //Update Properties + targetUser.DisplayName = (String.IsNullOrEmpty(targetUser.DisplayName)) + ? user.DisplayName + : targetUser.DisplayName; + targetUser.Email = (String.IsNullOrEmpty(targetUser.Email)) + ? user.Email + : targetUser.Email; + targetUser.FirstName = (String.IsNullOrEmpty(targetUser.FirstName)) + ? user.FirstName + : targetUser.FirstName; + targetUser.LastName = (String.IsNullOrEmpty(targetUser.LastName)) + ? user.LastName + : targetUser.LastName; + + //Update the profile + foreach (ProfilePropertyDefinition property in user.Profile.ProfileProperties) + { + if (String.IsNullOrEmpty(targetUser.Profile.GetPropertyValue(property.PropertyName))) + { + targetUser.Profile.SetProfileProperty(property.PropertyName, property.PropertyValue); + } + } + + //Update the user + UpdateUser(targetUser.PortalID, targetUser); + } + + //Delete original user + if (deleteUser) + { + RemoveUser(user); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates a new User in the Data Store + /// + /// + /// The userInfo object to persist to the Database + /// The Created status ot the User + /// ----------------------------------------------------------------------------- + public static UserCreateStatus CreateUser(ref UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + //Create the User + var createStatus = MembershipProvider.Instance().CreateUser(ref user); + + if (createStatus == UserCreateStatus.Success) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(user, PortalController.GetCurrentPortalSettings(), GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_CREATED); + DataCache.ClearPortalCache(portalId, false); + if (!user.IsSuperUser) + { + //autoassign user to portal roles + AutoAssignUsersToRoles(user, portalId); + } + } + + //Reset PortalId + FixMemberPortalId(user, portalId); + return createStatus; + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes all Unauthorized Users for a Portal + /// + /// + /// The Id of the Portal + /// ----------------------------------------------------------------------------- + public static void DeleteUnauthorizedUsers(int portalId) + { + var arrUsers = GetUsers(portalId); + for (int i = 0; i < arrUsers.Count; i++) + { + var user = arrUsers[i] as UserInfo; + if (user != null) + { + if (user.Membership.Approved == false || user.Membership.LastLoginDate == Null.NullDate) + { + DeleteUser(ref user, true, false); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes an existing User from the Data Store + /// + /// + /// The userInfo object to delete from the Database + /// A flag that indicates whether an email notification should be sent + /// A flag that indicates whether the Portal Administrator should be deleted + /// A Boolean value that indicates whether the User was successfully deleted + /// ----------------------------------------------------------------------------- + public static bool DeleteUser(ref UserInfo user, bool notify, bool deleteAdmin) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + var portalSettings = PortalController.GetCurrentPortalSettings(); + + var canDelete = deleteAdmin || (user.UserID != portalSettings.AdministratorId); + + if (canDelete) + { + //Delete Permissions + DeleteUserPermissions(user); + canDelete = MembershipProvider.Instance().DeleteUser(user); + } + if (canDelete) + { + //Obtain PortalSettings from Current Context + var objEventLog = new EventLogController(); + objEventLog.AddLog("Username", user.Username, portalSettings, user.UserID, EventLogController.EventLogType.USER_DELETED); + if (notify && !user.IsSuperUser) + { + //send email notification to portal administrator that the user was removed from the portal + SendDeleteEmailNotifications(user, portalSettings); + } + DataCache.ClearPortalCache(portalId, false); + DataCache.ClearUserCache(portalId, user.Username); + + //also clear current portal's cache if the user is a host user + if (portalSettings.PortalId != portalId) + { + DataCache.ClearPortalCache(portalSettings.PortalId, false); + DataCache.ClearUserCache(portalSettings.PortalId, user.Username); + } + } + + FixMemberPortalId(user, portalId); + + return canDelete; + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes all Users for a Portal + /// + /// + /// The Id of the Portal + /// A flag that indicates whether an email notification should be sent + /// A flag that indicates whether the Portal Administrator should be deleted + /// ----------------------------------------------------------------------------- + public static void DeleteUsers(int portalId, bool notify, bool deleteAdmin) + { + var arrUsers = GetUsers(portalId); + for (int i = 0; i < arrUsers.Count; i++) + { + var objUser = arrUsers[i] as UserInfo; + DeleteUser(ref objUser, notify, deleteAdmin); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates a new random password (Length = Minimum Length + 4) + /// + /// A String + /// ----------------------------------------------------------------------------- + public static string GeneratePassword() + { + return GeneratePassword(MembershipProviderConfig.MinPasswordLength + 4); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates a new random password + /// + /// The length of password to generate. + /// A String + /// ----------------------------------------------------------------------------- + public static string GeneratePassword(int length) + { + return MembershipProvider.Instance().GeneratePassword(length); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetCachedUser retrieves the User from the Cache, or fetches a fresh copy if + /// not in cache or if Cache settings not set to HeavyCaching + /// + /// + /// + /// The Id of the Portal + /// The username of the user being retrieved. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public static UserInfo GetCachedUser(int portalId, string username) + { + //Get the User cache key + var masterPortalId = GetEffectivePortalId(portalId); + var cacheKey = string.Format(DataCache.UserCacheKey, masterPortalId, username); + var user = CBO.GetCachedObject(new CacheItemArgs(cacheKey, DataCache.UserCacheTimeOut, DataCache.UserCachePriority, masterPortalId, username), GetCachedUserByPortalCallBack); + FixMemberPortalId(user, portalId); + + if (user!= null) + { + var lookUp = GetUserLookupDictionary(portalId); + lookUp[user.UserID] = user.Username; + } + + return user; + } + + /// ----------------------------------------------------------------------------- + /// + /// Get the current UserInfo object + /// + /// The current UserInfo if authenticated, oherwise an empty user + /// ----------------------------------------------------------------------------- + public static UserInfo GetCurrentUserInfo() + { + UserInfo user; + if ((HttpContext.Current == null)) + { + if (!Thread.CurrentPrincipal.Identity.IsAuthenticated) + { + return new UserInfo(); + } + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings != null) + { + user = GetCachedUser(portalSettings.PortalId, Thread.CurrentPrincipal.Identity.Name); + return user ?? new UserInfo(); + } + return new UserInfo(); + } + user = (UserInfo)HttpContext.Current.Items["UserInfo"]; + return user ?? new UserInfo(); + } + + public static ArrayList GetDeletedUsers(int portalId) + { + return MembershipProvider.Instance().GetDeletedUsers(GetEffectivePortalId(portalId)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Online Users + /// + /// The Id of the Portal + /// An ArrayList of UserInfo objects + /// ----------------------------------------------------------------------------- + public static ArrayList GetOnlineUsers(int portalId) + { + return MembershipProvider.Instance().GetOnlineUsers(GetEffectivePortalId(portalId)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Current Password Information for the User + /// + /// This method will only return the password if the memberProvider supports + /// and is using a password encryption method that supports decryption. + /// The user whose Password information we are retrieving. + /// The answer to the "user's" password Question. + /// ----------------------------------------------------------------------------- + public static string GetPassword(ref UserInfo user, string passwordAnswer) + { + if (MembershipProviderConfig.PasswordRetrievalEnabled) + { + user.Membership.Password = MembershipProvider.Instance().GetPassword(user, passwordAnswer); + } + else + { + //Throw a configuration exception as password retrieval is not enabled + throw new ConfigurationErrorsException("Password Retrieval is not enabled"); + } + return user.Membership.Password; + } + + public static ArrayList GetUnAuthorizedUsers(int portalId, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUnAuthorizedUsers(GetEffectivePortalId(portalId), includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUnAuthorizedUsers gets all the users of the portal, that are not authorized + /// + /// + /// + /// The Id of the Portal + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUnAuthorizedUsers(int portalId) + { + return GetUnAuthorizedUsers(portalId, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUser retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The Id of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public static UserInfo GetUserById(int portalId, int userId) + { + var lookUp = GetUserLookupDictionary(portalId); + + UserInfo user; + string userName; + if (lookUp.TryGetValue(userId, out userName)) + { + user = GetCachedUser(portalId, userName); + } + else + { + user = MembershipProvider.Instance().GetUser(GetEffectivePortalId(portalId), userId); + FixMemberPortalId(user, portalId); + if (user != null) + { + + lookUp[userId] = user.Username; + + } + } + return user; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByUserName retrieves a User from the DataStore + /// + /// + /// + /// The username of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public static UserInfo GetUserByName(string username) + { + return MembershipProvider.Instance().GetUserByUserName(-1, username); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByUserName retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The username of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public static UserInfo GetUserByName(int portalId, string username) + { + return GetCachedUser(portalId, username); + } + + public static UserInfo GetUserByVanityUrl(int portalId, string vanityUrl) + { + return MembershipProvider.Instance().GetUserByVanityUrl(portalId, vanityUrl); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserCountByPortal gets the number of users in the portal + /// + /// + /// + /// The Id of the Portal + /// The no of users + /// ----------------------------------------------------------------------------- + public static int GetUserCountByPortal(int portalId) + { + portalId = GetEffectivePortalId(portalId); + var cacheKey = string.Format(DataCache.PortalUserCountCacheKey, portalId); + return CBO.GetCachedObject(new CacheItemArgs(cacheKey, DataCache.PortalUserCountCacheTimeOut, DataCache.PortalUserCountCachePriority, portalId), GetUserCountByPortalCallBack); + } + + + /// ----------------------------------------------------------------------------- + /// + /// Retruns a String corresponding to the Registration Status of the User + /// + /// The AUserCreateStatus + /// A String + /// ----------------------------------------------------------------------------- + public static string GetUserCreateStatus(UserCreateStatus userRegistrationStatus) + { + switch (userRegistrationStatus) + { + case UserCreateStatus.DuplicateEmail: + return Localization.GetString("UserEmailExists"); + case UserCreateStatus.InvalidAnswer: + return Localization.GetString("InvalidAnswer"); + case UserCreateStatus.InvalidEmail: + return Localization.GetString("InvalidEmail"); + case UserCreateStatus.InvalidPassword: + string strInvalidPassword = Localization.GetString("InvalidPassword"); + strInvalidPassword = strInvalidPassword.Replace("[PasswordLength]", MembershipProviderConfig.MinPasswordLength.ToString()); + strInvalidPassword = strInvalidPassword.Replace("[NoneAlphabet]", MembershipProviderConfig.MinNonAlphanumericCharacters.ToString()); + return strInvalidPassword; + case UserCreateStatus.PasswordMismatch: + return Localization.GetString("PasswordMismatch"); + case UserCreateStatus.InvalidQuestion: + return Localization.GetString("InvalidQuestion"); + case UserCreateStatus.InvalidUserName: + return Localization.GetString("InvalidUserName"); + case UserCreateStatus.InvalidDisplayName: + return Localization.GetString("InvalidDisplayName"); + case UserCreateStatus.DuplicateDisplayName: + return Localization.GetString("DuplicateDisplayName"); + case UserCreateStatus.UserRejected: + return Localization.GetString("UserRejected"); + case UserCreateStatus.DuplicateUserName: + case UserCreateStatus.UserAlreadyRegistered: + case UserCreateStatus.UsernameAlreadyExists: + return Localization.GetString("UserNameExists"); + case UserCreateStatus.BannedPasswordUsed: + return Localization.GetString("BannedPasswordUsed"); + case UserCreateStatus.ProviderError: + case UserCreateStatus.DuplicateProviderUserKey: + case UserCreateStatus.InvalidProviderUserKey: + return Localization.GetString("RegError"); + default: + throw new ArgumentException("Unknown UserCreateStatus value encountered", "userRegistrationStatus"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Membership Information for the User + /// + /// + /// The user whose Membership information we are retrieving. + /// ----------------------------------------------------------------------------- + public static void GetUserMembership(UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + MembershipProvider.Instance().GetUserMembership(ref user); + FixMemberPortalId(user, portalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Default Settings for the Module + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static Hashtable GetDefaultUserSettings() + { + var portalId = -1; + var portalSettings = PortalController.GetCurrentPortalSettings(); + + if (portalSettings != null) + { + portalId = portalSettings.PortalId; + } + return GetUserSettings(portalId, new Hashtable()); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUser retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The Id of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public UserInfo GetUser(int portalId, int userId) + { + return GetUserById(portalId, userId); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserSettings retrieves the UserSettings from the User + /// + /// + /// + /// The Id of the Portal + /// The Settings Hashtable + /// ----------------------------------------------------------------------------- + public static Hashtable GetUserSettings(int portalId) + { + var settings = GetDefaultUserSettings(); + Dictionary settingsDictionary = (portalId == Null.NullInteger) + ? HostController.Instance.GetSettingsDictionary() + : PortalController.GetPortalSettingsDictionary(GetEffectivePortalId(portalId)); + if (settingsDictionary != null) + { + foreach (KeyValuePair kvp in settingsDictionary) + { + int index = kvp.Key.IndexOf("_"); + if (index > 0) + { + //Get the prefix + string prefix = kvp.Key.Substring(0, index + 1); + switch (prefix) + { + case "Column_": + case "Display_": + case "Profile_": + case "Records_": + case "Redirect_": + case "Registration_": + case "Security_": + switch (kvp.Key) + { + case "Display_Mode": + settings[kvp.Key] = (DisplayMode)Convert.ToInt32(kvp.Value); + break; + case "Profile_DefaultVisibility": + settings[kvp.Key] = (UserVisibilityMode)Convert.ToInt32(kvp.Value); + break; + case "Security_UsersControl": + settings[kvp.Key] = (UsersControl)Convert.ToInt32(kvp.Value); + break; + default: + //update value or add any new values + settings[kvp.Key] = kvp.Value; + break; + } + break; + } + } + } + } + return settings; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal + /// + /// + /// + /// The Id of the Portal + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsers(int portalId) + { + return GetUsers(false, false, portalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal + /// + /// + /// + /// The Id of the Portal + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsers(bool includeDeleted, bool superUsersOnly, int portalId) + { + var totalrecords = -1; + return GetUsers(portalId, -1, -1, ref totalrecords, includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal, by page + /// + /// + /// + /// The Id of the Portal + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsers(portalId, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal, by page + /// + /// + /// + /// The Id of the Portal + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUsers(GetEffectivePortalId(portalId), pageIndex, pageSize, ref totalRecords, includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByEmail gets all the users of the portal whose email matches a provided + /// filter expression + /// + /// + /// + /// The Id of the Portal + /// The email address to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByEmail(portalId, emailToMatch, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByEmail gets all the users of the portal whose email matches a provided + /// filter expression + /// + /// + /// + /// The Id of the Portal + /// The email address to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUsersByEmail(GetEffectivePortalId(portalId), emailToMatch, pageIndex, pageSize, ref totalRecords, includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByProfileProperty gets all the users of the portal whose profile matches + /// the profile property pased as a parameter + /// + /// + /// + /// The Id of the Portal + /// The name of the property being matched. + /// The value of the property being matched. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByProfileProperty(portalId, propertyName, propertyValue, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByProfileProperty gets all the users of the portal whose profile matches + /// the profile property pased as a parameter + /// + /// + /// + /// The Id of the Portal + /// The name of the property being matched. + /// The value of the property being matched. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUsersByProfileProperty(GetEffectivePortalId(portalId), propertyName, propertyValue, pageIndex, pageSize, ref totalRecords, includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByUserName gets all the users of the portal whose username matches a provided + /// filter expression + /// + /// + /// + /// The Id of the Portal + /// The username to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByUserName(portalId, userNameToMatch, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByUserName gets all the users of the portal whose username matches a provided + /// filter expression + /// + /// + /// + /// The Id of the Portal + /// The username to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUsersByUserName(GetEffectivePortalId(portalId), userNameToMatch, pageIndex, pageSize, ref totalRecords, includeDeleted, superUsersOnly); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByDisplayName gets all the users of the portal whose display name matches a provided + /// filter expression + /// + /// + /// + /// The Id of the Portal + /// The display name to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include Deleted Users. + /// Only get super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public static ArrayList GetUsersByDisplayName(int portalId, string nameToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + return MembershipProvider.Instance().GetUsersByDisplayName(GetEffectivePortalId(portalId), nameToMatch, pageIndex, pageSize, ref totalRecords, includeDeleted, superUsersOnly); + } + + public static void RemoveDeletedUsers(int portalId) + { + var arrUsers = GetUsers(true, false, portalId); + + foreach (UserInfo objUser in arrUsers) + { + if (objUser.IsDeleted) + { + RemoveUser(objUser); + } + } + } + + public static bool RemoveUser(UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + //Remove the User + var retValue = MembershipProvider.Instance().RemoveUser(user); + + if ((retValue)) + { + // Obtain PortalSettings from Current Context + var portalSettings = PortalController.GetCurrentPortalSettings(); + + //Log event + var objEventLog = new EventLogController(); + objEventLog.AddLog("Username", user.Username, portalSettings, user.UserID, EventLogController.EventLogType.USER_REMOVED); + + DataCache.ClearPortalCache(portalId, false); + DataCache.ClearUserCache(portalId, user.Username); + } + + //Reset PortalId + FixMemberPortalId(user, portalId); + + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Resets the password for the specified user + /// + /// Resets the user's password + /// The user whose Password information we are resetting. + /// The answer to the "user's" password Question. + /// ----------------------------------------------------------------------------- + public static string ResetPassword(UserInfo user, string passwordAnswer) + { + if (MembershipProviderConfig.PasswordResetEnabled) + { + user.Membership.Password = MembershipProvider.Instance().ResetPassword(user, passwordAnswer); + } + else + { + //Throw a configuration exception as password reset is not enabled + throw new ConfigurationErrorsException("Password Reset is not enabled"); + } + return user.Membership.Password; + } + + public static void ResetPasswordToken(UserInfo user) + { + ResetPasswordToken(user, false); + } + + public static bool ResetPasswordToken(UserInfo user,bool sendEmail) + { + var settings = new MembershipPasswordSettings(user.PortalID); + + user.PasswordResetExpiration = DateTime.Now.AddMinutes(settings.ResetLinkValidity); + user.PasswordResetToken = Guid.NewGuid(); + UpdateUser(user.PortalID, user); + if (sendEmail) + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + return Mail.SendMail(user, MessageType.PasswordReminder, portalSettings) == string.Empty; + } + return true; + } + + public static void ResetPasswordToken(UserInfo user, int minutesValid) + { + user.PasswordResetExpiration = DateTime.Now.AddMinutes(minutesValid); + user.PasswordResetToken = Guid.NewGuid(); + UpdateUser(user.PortalID, user); + } + + public static bool RestoreUser(ref UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + //Restore the User + var retValue = MembershipProvider.Instance().RestoreUser(user); + + if ((retValue)) + { + // Obtain PortalSettings from Current Context + var portalSettings = PortalController.GetCurrentPortalSettings(); + + //Log event + var objEventLog = new EventLogController(); + objEventLog.AddLog("Username", user.Username, portalSettings, user.UserID, EventLogController.EventLogType.USER_RESTORED); + + DataCache.ClearPortalCache(portalId, false); + DataCache.ClearUserCache(portalId, user.Username); + } + + //Reset PortalId + FixMemberPortalId(user, portalId); + + return retValue; + } + + public static string SettingsKey(int portalId) + { + return "UserSettings|" + portalId; + } + + /// ----------------------------------------------------------------------------- + /// + /// Unlocks the User's Account + /// + /// + /// The user whose account is being Unlocked. + /// ----------------------------------------------------------------------------- + public static bool UnLockUser(UserInfo user) + { + int portalId = user.PortalID; + user.PortalID = GetEffectivePortalId(portalId); + + //Unlock the User + var retValue = MembershipProvider.Instance().UnLockUser(user); + DataCache.ClearUserCache(portalId, user.Username); + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Update all the Users Display Names + /// + /// ----------------------------------------------------------------------------- + public void UpdateDisplayNames() + { + int portalId = GetEffectivePortalId(PortalId); + + var arrUsers = GetUsers(PortalId); + foreach (UserInfo objUser in arrUsers) + { + objUser.UpdateDisplayName(DisplayFormat); + UpdateUser(portalId, objUser); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a User + /// + /// The Id of the Portal + /// The use to update + /// + /// + /// ----------------------------------------------------------------------------- + public static void UpdateUser(int portalId, UserInfo user) + { + UpdateUser(portalId, user, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// updates a user + /// + /// the portalid of the user + /// the user object + /// whether or not the update calls the eventlog - the eventlogtype must still be enabled for logging to occur + /// + /// + public static void UpdateUser(int portalId, UserInfo user, bool loggedAction) + { + UpdateUser(portalId, user, loggedAction, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// updates a user + /// + /// the portalid of the user + /// the user object + /// whether or not the update calls the eventlog - the eventlogtype must still be enabled for logging to occur + /// Whether clear cache after update user. + /// + /// This method is used internal because it should be use carefully, or it will caught cache doesn't clear correctly. + /// + internal static void UpdateUser(int portalId, UserInfo user, bool loggedAction, bool clearCache) + { + portalId = GetEffectivePortalId(portalId); + user.PortalID = portalId; + + //Update the User + MembershipProvider.Instance().UpdateUser(user); + if (loggedAction) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(user, PortalController.GetCurrentPortalSettings(), GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_UPDATED); + } + //Remove the UserInfo from the Cache, as it has been modified + if (clearCache) + { + DataCache.ClearUserCache(portalId, user.Username); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates a User's credentials against the Data Store, and sets the Forms Authentication + /// Ticket + /// + /// The Id of the Portal the user belongs to + /// The user name of the User attempting to log in + /// The password of the User attempting to log in + /// The verification code of the User attempting to log in + /// The name of the Portal + /// The IP Address of the user attempting to log in + /// A UserLoginStatus enumeration that indicates the status of the + /// Login attempt. This value is returned by reference. + /// A flag that indicates whether the login credentials + /// should be persisted. + /// The UserInfo object representing a successful login + /// ----------------------------------------------------------------------------- + public static UserInfo UserLogin(int portalId, string username, string password, string verificationCode, string portalName, string ip, ref UserLoginStatus loginStatus, bool createPersistentCookie) + { + portalId = GetEffectivePortalId(portalId); + + loginStatus = UserLoginStatus.LOGIN_FAILURE; + + //Validate the user + var objUser = ValidateUser(portalId, username, password, verificationCode, portalName, ip, ref loginStatus); + if (objUser != null) + { + //Call UserLogin overload + UserLogin(portalId, objUser, portalName, ip, createPersistentCookie); + } + else + { + AddEventLog(portalId, username, Null.NullInteger, portalName, ip, loginStatus); + } + + //return the User object + return objUser; + } + + /// ----------------------------------------------------------------------------- + /// + /// Logs a Validated User in + /// + /// The Id of the Portal the user belongs to + /// The validated User + /// The name of the Portal + /// The IP Address of the user attempting to log in + /// A flag that indicates whether the login credentials should be persisted. + /// ----------------------------------------------------------------------------- + public static void UserLogin(int portalId, UserInfo user, string portalName, string ip, bool createPersistentCookie) + { + portalId = GetEffectivePortalId(portalId); + + AddEventLog(portalId, user.Username, user.UserID, portalName, ip, user.IsSuperUser ? UserLoginStatus.LOGIN_SUPERUSER : UserLoginStatus.LOGIN_SUCCESS); + + //Update User in Database with Last IP used + user.LastIPAddress = ip; + UpdateUser(portalId, user, false); + + //set the forms authentication cookie ( log the user in ) + var security = new PortalSecurity(); + security.SignIn(user, createPersistentCookie); + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates a Password + /// + /// The password to Validate + /// A boolean + /// ----------------------------------------------------------------------------- + public static bool ValidatePassword(string password) + { + var isValid = true; + + //Valid Length + if (password.Length < MembershipProviderConfig.MinPasswordLength) + { + isValid = false; + } + + //Validate NonAlphaChars + var rx = new Regex("[^0-9a-zA-Z]"); + if (rx.Matches(password).Count < MembershipProviderConfig.MinNonAlphanumericCharacters) + { + isValid = false; + } + //Validate Regex + if (!String.IsNullOrEmpty(MembershipProviderConfig.PasswordStrengthRegularExpression) && isValid) + { + rx = new Regex(MembershipProviderConfig.PasswordStrengthRegularExpression); + isValid = rx.IsMatch(password); + } + return isValid; + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates a User's credentials against the Data Store + /// + /// The Id of the Portal the user belongs to + /// The user name of the User attempting to log in + /// The password of the User attempting to log in + /// The verification code of the User attempting to log in + /// The name of the Portal + /// The IP Address of the user attempting to log in + /// A UserLoginStatus enumeration that indicates the status of the + /// Login attempt. This value is returned by reference. + /// The UserInfo object representing a valid user + /// ----------------------------------------------------------------------------- + public static UserInfo ValidateUser(int portalId, string username, string password, string verificationCode, string portalName, string ip, ref UserLoginStatus loginStatus) + { + return ValidateUser(portalId, username, password, "DNN", verificationCode, portalName, ip, ref loginStatus); + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates a User's credentials against the Data Store + /// + /// The Id of the Portal the user belongs to + /// The user name of the User attempting to log in + /// The password of the User attempting to log in + /// The type of Authentication Used + /// The verification code of the User attempting to log in + /// The name of the Portal + /// The IP Address of the user attempting to log in + /// A UserLoginStatus enumeration that indicates the status of the + /// Login attempt. This value is returned by reference. + /// The UserInfo object representing a valid user + /// ----------------------------------------------------------------------------- + public static UserInfo ValidateUser(int portalId, string username, string password, string authType, string verificationCode, string portalName, string ip, ref UserLoginStatus loginStatus) + { + loginStatus = UserLoginStatus.LOGIN_FAILURE; + + //Try and Log the user in + var user = MembershipProvider.Instance().UserLogin(GetEffectivePortalId(portalId), username, password, authType, verificationCode, ref loginStatus); + if (loginStatus == UserLoginStatus.LOGIN_USERLOCKEDOUT || loginStatus == UserLoginStatus.LOGIN_FAILURE || loginStatus == UserLoginStatus.LOGIN_USERNOTAPPROVED) + { + //User Locked Out so log to event log + AddEventLog(portalId, username, Null.NullInteger, portalName, ip, loginStatus); + } + + //Check Default Accounts + if (loginStatus == UserLoginStatus.LOGIN_SUCCESS || loginStatus == UserLoginStatus.LOGIN_SUPERUSER) + { + CheckInsecurePassword(username, password, ref loginStatus); + } + + //Reset portalId + FixMemberPortalId(user, portalId); + + //return the User object + return user; + } + + /// ----------------------------------------------------------------------------- + /// + /// Validates a User's Password and Profile + /// + /// This overload takes a valid User (Credentials check out) and check whether the Password and Profile need updating + /// The Id of the Portal the user belongs to + /// The user attempting to log in + /// Ingore expired user. + /// The UserLoginStatus + /// ----------------------------------------------------------------------------- + public static UserValidStatus ValidateUser(UserInfo objUser, int portalId, bool ignoreExpiring) + { + portalId = GetEffectivePortalId(portalId); + + var validStatus = UserValidStatus.VALID; + + //Check if Password needs to be updated + if (objUser.Membership.UpdatePassword) + { + //Admin has forced password update + validStatus = UserValidStatus.UPDATEPASSWORD; + } + else if (PasswordConfig.PasswordExpiry > 0) + { + var expiryDate = objUser.Membership.LastPasswordChangeDate.AddDays(PasswordConfig.PasswordExpiry); + if (expiryDate < DateTime.Now) + { + //Password Expired + validStatus = UserValidStatus.PASSWORDEXPIRED; + } + else if (expiryDate < DateTime.Now.AddDays(PasswordConfig.PasswordExpiryReminder) && (!ignoreExpiring)) + { + //Password update reminder + validStatus = UserValidStatus.PASSWORDEXPIRING; + } + } + + //Check if Profile needs updating + if (validStatus == UserValidStatus.VALID) + { + var validProfile = Convert.ToBoolean(UserModuleBase.GetSetting(portalId, "Security_RequireValidProfileAtLogin")); + if (validProfile && (!ProfileController.ValidateProfile(portalId, objUser.Profile))) + { + validStatus = UserValidStatus.UPDATEPROFILE; + } + } + return validStatus; + } + + /// + /// Tries to validate a verification code sent after a user is registered in a portal configured to use a verified registration. + /// + /// The verification code. + /// An null string if the verification code has been validated and the user has been approved. An error message otherwise. + /// Thrown when provided verification code has been already used. + /// Thrown when the provided verification code is invalid. + /// Thrown when the user does not exist. + public static void VerifyUser(string verificationCode) + { + Requires.NotNullOrEmpty("verificationCode", verificationCode); + + var portalSecurity = new PortalSecurity(); + var decryptString = portalSecurity.DecryptString(verificationCode, Config.GetDecryptionkey()); + var strings = decryptString.Split('-'); + + if (strings.Length != 2) + { + throw new InvalidVerificationCodeException(); + } + + int portalId; + int userId; + + if (!int.TryParse(strings[0], out portalId) || !int.TryParse(strings[1], out userId)) + { + throw new InvalidVerificationCodeException(); + } + + var user = GetUserById(int.Parse(strings[0]), int.Parse(strings[1])); + + if (user == null) + { + throw new UserDoesNotExistException(); + } + + if (user.Membership.Approved) + { + throw new UserAlreadyVerifiedException(); + } + + if (!user.IsInRole("Unverified Users")) + { + // A Registered User that has been unapproved has managed to get a valid verification code + throw new InvalidVerificationCodeException(); + } + + user.Membership.Approved = true; + UpdateUser(portalId, user); + ApproveUser(user); + } + + #endregion + + #region "Obsoleted Methods, retained for Binary Compatability" + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.CreateUser")] + public int AddUser(UserInfo objUser) + { + CreateUser(ref objUser); + return objUser.UserID; + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.CreateUser")] + public int AddUser(UserInfo objUser, bool addToMembershipProvider) + { + CreateUser(ref objUser); + return objUser.UserID; + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.DeleteUsers")] + public void DeleteAllUsers(int portalId) + { + DeleteUsers(portalId, false, true); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.DeleteUser")] + public bool DeleteUser(int portalId, int userId) + { + var objUser = GetUser(portalId, userId); + + //Call Shared method with notify=true, deleteAdmin=false + return DeleteUser(ref objUser, true, false); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.DeleteUsers")] + public void DeleteUsers(int portalId) + { + DeleteUsers(portalId, true, false); + } + + [Obsolete("Deprecated in DNN 6.1.")] + public static ArrayList FillUserCollection(int portalId, IDataReader dr, ref int totalRecords) + { + //Note: the DataReader returned from this method should contain 2 result sets. The first set + // contains the TotalRecords, that satisfy the filter, the second contains the page + // of data + var arrUsers = new ArrayList(); + try + { + while (dr.Read()) + { + //fill business object + UserInfo user = FillUserInfo(portalId, dr, false); + //add to collection + arrUsers.Add(user); + } + //Get the next result (containing the total) + dr.NextResult(); + + //Get the total no of records from the second result + totalRecords = Globals.GetTotalRecords(ref dr); + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arrUsers; + } + + [Obsolete("Deprecated in DNN 6.1.")] + public static ArrayList FillUserCollection(int portalId, IDataReader dr) + { + //Note: the DataReader returned from this method should contain 2 result sets. The first set + // contains the TotalRecords, that satisfy the filter, the second contains the page + // of data + var arrUsers = new ArrayList(); + try + { + while (dr.Read()) + { + //fill business object + UserInfo user = FillUserInfo(portalId, dr, false); + //add to collection + arrUsers.Add(user); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arrUsers; + } + + [Obsolete("Deprecated in DNN 6.1.")] + public static UserInfo FillUserInfo(int portalId, IDataReader dr, bool closeDataReader) + { + UserInfo objUserInfo = null; + try + { + //read datareader + var bContinue = true; + if (closeDataReader) + { + bContinue = false; + if (dr.Read()) + { + //Ensure the data reader returned is valid + if (string.Equals(dr.GetName(0), "UserID", StringComparison.InvariantCultureIgnoreCase)) + { + bContinue = true; + } + } + } + if (bContinue) + { + objUserInfo = new UserInfo + { + PortalID = portalId, + IsSuperUser = Null.SetNullBoolean(dr["IsSuperUser"]), + IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]), + UserID = Null.SetNullInteger(dr["UserID"]), + FirstName = Null.SetNullString(dr["FirstName"]), + LastName = Null.SetNullString(dr["LastName"]), + RefreshRoles = Null.SetNullBoolean(dr["RefreshRoles"]), + DisplayName = Null.SetNullString(dr["DisplayName"]) + }; + objUserInfo.AffiliateID = Null.SetNullInteger(Null.SetNull(dr["AffiliateID"], objUserInfo.AffiliateID)); + objUserInfo.Username = Null.SetNullString(dr["Username"]); + GetUserMembership(objUserInfo); + objUserInfo.Email = Null.SetNullString(dr["Email"]); + objUserInfo.Membership.UpdatePassword = Null.SetNullBoolean(dr["UpdatePassword"]); + + var schema = dr.GetSchemaTable(); + if (schema != null) + { + if (schema.Select("ColumnName = 'PasswordResetExpiration'").Length > 0) + { + objUserInfo.PasswordResetExpiration = Null.SetNullDateTime(dr["PasswordResetExpiration"]); + } + if (schema.Select("ColumnName = 'PasswordResetToken'").Length > 0) + { + objUserInfo.PasswordResetToken = Null.SetNullGuid(dr["PasswordResetToken"]); + } + } + + if (!objUserInfo.IsSuperUser) + { + objUserInfo.Membership.Approved = Null.SetNullBoolean(dr["Authorised"]); + } + } + } + finally + { + CBO.CloseDataReader(dr, closeDataReader); + } + return objUserInfo; + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUserByName")] + public UserInfo FillUserInfo(int portalID, string username) + { + return GetCachedUser(portalID, username); + } + + [Obsolete("Deprecated in DNN 5.1. This function should be replaced by String.Format(DataCache.UserCacheKey, portalId, username)")] + public string GetCacheKey(int portalID, string username) + { + return string.Format(DataCache.UserCacheKey, portalID, username); + } + + [Obsolete("Deprecated in DNN 5.1. This function should be replaced by String.Format(DataCache.UserCacheKey, portalId, username)")] + public static string CacheKey(int portalId, string username) + { + return string.Format(DataCache.UserCacheKey, portalId, username); + } + + [Obsolete("Deprecated in DNN 5.1. Not needed any longer for due to autohydration")] + public static ArrayList GetUnAuthorizedUsers(int portalId, bool isHydrated) + { + return GetUnAuthorizedUsers(portalId); + } + + [Obsolete("Deprecated in DNN 5.1. Not needed any longer for due to autohydration")] + public static UserInfo GetUser(int portalId, int userId, bool isHydrated) + { + return GetUserById(portalId, userId); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUser retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The Id of the user being retrieved from the Data Store. + /// A flag that determines whether the user is hydrated. + /// A flag that instructs the method to automatically hydrate the roles + /// The User as a UserInfo object + /// + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 5.1. Not needed any longer for single users due to autohydration")] + public static UserInfo GetUser(int portalId, int userId, bool isHydrated, bool hydrateRoles) + { + return GetUserById(portalId, userId); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUserByName")] + public UserInfo GetUserByUsername(int portalID, string username) + { + return GetCachedUser(portalID, username); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUserByName")] + public UserInfo GetUserByUsername(int portalID, string username, bool synchronizeUsers) + { + return GetCachedUser(portalID, username); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUserByName")] + public static UserInfo GetUserByName(int portalId, string username, bool isHydrated) + { + return GetCachedUser(portalId, username); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsers")] + public ArrayList GetSuperUsers() + { + return GetUsers(Null.NullInteger); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsers")] + public ArrayList GetUsers(bool synchronizeUsers, bool progressiveHydration) + { + return GetUsers(Null.NullInteger); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsers")] + public ArrayList GetUsers(int portalId, bool synchronizeUsers, bool progressiveHydration) + { + var totalRecords = -1; + return GetUsers(portalId, -1, -1, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsers")] + public static ArrayList GetUsers(int portalId, bool isHydrated) + { + var totalRecords = -1; + return GetUsers(portalId, -1, -1, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsers")] + public static ArrayList GetUsers(int portalId, bool isHydrated, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsers(portalId, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsersByEmail")] + public static ArrayList GetUsersByEmail(int portalId, bool isHydrated, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByEmail(portalId, emailToMatch, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsersByUserName")] + public static ArrayList GetUsersByUserName(int portalId, bool isHydrated, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByUserName(portalId, userNameToMatch, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.GetUsersByProfileProperty")] + public static ArrayList GetUsersByProfileProperty(int portalId, bool isHydrated, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByProfileProperty(portalId, propertyName, propertyValue, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in DNN 6.1. The method had no implementation !!!")] + public static void SetAuthCookie(string username, bool createPersistentCookie) + { + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.ChangePassword")] + public bool SetPassword(UserInfo objUser, string newPassword) + { + return ChangePassword(objUser, Null.NullString, newPassword); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.ChangePassword")] + public bool SetPassword(UserInfo objUser, string oldPassword, string newPassword) + { + return ChangePassword(objUser, oldPassword, newPassword); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.UnlockUserAccount")] + public void UnlockUserAccount(UserInfo objUser) + { + UnLockUser(objUser); + } + + [Obsolete("Deprecated in DNN 5.1. This function has been replaced by UserController.UpdateUser")] + public void UpdateUser(UserInfo objUser) + { + UpdateUser(objUser.PortalID, objUser); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Users/UserInfo.cs b/DNN Platform/Library/Entities/Users/UserInfo.cs new file mode 100644 index 00000000000..8a443a03224 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/UserInfo.cs @@ -0,0 +1,595 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Security; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.SystemDateTime; +using DotNetNuke.Services.Tokens; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserInfo + /// ----------------------------------------------------------------------------- + /// + /// The UserInfo class provides Business Layer model for Users + /// + /// + /// + /// + /// [cnurse] 12/13/2005 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserInfo : BaseEntityInfo, IPropertyAccess + { + #region Private Members + + private string _administratorRoleName; + private string _fullName; + private UserMembership _membership; + private UserProfile _profile; + private IDictionary _social; + + #endregion + + #region Constructors + + public UserInfo() + { + IsDeleted = Null.NullBoolean; + UserID = Null.NullInteger; + PortalID = Null.NullInteger; + IsSuperUser = Null.NullBoolean; + AffiliateID = Null.NullInteger; + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the AffiliateId for this user + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public int AffiliateID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Display Name + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [SortOrder(3), Required(true), MaxLength(128)] + public string DisplayName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Email Address + /// + /// + /// [cnurse] 02/27/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [SortOrder(4), MaxLength(256), Required(true), RegularExpressionValidator(Globals.glbEmailRegEx)] + public string Email { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the First Name + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [SortOrder(1), MaxLength(50)] + public string FirstName + { + get { return Profile.FirstName; } + set { Profile.FirstName = value; } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the User is deleted + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public bool IsDeleted { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the User is a SuperUser + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public bool IsSuperUser { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last IP address used by user + /// + /// + /// [cnurse] 02/13/2009 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public string LastIPAddress { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Last Name + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [SortOrder(2), MaxLength(50)] + public string LastName + { + get { return Profile.LastName; } + set { Profile.LastName = value; } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Membership object + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public UserMembership Membership + { + get + { + if (_membership == null) + { + _membership = new UserMembership(this); + if ((Username != null) && (!String.IsNullOrEmpty(Username))) + { + UserController.GetUserMembership(this); + } + } + return _membership; + } + set { _membership = value; } + } + + /// + /// gets and sets the token created for resetting passwords + /// + [Browsable(false)] + public Guid PasswordResetToken { get; set; } + + /// + /// gets and sets the datetime that the PasswordResetToken is valid + /// + [Browsable(false)] + public DateTime PasswordResetExpiration { get; set; } + + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the PortalId + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public int PortalID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Profile Object + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public UserProfile Profile + { + get + { + if (_profile == null) + { + _profile = new UserProfile(this); + UserInfo userInfo = this; + ProfileController.GetUserProfile(ref userInfo); + } + return _profile; + } + set { _profile = value; } + } + + [Browsable(false)] + public string[] Roles + { + get + { + return (from r in Social.Roles + where + r.Status == RoleStatus.Approved && + (r.EffectiveDate < DateTime.Now || Null.IsNull(r.EffectiveDate)) && + (r.ExpiryDate > DateTime.Now || Null.IsNull(r.ExpiryDate)) + select r.RoleName + ).ToArray(); + } + set { } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Social property + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public UserSocial Social + { + get + { + if (_social == null) + { + _social = new Dictionary(); + } + + if (!_social.ContainsKey(PortalID)) + { + _social.Add(PortalID, new UserSocial(this)); + } + + return _social[PortalID]; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Id + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public int UserID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Name + /// + /// + /// [cnurse] 02/24/2006 Documented + /// + /// ----------------------------------------------------------------------------- + [SortOrder(0), MaxLength(100), IsReadOnly(true), Required(true)] + public string Username { get; set; } + + public string VanityUrl { get; set; } + + + #region IPropertyAccess Members + + /// + /// Property access, initially provided for TokenReplace + /// + /// Name of the Property + /// format string + /// format provider for numbers, dates, currencies + /// userinfo of the user, who queries the data (used to determine permissions) + /// requested maximum access level, might be restricted due to user level + /// out: flag, if property could be retrieved. + /// current value of the property for this userinfo object + /// + /// 2007-10-20 [sleupold] documented and extended with differenciated access permissions + /// 2007-10-20 [sleupold] role access added (for user himself or admin only). + /// + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope currentScope, ref bool propertyNotFound) + { + Scope internScope; + if (UserID == -1 && currentScope > Scope.Configuration) + { + internScope = Scope.Configuration; //anonymous users only get access to displayname + } + else if (UserID != accessingUser.UserID && !isAdminUser(ref accessingUser) && currentScope > Scope.DefaultSettings) + { + internScope = Scope.DefaultSettings; //registerd users can access username and userID as well + } + else + { + internScope = currentScope; //admins and user himself can access all data + } + string outputFormat = format == string.Empty ? "g" : format; + switch (propertyName.ToLower()) + { + case "verificationcode": + if (internScope < Scope.SystemMessages) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + var ps = new PortalSecurity(); + var code = ps.EncryptString(PortalID + "-" + UserID, Config.GetDecryptionkey()); + return code.Replace("+", ".").Replace("/", "-").Replace("=", "_"); + case "affiliateid": + if (internScope < Scope.SystemMessages) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (AffiliateID.ToString(outputFormat, formatProvider)); + case "displayname": + if (internScope < Scope.Configuration) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return PropertyAccess.FormatString(DisplayName, format); + case "email": + if (internScope < Scope.DefaultSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(Email, format)); + case "firstname": //using profile property is recommended! + if (internScope < Scope.DefaultSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(FirstName, format)); + case "issuperuser": + if (internScope < Scope.Debug) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (IsSuperUser.ToString(formatProvider)); + case "lastname": //using profile property is recommended! + if (internScope < Scope.DefaultSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(LastName, format)); + case "portalid": + if (internScope < Scope.Configuration) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PortalID.ToString(outputFormat, formatProvider)); + case "userid": + if (internScope < Scope.DefaultSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (UserID.ToString(outputFormat, formatProvider)); + case "username": + if (internScope < Scope.DefaultSettings) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(Username, format)); + case "fullname": //fullname is obsolete, it will return DisplayName + if (internScope < Scope.Configuration) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(DisplayName, format)); + case "roles": + if (currentScope < Scope.SystemMessages) + { + propertyNotFound = true; + return PropertyAccess.ContentLocked; + } + return (PropertyAccess.FormatString(string.Join(", ", Roles), format)); + } + propertyNotFound = true; + return string.Empty; + } + + [Browsable(false)] + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + + #endregion + + #region Private Methods + + /// + /// Determine, if accessing user is Administrator + /// + /// userinfo of the user to query + /// true, if user is portal administrator or superuser + /// + /// 2007-10-20 [sleupold] added + /// + private bool isAdminUser(ref UserInfo accessingUser) + { + if (accessingUser == null || accessingUser.UserID == -1) + { + return false; + } + if (String.IsNullOrEmpty(_administratorRoleName)) + { + PortalInfo ps = new PortalController().GetPortal(accessingUser.PortalID); + _administratorRoleName = ps.AdministratorRoleName; + } + return accessingUser.IsInRole(_administratorRoleName) || accessingUser.IsSuperUser; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// IsInRole determines whether the user is in the role passed + /// + /// The role to check + /// A Boolean indicating success or failure. + /// + /// [cnurse] 12/13/2005 created + /// + /// ----------------------------------------------------------------------------- + public bool IsInRole(string role) + { + if (IsSuperUser || role == Globals.glbRoleAllUsersName) + { + return true; + } + if (UserID == Null.NullInteger && role == Globals.glbRoleUnauthUserName) + { + return true; + } + if ("[" + UserID + "]" == role) + { + return true; + } + if (Roles != null) + { + return Roles.Any(s => s == role); + } + return false; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets current time in User's timezone + /// + /// + /// [aprasad] 07/19/2011 Added + /// + /// ----------------------------------------------------------------------------- + public DateTime LocalTime() + { + return LocalTime(SystemDateTime.GetCurrentTimeUtc()); + } + + /// ----------------------------------------------------------------------------- + /// + /// Convert utc time in User's timezone + /// + /// Utc time to convert + /// + /// [aprasad] 07/19/2011 Added + /// + /// ----------------------------------------------------------------------------- + public DateTime LocalTime(DateTime utcTime) + { + if (UserID > Null.NullInteger) + { + return TimeZoneInfo.ConvertTime(utcTime, TimeZoneInfo.Utc, Profile.PreferredTimeZone); + } + return TimeZoneInfo.ConvertTime(utcTime, TimeZoneInfo.Utc, PortalController.GetCurrentPortalSettings().TimeZone); + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateDisplayName updates the displayname to the format provided + /// + /// The format to use + /// + /// [cnurse] 02/21/2007 created + /// + /// ----------------------------------------------------------------------------- + public void UpdateDisplayName(string format) + { + //Replace Tokens + format = format.Replace("[USERID]", UserID.ToString(CultureInfo.InvariantCulture)); + format = format.Replace("[FIRSTNAME]", FirstName); + format = format.Replace("[LASTNAME]", LastName); + format = format.Replace("[USERNAME]", Username); + DisplayName = format; + } + + #endregion + + #region Obsolete + + [Obsolete("Deprecated in DNN 6.2. Roles are no longer stored in a cookie")] + public void ClearRoles() { } + + [Browsable(false), Obsolete("Deprecated in DNN 5.1. This property has been deprecated in favour of Display Name")] + public string FullName + { + get + { + if (String.IsNullOrEmpty(_fullName)) + { + _fullName = FirstName + " " + LastName; + } + return _fullName; + } + set { _fullName = value; } + } + + [Browsable(false)] + [Obsolete("Deprecated in DNN 6.2. Roles are no longer stored in a cookie so this property is no longer neccessary")] + public bool RefreshRoles { get; set; } + + #endregion + } +} diff --git a/DNN Platform/Library/Entities/Users/UserRoleInfo.cs b/DNN Platform/Library/Entities/Users/UserRoleInfo.cs new file mode 100644 index 00000000000..8c056af5164 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/UserRoleInfo.cs @@ -0,0 +1,90 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security.Roles; + + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserRoleInfo + /// ----------------------------------------------------------------------------- + /// + /// The UserRoleInfo class provides Business Layer model for a User/Role + /// + /// + /// + /// + /// [cnurse] 01/03/2006 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class UserRoleInfo : RoleInfo + { + #region Public Properties + + public int UserRoleID { get; set; } + + public int UserID { get; set; } + + public string FullName { get; set; } + + public string Email { get; set; } + + public DateTime EffectiveDate { get; set; } + + public DateTime ExpiryDate { get; set; } + + public bool IsOwner { get; set; } + + public bool IsTrialUsed { get; set; } + + public bool Subscribed { get; set; } + + #endregion + + public override void Fill(IDataReader dr) + { + //Fill base class properties + base.Fill(dr); + + //Fill this class properties + UserRoleID = Null.SetNullInteger(dr["UserRoleID"]); + UserID = Null.SetNullInteger(dr["UserID"]); + FullName = Null.SetNullString(dr["DisplayName"]); + Email = Null.SetNullString(dr["Email"]); + EffectiveDate = Null.SetNullDateTime(dr["EffectiveDate"]); + ExpiryDate = Null.SetNullDateTime(dr["ExpiryDate"]); + IsOwner = Null.SetNullBoolean(dr["IsOwner"]); + IsTrialUsed = Null.SetNullBoolean(dr["IsTrialUsed"]); + if (UserRoleID > Null.NullInteger) + { + Subscribed = true; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/UserTime.cs b/DNN Platform/Library/Entities/Users/UserTime.cs new file mode 100644 index 00000000000..83f6b018656 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/UserTime.cs @@ -0,0 +1,117 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Services.SystemDateTime; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + public class UserTime + { + [Obsolete("Deprecated in DNN 6.0.1. Replaced by UserInfo.LocalTime")] + public DateTime CurrentUserTime + { + get + { + HttpContext context = HttpContext.Current; + //Obtain PortalSettings from Current Context + PortalSettings objSettings = PortalController.GetCurrentPortalSettings(); + if (!context.Request.IsAuthenticated) + { + return TimeZoneInfo.ConvertTime(SystemDateTime.GetCurrentTimeUtc(), TimeZoneInfo.Utc, objSettings.TimeZone); + } + else + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + return TimeZoneInfo.ConvertTime(SystemDateTime.GetCurrentTimeUtc(), TimeZoneInfo.Utc, objUserInfo.Profile.PreferredTimeZone); + } + } + } + + [Obsolete("Deprecated in DNN 6.0.")] + public double ClientToServerTimeZoneFactor + { + get + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + return FromClientToServerFactor(objUserInfo.Profile.PreferredTimeZone.BaseUtcOffset.TotalMinutes, portalSettings.TimeZone.BaseUtcOffset.TotalMinutes); + } + } + + [Obsolete("Deprecated in DNN 6.0.")] + public double ServerToClientTimeZoneFactor + { + get + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + return FromServerToClientFactor(objUserInfo.Profile.PreferredTimeZone.BaseUtcOffset.TotalMinutes, portalSettings.TimeZone.BaseUtcOffset.TotalMinutes); + } + } + + [Obsolete("Deprecated in DNN 6.0.")] + public DateTime ConvertToUserTime(DateTime dt, double clientTimeZone) + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + return dt.AddMinutes(FromClientToServerFactor(clientTimeZone, portalSettings.TimeZone.BaseUtcOffset.TotalMinutes)); + } + + [Obsolete("Deprecated in DNN 6.0.")] + public DateTime ConvertToServerTime(DateTime dt, double clientTimeZone) + { + //Obtain PortalSettings from Current Context + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + return dt.AddMinutes(FromServerToClientFactor(clientTimeZone, portalSettings.TimeZone.BaseUtcOffset.TotalMinutes)); + } + + [Obsolete("Deprecated in DNN 6.0.1. Replaced by UserInfo.LocalTime")] + public static DateTime CurrentTimeForUser(UserInfo userInfo) + { + if (userInfo == null || userInfo.UserID == -1) + { + //Obtain PortalSettings from Current Context + PortalSettings objSettings = PortalController.GetCurrentPortalSettings(); + return TimeZoneInfo.ConvertTime(SystemDateTime.GetCurrentTimeUtc(), TimeZoneInfo.Utc, objSettings.TimeZone); + } + else + { + return TimeZoneInfo.ConvertTime(SystemDateTime.GetCurrentTimeUtc(), TimeZoneInfo.Utc, userInfo.Profile.PreferredTimeZone); + } + } + + private double FromClientToServerFactor(double Client, double Server) + { + return Client - Server; + } + + private double FromServerToClientFactor(double Client, double Server) + { + return Server - Client; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/UserVisibilityMode.cs b/DNN Platform/Library/Entities/Users/UserVisibilityMode.cs new file mode 100644 index 00000000000..7200b5a3b87 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/UserVisibilityMode.cs @@ -0,0 +1,33 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Entities.Users +{ + public enum UserVisibilityMode + { + AllUsers = 0, + MembersOnly = 1, + AdminOnly = 2, + FriendsAndGroups = 3 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Entities/Users/Users Online/AnonymousUserInfo.cs b/DNN Platform/Library/Entities/Users/Users Online/AnonymousUserInfo.cs new file mode 100644 index 00000000000..f4bb890376c --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Users Online/AnonymousUserInfo.cs @@ -0,0 +1,68 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: PurgeUsersOnline + /// ----------------------------------------------------------------------------- + /// + /// The AnonymousUserInfo class provides an Entity for an anonymous user + /// + /// + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class AnonymousUserInfo : BaseUserInfo + { + private string _UserID; + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Id for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string UserID + { + get + { + return _UserID; + } + set + { + _UserID = value; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Users Online/BaseUserInfo.cs b/DNN Platform/Library/Entities/Users/Users Online/BaseUserInfo.cs new file mode 100644 index 00000000000..0c3e4b76fef --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Users Online/BaseUserInfo.cs @@ -0,0 +1,131 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: BaseUserInfo + /// ----------------------------------------------------------------------------- + /// + /// The BaseUserInfo class provides a base Entity for an online user + /// + /// + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public abstract class BaseUserInfo + { + private DateTime _CreationDate; + private DateTime _LastActiveDate; + private int _PortalID; + private int _TabID; + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the PortalId for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public int PortalID + { + get + { + return _PortalID; + } + set + { + _PortalID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the TabId for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public int TabID + { + get + { + return _TabID; + } + set + { + _TabID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the CreationDate for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime CreationDate + { + get + { + return _CreationDate; + } + set + { + _CreationDate = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the LastActiveDate for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DateTime LastActiveDate + { + get + { + return _LastActiveDate; + } + set + { + _LastActiveDate = value; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Users Online/OnlineUserInfo.cs b/DNN Platform/Library/Entities/Users/Users Online/OnlineUserInfo.cs new file mode 100644 index 00000000000..4dce6390a7c --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Users Online/OnlineUserInfo.cs @@ -0,0 +1,68 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: OnlineUserInfo + /// ----------------------------------------------------------------------------- + /// + /// The OnlineUserInfo class provides an Entity for an online user + /// + /// + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class OnlineUserInfo : BaseUserInfo + { + private int _UserID; + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Id for this online user + /// + /// + /// [cnurse] 03/14/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public int UserID + { + get + { + return _UserID; + } + set + { + _UserID = value; + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Users Online/PurgeUsersOnline.cs b/DNN Platform/Library/Entities/Users/Users Online/PurgeUsersOnline.cs new file mode 100644 index 00000000000..2c98e0e61b9 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Users Online/PurgeUsersOnline.cs @@ -0,0 +1,119 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: PurgeUsersOnline + /// ----------------------------------------------------------------------------- + /// + /// The PurgeUsersOnline class provides a Scheduler for purging the Users Online + /// data + /// + /// + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public class PurgeUsersOnline : SchedulerClient + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs a PurgeUsesOnline SchedulerClient + /// + /// + /// + /// A SchedulerHistiryItem + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public PurgeUsersOnline(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateUsersOnline updates the Users Online information + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + private void UpdateUsersOnline() + { + var objUserOnlineController = new UserOnlineController(); + + //Is Users Online Enabled? + if ((objUserOnlineController.IsEnabled())) + { + //Update the Users Online records from Cache + Status = "Updating Users Online"; + objUserOnlineController.UpdateUsersOnline(); + Status = "Update Users Online Successfully"; + ScheduleHistoryItem.Succeeded = true; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// DoWork does th4 Scheduler work + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); //OPTIONAL + UpdateUsersOnline(); + ScheduleHistoryItem.Succeeded = true; //REQUIRED + ScheduleHistoryItem.AddLogNote("UsersOnline purge completed."); + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + ScheduleHistoryItem.AddLogNote("UsersOnline purge failed." + exc); + + //notification that we have errored + Errored(ref exc); + + //log the exception + Exceptions.LogException(exc); + } + } + } +} diff --git a/DNN Platform/Library/Entities/Users/Users Online/UserOnlineController.cs b/DNN Platform/Library/Entities/Users/Users Online/UserOnlineController.cs new file mode 100644 index 00000000000..a9ff7a73073 --- /dev/null +++ b/DNN Platform/Library/Entities/Users/Users Online/UserOnlineController.cs @@ -0,0 +1,337 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Membership; + +#endregion + +namespace DotNetNuke.Entities.Users +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Users + /// Class: UserOnlineController + /// ----------------------------------------------------------------------------- + /// + /// The UserOnlineController class provides Business Layer methods for Users Online + /// + /// + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public class UserOnlineController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (UserOnlineController)); + private static readonly MembershipProvider memberProvider = MembershipProvider.Instance(); + + /// ----------------------------------------------------------------------------- + /// + /// Clears the cached Users Online Information + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public void ClearUserList() + { + string key = "OnlineUserList"; + DataCache.RemoveCache(key); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Online time window + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public int GetOnlineTimeWindow() + { + return Host.Host.UsersOnlineTimeWindow; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the cached Users Online Information + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public Hashtable GetUserList() + { + string key = "OnlineUserList"; + var userList = (Hashtable) DataCache.GetCache(key); + if ((userList == null)) + { + //Do we have the Hashtable? + userList = new Hashtable(); + DataCache.SetCache(key, userList); + } + return userList; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Users Online functionality is enabled + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public bool IsEnabled() + { + return Host.Host.EnableUsersOnline; + } + + /// ----------------------------------------------------------------------------- + /// + /// Determines whether a User is online + /// + /// + /// [cnurse] 03/14/2006 created + /// + /// ----------------------------------------------------------------------------- + public bool IsUserOnline(UserInfo user) + { + bool isOnline = false; + if (IsEnabled()) + { + isOnline = memberProvider.IsUserOnline(user); + } + return isOnline; + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets the cached Users Online Information + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public void SetUserList(Hashtable userList) + { + string key = "OnlineUserList"; + DataCache.SetCache(key, userList); + } + + /// ----------------------------------------------------------------------------- + /// + /// Tracks an Anonymous User + /// + /// An HttpContext Object + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + private void TrackAnonymousUser(HttpContext context) + { + string cookieName = "DotNetNukeAnonymous"; + var portalSettings = (PortalSettings) context.Items["PortalSettings"]; + if (portalSettings == null) + { + return; + } + AnonymousUserInfo user; + Hashtable userList = GetUserList(); + string userID; + + //Check if the Tracking cookie exists + HttpCookie cookie = context.Request.Cookies[cookieName]; + //Track Anonymous User + if ((cookie == null)) + { + //Create a temporary userId + userID = Guid.NewGuid().ToString(); + + //Create a new cookie + cookie = new HttpCookie(cookieName); + cookie.Value = userID; + cookie.Expires = DateTime.Now.AddMinutes(20); + context.Response.Cookies.Add(cookie); + + //Create a user + user = new AnonymousUserInfo(); + user.UserID = userID; + user.PortalID = portalSettings.PortalId; + user.TabID = portalSettings.ActiveTab.TabID; + user.CreationDate = DateTime.Now; + user.LastActiveDate = DateTime.Now; + + //Add the user + if (!userList.Contains(userID)) + { + userList[userID] = user; + } + } + else + { + if ((cookie.Value == null)) + { + //Expire the cookie, there is something wrong with it + context.Response.Cookies[cookieName].Expires = new DateTime(1999, 10, 12); + + //No need to do anything else + return; + } + + //Get userID out of cookie + userID = cookie.Value; + + //Find the cookie in the user list + if ((userList[userID] == null)) + { + userList[userID] = new AnonymousUserInfo(); + ((AnonymousUserInfo) userList[userID]).CreationDate = DateTime.Now; + } + + user = (AnonymousUserInfo) userList[userID]; + user.UserID = userID; + user.PortalID = portalSettings.PortalId; + user.TabID = portalSettings.ActiveTab.TabID; + user.LastActiveDate = DateTime.Now; + + //Reset the expiration on the cookie + cookie = new HttpCookie(cookieName); + cookie.Value = userID; + cookie.Expires = DateTime.Now.AddMinutes(20); + context.Response.Cookies.Add(cookie); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Tracks an Authenticated User + /// + /// An HttpContext Object + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + private void TrackAuthenticatedUser(HttpContext context) + { + //Retrieve Portal Settings + var portalSettings = (PortalSettings) context.Items["PortalSettings"]; + + if (portalSettings == null) + { + return; + } + //Get the logged in User ID + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + + //Get user list + Hashtable userList = GetUserList(); + + var user = new OnlineUserInfo(); + if (objUserInfo.UserID > 0) + { + user.UserID = objUserInfo.UserID; + } + user.PortalID = portalSettings.PortalId; + user.TabID = portalSettings.ActiveTab.TabID; + user.LastActiveDate = DateTime.Now; + if ((userList[objUserInfo.UserID.ToString()] == null)) + { + user.CreationDate = user.LastActiveDate; + } + userList[objUserInfo.UserID.ToString()] = user; + SetUserList(userList); + } + + /// ----------------------------------------------------------------------------- + /// + /// Tracks an online User + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public void TrackUsers() + { + HttpContext context = HttpContext.Current; + + //Have we already done the work for this request? + if (context.Items["CheckedUsersOnlineCookie"] != null) + { + return; + } + else + { + context.Items["CheckedUsersOnlineCookie"] = "true"; + } + if ((context.Request.IsAuthenticated)) + { + TrackAuthenticatedUser(context); + } + else if ((context.Request.Browser.Cookies)) + { + TrackAnonymousUser(context); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Update the Users Online information + /// + /// + /// [cnurse] 03/14/2006 documented + /// + /// ----------------------------------------------------------------------------- + public void UpdateUsersOnline() + { + //Get a Current User List + Hashtable userList = GetUserList(); + + //Create a shallow copy of the list to Process + var listToProcess = (Hashtable) userList.Clone(); + + //Clear the list + ClearUserList(); + + //Persist the current User List + try + { + memberProvider.UpdateUsersOnline(listToProcess); + } + catch (Exception exc) + { + Logger.Error(exc); + + } + + //Remove users that have expired + memberProvider.DeleteUsersOnline(GetOnlineTimeWindow()); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ExtensionPoints/ContextMenuItemExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/ContextMenuItemExtensionControl.cs new file mode 100644 index 00000000000..9854743e66e --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ContextMenuItemExtensionControl.cs @@ -0,0 +1,64 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Text")] + [ToolboxData("<{0}:ContextMenuItemExtensionControl runat=server>")] + public class ContextMenuItemExtensionControl : DefaultExtensionControl + { + private string content = ""; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + var extensionPointManager = new ExtensionPointManager(); + + StringBuilder str = new StringBuilder(); + + foreach (var extension in extensionPointManager.GetContextMenuItemExtensionPoints(Module, Group)) + { + str.Append(@"
  • + + + "+extension.Text+@" + +
  • "); + } + + content = str.ToString(); + } + + protected override void RenderContents(HtmlTextWriter output) + { + output.Write(content); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/DefaultExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/DefaultExtensionControl.cs new file mode 100644 index 00000000000..82ad2d52c13 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/DefaultExtensionControl.cs @@ -0,0 +1,82 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Text")] + [ToolboxData("<{0}:DefaultExtensionControl runat=server>")] + public class DefaultExtensionControl : WebControl + { + [Bindable(true)] + [DefaultValue("")] + public string Module + { + get + { + String s = (String)ViewState["Module"]; + return ((s == null) ? String.Empty : s); + } + set + { + ViewState["Module"] = value; + } + } + + [Bindable(true)] + [DefaultValue("")] + public string Group + { + get + { + String s = (String)ViewState["Group"]; + return ((s == null) ? String.Empty : s); + } + set + { + ViewState["Group"] = value; + } + } + + [Bindable(true)] + [DefaultValue("")] + public string Name + { + get + { + String s = (String)ViewState["Name"]; + return ((s == null) ? String.Empty : s); + } + set + { + ViewState["Name"] = value; + } + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/EditPagePanelExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/EditPagePanelExtensionControl.cs new file mode 100644 index 00000000000..49c979971b7 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/EditPagePanelExtensionControl.cs @@ -0,0 +1,138 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.ComponentModel; +using System.IO; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Text")] + [ToolboxData("<{0}:EditPagePanelExtensionControl runat=server>")] + public class EditPagePanelExtensionControl : DefaultExtensionControl + { + private void LoadControl(IEditPagePanelExtensionPoint extension) + { + var editPanel = new PanelEditPagePanelExtensionControl { PanelId = extension.EditPagePanelId, Text = extension.Text, CssClass = extension.CssClass }; + var control = Page.LoadControl(extension.UserControlSrc); + control.ID = Path.GetFileNameWithoutExtension(extension.UserControlSrc); + editPanel.Controls.Add(control); + Controls.Add(editPanel); + + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + var extensionPointManager = new ExtensionPointManager(); + + if (!String.IsNullOrEmpty(Name)) + { + var extension = extensionPointManager.GetEditPagePanelExtensionPointFirstByPriority(Module, Name); + LoadControl(extension); + } + else + { + foreach (var extension in extensionPointManager.GetEditPagePanelExtensionPoints(Module, Group)) + { + LoadControl(extension); + } + } + } + + public void BindAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var panelcontrol = control as PanelEditPagePanelExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPagePanelControlActions; + if (actionsControl != null) + { + actionsControl.BindAction(portalId, tabId, moduleId); + } + } + } + } + } + + public void SaveAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var panelcontrol = control as PanelEditPagePanelExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPagePanelControlActions; + if (actionsControl != null) + { + actionsControl.SaveAction(portalId, tabId, moduleId); + } + } + } + } + } + + public void CancelAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var panelcontrol = control as PanelEditPagePanelExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPagePanelControlActions; + if (actionsControl != null) + { + actionsControl.CancelAction(portalId, tabId, moduleId); + } + } + } + } + } + } + + public class PanelEditPagePanelExtensionControl : WebControl + { + public string PanelId { get; set; } + public string Text { get; set; } + + protected override void RenderContents(HtmlTextWriter op) + { + + op.Write(@"
    +

    +"+Text+@" +

    +
    "); + base.RenderContents(op); + op.Write("
    "); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/EditPageTabExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/EditPageTabExtensionControl.cs new file mode 100644 index 00000000000..1f4a838a141 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/EditPageTabExtensionControl.cs @@ -0,0 +1,178 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.ComponentModel; +using System.IO; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Module")] + [ToolboxData("<{0}:EditPageTabExtensionControl runat=server>")] + public class EditPageTabExtensionControl : DefaultExtensionControl + { + [Bindable(true)] + [DefaultValue("")] + public string TabControlId + { + get + { + var s = (String)ViewState["TabControlId"]; + return (s ?? String.Empty); + } + set + { + ViewState["TabControlId"] = value; + } + } + + [Bindable(true)] + [DefaultValue("")] + public string PanelControlId + { + get + { + var s = (String)ViewState["PanelControlId"]; + return (s ?? String.Empty); + } + set + { + ViewState["PanelControlId"] = value; + } + } + + protected override void OnInit(EventArgs e) + { + var extensionPointManager = new ExtensionPointManager(); + + var tabs = (HtmlGenericControl)Parent.FindControl(TabControlId); + var panel = Parent.FindControl(PanelControlId); + + foreach (var extension in extensionPointManager.GetEditPageTabExtensionPoints(Module, Group)) + { + if (extension.Visible) + { + var liElement = new HtmlGenericControl("li") + { + InnerHtml = "" + extension.Text + "", + }; + liElement.Attributes.Add("class", extension.CssClass); + tabs.Controls.Add(liElement); + + var container = new PanelTabExtensionControl { PanelId = extension.EditPageTabId }; + var control = Page.LoadControl(extension.UserControlSrc); + control.ID = Path.GetFileNameWithoutExtension(extension.UserControlSrc); + container.Controls.Add(control); + panel.Controls.Add(container); + } + } + } + + public void BindAction(int portalId, int tabId, int moduleId) + { + var panel = Parent.FindControl(PanelControlId); + + foreach (var control in panel.Controls) + { + var panelcontrol = control as PanelTabExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPageTabControlActions; + if (actionsControl != null) + { + actionsControl.BindAction(portalId, tabId, moduleId); + } + } + } + } + } + + public void SaveAction(int portalId, int tabId, int moduleId) + { + var panel = Parent.FindControl(PanelControlId); + + foreach (var control in panel.Controls) + { + var panelcontrol = control as PanelTabExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPageTabControlActions; + if (actionsControl != null) + { + actionsControl.SaveAction(portalId, tabId, moduleId); + } + } + } + } + } + + public void CancelAction(int portalId, int tabId, int moduleId) + { + var panel = Parent.FindControl(PanelControlId); + + foreach (var control in panel.Controls) + { + var panelcontrol = control as PanelTabExtensionControl; + if (panelcontrol != null) + { + foreach (var extensionControl in panelcontrol.Controls) + { + var actionsControl = extensionControl as IEditPageTabControlActions; + if (actionsControl != null) + { + actionsControl.CancelAction(portalId, tabId, moduleId); + } + } + } + } + } + + } + + public class PanelTabExtensionControl : WebControl + { + public string PanelId { get; set; } + + public override void RenderBeginTag(HtmlTextWriter writer) + { + writer.Write(""); + } + + public override void RenderEndTag(HtmlTextWriter writer) + { + writer.Write(""); + } + + protected override void RenderContents(HtmlTextWriter op) + { + op.Write("
    "); + base.RenderContents(op); + op.Write("
    "); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/ExportClientScriptAttribute.cs b/DNN Platform/Library/ExtensionPoints/ExportClientScriptAttribute.cs new file mode 100644 index 00000000000..a05cd441bcc --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ExportClientScriptAttribute.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.ExtensionPoints +{ + using System.ComponentModel.Composition; + + [MetadataAttribute] + public class ExportClientScriptAttribute : ExportAttribute + { + public ExportClientScriptAttribute() + : base(typeof(IScriptItemExtensionPoint)) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ExtensionPoints/ExtensionPointManager.cs b/DNN Platform/Library/ExtensionPoints/ExtensionPointManager.cs new file mode 100644 index 00000000000..8f7d2a6e724 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ExtensionPointManager.cs @@ -0,0 +1,227 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; +using System.IO; +using System.Linq; +using System.Web; + +namespace DotNetNuke.ExtensionPoints +{ + using Common; + + public class ExtensionPointManager + { +#pragma warning disable 649 + + [ImportMany] + private IEnumerable> _scripts; + + [ImportMany] + private IEnumerable> _editPageTabExtensionPoint; + + [ImportMany] + private IEnumerable> _toolbarButtonExtensionPoints; + + [ImportMany] + private IEnumerable> _editPagePanelExtensionPoints; + + [ImportMany] + private IEnumerable> _ctxMenuItemExtensionPoints; + + [ImportMany] + private IEnumerable> _userControlExtensionPoints; + + [ImportMany] + private IEnumerable> _menuItems; + + [ImportMany] + private IEnumerable> _gridColumns; + +#pragma warning restore 649 + + private static readonly object SyncRoot = new Object(); + + private static CompositionContainer MefCompositionContainer + { + get + { + var container = HttpContext.Current.Application["MefCompositionContainer"] as CompositionContainer; + if (container == null) + { + var catalog = new AggregateCatalog(); + var path = Path.Combine(Globals.ApplicationMapPath, "bin"); + catalog.Catalogs.Add(new SafeDirectoryCatalog(path)); + container = new CompositionContainer(catalog, true); + HttpContext.Current.Application["MefCompositionContainer"] = container; + } + + return container; + } + } + + public static void ComposeParts(params object[] attributeParts) + { + lock (SyncRoot) + { + MefCompositionContainer.ComposeParts(attributeParts); + } + } + + public ExtensionPointManager() + { + ComposeParts(this); + } + + public IEnumerable GetEditPageTabExtensionPoints(string module) + { + return _editPageTabExtensionPoint.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetEditPageTabExtensionPoints(string module, string group) + { + if (String.IsNullOrEmpty(group)) + { + return GetEditPageTabExtensionPoints(module); + } + + return _editPageTabExtensionPoint.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetToolBarButtonExtensionPoints(string module) + { + return _toolbarButtonExtensionPoints.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetToolBarButtonExtensionPoints(string module, string group) + { + if (string.IsNullOrEmpty(group)) + { + return GetToolBarButtonExtensionPoints(module); + } + + return _toolbarButtonExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetScriptItemExtensionPoints(string module) + { + return _scripts.Where(e => e.Metadata.Module == module).OrderByDescending(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetScriptItemExtensionPoints(string module, string group) + { + if (string.IsNullOrEmpty(group)) + { + return GetScriptItemExtensionPoints(module); + } + + return _scripts.Where(e => e.Metadata.Module == module && e.Metadata.Group == group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetEditPagePanelExtensionPoints(string module) + { + return _editPagePanelExtensionPoints.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetEditPagePanelExtensionPoints(string module, string group) + { + if(string.IsNullOrEmpty(group)) + { + return GetEditPagePanelExtensionPoints(module); + } + + return _editPagePanelExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group) + .OrderBy(e => e.Value.Order) + .Select(e => e.Value); + } + + public IEditPagePanelExtensionPoint GetEditPagePanelExtensionPointFirstByPriority(string module, string name) + { + return _editPagePanelExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Name == name) + .OrderBy(e => e.Metadata.Priority) + .Select(e => e.Value) + .FirstOrDefault(); + } + + public IEnumerable GetContextMenuItemExtensionPoints(string module) + { + return _ctxMenuItemExtensionPoints.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetContextMenuItemExtensionPoints(string module, string group) + { + if (string.IsNullOrEmpty(group)) + { + return GetContextMenuItemExtensionPoints(module); + } + + return _ctxMenuItemExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IUserControlExtensionPoint GetUserControlExtensionPointFirstByPriority(string module, string name) + { + return _userControlExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Name == name) + .OrderBy(e => e.Metadata.Priority) + .Select(e => e.Value) + .FirstOrDefault(); + } + + public IEnumerable GetUserControlExtensionPoints(string module, string group) + { + return _userControlExtensionPoints.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group) + .OrderBy(e => e.Value.Order) + .Select(e => e.Value); + } + + public IEnumerable GetMenuItemExtensionPoints(string module) + { + return _menuItems.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetMenuItemExtensionPoints(string module, string group) + { + if (string.IsNullOrEmpty(group)) + { + return GetMenuItemExtensionPoints(module); + } + + return _menuItems.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetGridColumnExtensionPoints(string module) + { + return _gridColumns.Where(e => e.Metadata.Module == module).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + + public IEnumerable GetGridColumnExtensionPoints(string module, string group) + { + if (string.IsNullOrEmpty(group)) + { + return GetGridColumnExtensionPoints(module); + } + + return _gridColumns.Where(e => e.Metadata.Module == module && e.Metadata.Group == @group).OrderBy(e => e.Value.Order).Select(e => e.Value); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ExtensionPoints/IContextMenuItemExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IContextMenuItemExtensionPoint.cs new file mode 100644 index 00000000000..85ca04fdc04 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IContextMenuItemExtensionPoint.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.ExtensionPoints +{ + public interface IContextMenuItemExtensionPoint : IExtensionPoint + { + string CtxMenuItemId { get; } + + string CssClass { get; } + + string Action { get; } + + string AltText { get; } + + bool ShowText { get; } + + bool ShowIcon { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IEditPagePanelControlActions.cs b/DNN Platform/Library/ExtensionPoints/IEditPagePanelControlActions.cs new file mode 100644 index 00000000000..deb744c1c2d --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IEditPagePanelControlActions.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IEditPagePanelControlActions + { + void SaveAction(int portalId, int tabId, int moduleId); + void CancelAction(int portalId, int tabId, int moduleId); + void BindAction(int portalId, int tabId, int moduleId); + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IEditPagePanelExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IEditPagePanelExtensionPoint.cs new file mode 100644 index 00000000000..10cf43c1227 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IEditPagePanelExtensionPoint.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IEditPagePanelExtensionPoint: IUserControlExtensionPoint + { + string EditPagePanelId { get; } + string CssClass { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IEditPageTabControlActions.cs b/DNN Platform/Library/ExtensionPoints/IEditPageTabControlActions.cs new file mode 100644 index 00000000000..0c7a86e37f7 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IEditPageTabControlActions.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IEditPageTabControlActions + { + void SaveAction(int portalId, int tabId, int moduleId); + void CancelAction(int portalId, int tabId, int moduleId); + void BindAction(int portalId, int tabId, int moduleId); + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IEditPageTabExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IEditPageTabExtensionPoint.cs new file mode 100644 index 00000000000..bb8e7201ce3 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IEditPageTabExtensionPoint.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IEditPageTabExtensionPoint : IUserControlExtensionPoint + { + string EditPageTabId { get; } + string CssClass { get; } + string Permission { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IExtensionControlRenderer.cs b/DNN Platform/Library/ExtensionPoints/IExtensionControlRenderer.cs new file mode 100644 index 00000000000..918a51c0fbe --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IExtensionControlRenderer.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IExtensionControlRenderer + { + string GetOutput(IExtensionPoint extension); + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IExtensionPoint.cs new file mode 100644 index 00000000000..fb4cafac2ef --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IExtensionPoint.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.ExtensionPoints +{ + public interface IExtensionPoint + { + string Text { get; } + string Icon { get; } + int Order { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IExtensionPointData.cs b/DNN Platform/Library/ExtensionPoints/IExtensionPointData.cs new file mode 100644 index 00000000000..b9bbbdfd03d --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IExtensionPointData.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IExtensionPointData + { + string Module { get; } + string Name { get; } + string Group { get; } + int Priority { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IGridColumnExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IGridColumnExtensionPoint.cs new file mode 100644 index 00000000000..e1127df71e2 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IGridColumnExtensionPoint.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Web.UI.WebControls; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IGridColumnExtensionPoint : IExtensionPoint + { + int ColumnAt { get; } + string UniqueName { get; } + string DataField { get; } + string HeaderText { get; } + Unit HeaderStyleWidth { get; } + bool ReadOnly { get; } + bool Reorderable { get; } + string SortExpression { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IMenuButtonItemExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IMenuButtonItemExtensionPoint.cs new file mode 100644 index 00000000000..1e0473be8aa --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IMenuButtonItemExtensionPoint.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IMenuButtonItemExtensionPoint : IExtensionPoint + { + string ItemId { get; } + + string Attributes { get; } + + string Type { get; } + + string CssClass { get; } + + string Action { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IMenuItemExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IMenuItemExtensionPoint.cs new file mode 100644 index 00000000000..ae5c1eb6283 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IMenuItemExtensionPoint.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IMenuItemExtensionPoint : IExtensionPoint + { + string Value { get; } + string CssClass { get; } + bool EnabledOnHost { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IScriptItemExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IScriptItemExtensionPoint.cs new file mode 100644 index 00000000000..b1fe6118179 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IScriptItemExtensionPoint.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.ExtensionPoints +{ + public interface IScriptItemExtensionPoint : IExtensionPoint + { + string ScriptName { get; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ExtensionPoints/IToolBarButtonExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IToolBarButtonExtensionPoint.cs new file mode 100644 index 00000000000..03f8cd4b524 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IToolBarButtonExtensionPoint.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.ExtensionPoints +{ + public interface IToolBarButtonExtensionPoint : IExtensionPoint + { + string ButtonId { get; } + + string CssClass { get; } + + string Action { get; } + + string AltText { get; } + + bool ShowText { get; } + + bool ShowIcon { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IToolBarMenuButtonExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IToolBarMenuButtonExtensionPoint.cs new file mode 100644 index 00000000000..56251c515d5 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IToolBarMenuButtonExtensionPoint.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IToolBarMenuButtonExtensionPoint: IToolBarButtonExtensionPoint + { + List Items { get; } + string MenuCssClass { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IUserControlActions.cs b/DNN Platform/Library/ExtensionPoints/IUserControlActions.cs new file mode 100644 index 00000000000..6840be9dea2 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IUserControlActions.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IUserControlActions + { + void SaveAction(int portalId, int tabId, int moduleId); + void CancelAction(int portalId, int tabId, int moduleId); + void BindAction(int portalId, int tabId, int moduleId); + } +} diff --git a/DNN Platform/Library/ExtensionPoints/IUserControlExtensionPoint.cs b/DNN Platform/Library/ExtensionPoints/IUserControlExtensionPoint.cs new file mode 100644 index 00000000000..76601555847 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/IUserControlExtensionPoint.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.ExtensionPoints +{ + public interface IUserControlExtensionPoint : IExtensionPoint + { + string UserControlSrc { get; } + bool Visible { get; } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/SafeDirectoryCatalog.cs b/DNN Platform/Library/ExtensionPoints/SafeDirectoryCatalog.cs new file mode 100644 index 00000000000..6c6e5089064 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/SafeDirectoryCatalog.cs @@ -0,0 +1,72 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.ComponentModel.Composition.Hosting; +using System.ComponentModel.Composition.Primitives; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace DotNetNuke.ExtensionPoints +{ + public class SafeDirectoryCatalog : ComposablePartCatalog + { + private readonly AggregateCatalog _catalog; + + public SafeDirectoryCatalog(string directory) + { + var files = Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories); + + _catalog = new AggregateCatalog(); + + foreach (var file in files) + { + try + { + var asmCat = new AssemblyCatalog(file); + + //Force MEF to load the plugin and figure out if there are any exports + // good assemblies will not throw the RTLE exception and can be added to the catalog + if (asmCat.Parts.ToList().Count > 0) _catalog.Catalogs.Add(asmCat); + } + catch (ReflectionTypeLoadException) + { + } + catch (BadImageFormatException) + { + } + catch (FileLoadException) //ignore when the assembly load failed. + { + + } + } + } + + public override IQueryable Parts + { + get + { + return _catalog.Parts; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/ExtensionPoints/ToolBarButtonExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/ToolBarButtonExtensionControl.cs new file mode 100644 index 00000000000..719a302304e --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ToolBarButtonExtensionControl.cs @@ -0,0 +1,70 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.ComponentModel; +using System.Text; +using System.Web.UI; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Text")] + [ToolboxData("<{0}:ToolBarButtonExtensionControl runat=server>")] + public class ToolBarButtonExtensionControl : DefaultExtensionControl + { + private string content = ""; + private IExtensionControlRenderer btnRenderer = null; + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + var extensionPointManager = new ExtensionPointManager(); + + var str = new StringBuilder(); + + foreach (var extension in extensionPointManager.GetToolBarButtonExtensionPoints(Module, Group)) + { + if (extension is IToolBarMenuButtonExtensionPoint) + { + btnRenderer = new ToolBarMenuButtonRenderer(); + str.AppendFormat(btnRenderer.GetOutput(extension)); + } else + { + btnRenderer = new ToolBarButtonRenderer(); + str.AppendFormat(btnRenderer.GetOutput(extension)); + } + + } + + content = str.ToString(); + } + + protected override void RenderContents(HtmlTextWriter output) + { + output.Write(content); + } + + protected override void Render(HtmlTextWriter writer) + { + RenderContents(writer); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/ToolBarButtonRenderer.cs b/DNN Platform/Library/ExtensionPoints/ToolBarButtonRenderer.cs new file mode 100644 index 00000000000..d11960d7807 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ToolBarButtonRenderer.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Text; + +namespace DotNetNuke.ExtensionPoints +{ + public class ToolBarButtonRenderer : IExtensionControlRenderer + { + public string GetOutput(IExtensionPoint extensionPoint) + { + var extension = (IToolBarButtonExtensionPoint)extensionPoint; + + var str = new StringBuilder(); + str.AppendFormat( + ""); + + return str.ToString(); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/ToolBarMenuButtonRenderer.cs b/DNN Platform/Library/ExtensionPoints/ToolBarMenuButtonRenderer.cs new file mode 100644 index 00000000000..1bfad178fb6 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/ToolBarMenuButtonRenderer.cs @@ -0,0 +1,70 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Text; + +namespace DotNetNuke.ExtensionPoints +{ + public class ToolBarMenuButtonRenderer : IExtensionControlRenderer + { + public string GetOutput(IExtensionPoint extensionPoint) + { + var extension = (IToolBarMenuButtonExtensionPoint)extensionPoint; + + var str = new StringBuilder(); + str.AppendFormat("
    ", extension.ButtonId, extension.MenuCssClass); + str.AppendFormat( + ""); + str.AppendFormat("
    ", extension.MenuCssClass); + str.AppendLine("
    "); + str.AppendLine("
      "); + foreach (var item in extension.Items) + { + str.AppendLine(GetItemOutput(item)); + } + + str.AppendLine("
    "); + str.AppendLine("
    "); + str.AppendLine("
    "); + + return str.ToString(); + } + + private string GetItemOutput(IMenuButtonItemExtensionPoint item) + { + if (string.IsNullOrEmpty(item.Type)) + { + return string.Format("
  • {4}
  • ", item.CssClass, item.ItemId, item.Action, item.Attributes, item.Text); + } + + return string.Format("
  • {6}
  • ", item.Type, item.ItemId, item.ItemId, item.Text, item.Attributes, item.Action, item.Text); + } + } +} diff --git a/DNN Platform/Library/ExtensionPoints/UserControlExtensionControl.cs b/DNN Platform/Library/ExtensionPoints/UserControlExtensionControl.cs new file mode 100644 index 00000000000..46b632025a4 --- /dev/null +++ b/DNN Platform/Library/ExtensionPoints/UserControlExtensionControl.cs @@ -0,0 +1,74 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Web.UI; + +namespace DotNetNuke.ExtensionPoints +{ + [DefaultProperty("Text")] + [ToolboxData("<{0}:UserControlExtensionControl runat=server>")] + public class UserControlExtensionControl : DefaultExtensionControl + { + private void LoadControl(IUserControlExtensionPoint extension) + { + var control = Page.LoadControl(extension.UserControlSrc); + control.ID = Path.GetFileNameWithoutExtension(extension.UserControlSrc); + Controls.Add(control); + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + var extensionPointManager = new ExtensionPointManager(); + + if (!String.IsNullOrEmpty(Name)) + { + var extension = extensionPointManager.GetUserControlExtensionPointFirstByPriority(Module, Name); + LoadControl(extension); + } + else + { + foreach (var extension in extensionPointManager.GetUserControlExtensionPoints(Module, Group)) + { + LoadControl(extension); + } + } + } + + public void BindAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var actionsControl = control as IUserControlActions; + if (actionsControl != null) + { + actionsControl.BindAction(portalId, tabId, moduleId); + } + } + } + + public void SaveAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var actionsControl = control as IUserControlActions; + if (actionsControl != null) + { + actionsControl.SaveAction(portalId, tabId, moduleId); + } + } + } + + public void CancelAction(int portalId, int tabId, int moduleId) + { + foreach (var control in Controls) + { + var actionsControl = control as IUserControlActions; + if (actionsControl != null) + { + actionsControl.CancelAction(portalId, tabId, moduleId); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/AJAX.cs b/DNN Platform/Library/Framework/AJAX.cs new file mode 100644 index 00000000000..7d9716d5b98 --- /dev/null +++ b/DNN Platform/Library/Framework/AJAX.cs @@ -0,0 +1,347 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Entities.Host; +using DotNetNuke.UI.WebControls; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.Framework +{ + public class AJAX + { + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// AddScriptManager is used internally by the framework to add a ScriptManager control to the page + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static void AddScriptManager(Page page) + { + AddScriptManager(page, true); + } + /// + /// AddScriptManager is used internally by the framework to add a ScriptManager control to the page. + /// + /// the page instance. + /// Whether check cdn settings from host settings. + public static void AddScriptManager(Page page, bool checkCdn) + { + if (GetScriptManager(page) == null) + { + using (var scriptManager = new RadScriptManager + { + ID = "ScriptManager", + EnableScriptGlobalization = true, + SupportsPartialRendering = true, + EnableHandlerDetection = false + }) + { + if (page.Form != null) + { + try + { + if (checkCdn) + { + scriptManager.EnableCdn = Host.EnableMsAjaxCdn; + scriptManager.CdnSettings.TelerikCdn = Host.EnableTelerikCdn ? TelerikCdnMode.Enabled : TelerikCdnMode.Disabled; + if (scriptManager.CdnSettings.TelerikCdn != TelerikCdnMode.Disabled && !string.IsNullOrEmpty(Host.TelerikCdnBasicUrl)) + { + scriptManager.CdnSettings.BaseUrl = Host.TelerikCdnBasicUrl; + } + if (scriptManager.CdnSettings.TelerikCdn != TelerikCdnMode.Disabled && !string.IsNullOrEmpty(Host.TelerikCdnSecureUrl)) + { + scriptManager.CdnSettings.BaseSecureUrl = Host.TelerikCdnSecureUrl; + } + } + page.Form.Controls.AddAt(0, scriptManager); + } + catch + { + //suppress error adding script manager to support edge-case of module developers custom aspx pages that inherit from basepage and use code blocks + } + if (HttpContext.Current.Items["System.Web.UI.ScriptManager"] == null) + { + HttpContext.Current.Items.Add("System.Web.UI.ScriptManager", true); + } + } + } + using (var stylesheetManager = new RadStyleSheetManager { ID = "StylesheetManager", EnableHandlerDetection = false }) + { + if (page.Form != null) + { + try + { + if (checkCdn) + { + stylesheetManager.CdnSettings.TelerikCdn = Host.EnableTelerikCdn ? TelerikCdnMode.Enabled : TelerikCdnMode.Disabled; + if (stylesheetManager.CdnSettings.TelerikCdn != TelerikCdnMode.Disabled && !string.IsNullOrEmpty(Host.TelerikCdnBasicUrl)) + { + stylesheetManager.CdnSettings.BaseUrl = Host.TelerikCdnBasicUrl; + } + if (stylesheetManager.CdnSettings.TelerikCdn != TelerikCdnMode.Disabled && !string.IsNullOrEmpty(Host.TelerikCdnSecureUrl)) + { + stylesheetManager.CdnSettings.BaseSecureUrl = Host.TelerikCdnSecureUrl; + } + } + page.Form.Controls.AddAt(0, stylesheetManager); + } + catch + { + //suppress error adding script manager to support edge-case of module developers custom aspx pages that inherit from basepage and use code blocks + } + } + } + } + } + + public static ScriptManager GetScriptManager(Page objPage) + { + return objPage.FindControl("ScriptManager") as ScriptManager; + } + + /// ----------------------------------------------------------------------------- + /// + /// IsEnabled can be used to determine if AJAX has been enabled already as we + /// only need one Script Manager per page. + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static bool IsEnabled() + { + if (HttpContext.Current.Items["System.Web.UI.ScriptManager"] == null) + { + return false; + } + else + { + return (bool) HttpContext.Current.Items["System.Web.UI.ScriptManager"]; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// IsInstalled can be used to determine if AJAX is installed on the server + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static bool IsInstalled() + { + return true; + } + + /// ----------------------------------------------------------------------------- + /// + /// Allows a control to be excluded from UpdatePanel async callback + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static void RegisterPostBackControl(Control objControl) + { + ScriptManager objScriptManager = GetScriptManager(objControl.Page); + if (objScriptManager != null) + { + objScriptManager.RegisterPostBackControl(objControl); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// RegisterScriptManager must be used by developers to instruct the framework that AJAX is required on the page + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static void RegisterScriptManager() + { + if (!IsEnabled()) + { + HttpContext.Current.Items.Add("System.Web.UI.ScriptManager", true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// RemoveScriptManager will remove the ScriptManager control during Page Render if the RegisterScriptManager has not been called + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static void RemoveScriptManager(Page objPage) + { + if (!IsEnabled()) + { + Control objControl = objPage.FindControl("ScriptManager"); + if ((objControl != null)) + { + objPage.Form.Controls.Remove(objControl); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Wraps a control in an update panel + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public static Control WrapUpdatePanelControl(Control objControl, bool blnIncludeProgress) + { + var updatePanel = new UpdatePanel(); + updatePanel.ID = objControl.ID + "_UP"; + updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional; + + Control objContentTemplateContainer = updatePanel.ContentTemplateContainer; + + for (int i = 0; i <= objControl.Parent.Controls.Count - 1; i++) + { + //find offset of original control + if (objControl.Parent.Controls[i].ID == objControl.ID) + { + //if ID matches + objControl.Parent.Controls.AddAt(i, updatePanel); + //insert update panel in that position + objContentTemplateContainer.Controls.Add(objControl); + //inject passed in control into update panel + break; + } + } + + if (blnIncludeProgress) + { + //create image for update progress control + var objImage = new Image(); + objImage.ImageUrl = "~/images/progressbar.gif"; + //hardcoded + objImage.AlternateText = "ProgressBar"; + + var updateProgress = new UpdateProgress(); + updateProgress.AssociatedUpdatePanelID = updatePanel.ID; + updateProgress.ID = updatePanel.ID + "_Prog"; + updateProgress.ProgressTemplate = new LiteralTemplate(objImage); + + objContentTemplateContainer.Controls.Add(updateProgress); + } + + return updatePanel; + } + + #endregion + + #region "Obsolete Methods" + + [Obsolete("Deprecated in DNN 5.4, Developers can work directly with the UpdatePanel")] + public static Control ContentTemplateContainerControl(object objUpdatePanel) + { + return (objUpdatePanel as UpdatePanel).ContentTemplateContainer; + } + + [Obsolete("Deprecated in DNN 5.4, MS AJax is now required for DotNetNuke 5.0. Develoers can create the control directly")] + public static Control CreateUpdatePanelControl() + { + var updatePanel = new UpdatePanel(); + updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional; + return updatePanel; + } + + [Obsolete("Deprecated in DNN 5.4, MS AJax is now required for DotNetNuke 5.0. Developers can work directly with the UpdateProgress")] + public static Control CreateUpdateProgressControl(string AssociatedUpdatePanelID) + { + var updateProgress = new UpdateProgress(); + updateProgress.ID = AssociatedUpdatePanelID + "_Prog"; + updateProgress.AssociatedUpdatePanelID = AssociatedUpdatePanelID; + return updateProgress; + } + + [Obsolete("Deprecated in DNN 5.4, MS AJax is now required for DotNetNuke 5.0. Developers can work directly with the UpdateProgress")] + public static Control CreateUpdateProgressControl(string AssociatedUpdatePanelID, string ProgressHTML) + { + var updateProgress = new UpdateProgress(); + updateProgress.ID = AssociatedUpdatePanelID + "_Prog"; + updateProgress.AssociatedUpdatePanelID = AssociatedUpdatePanelID; + updateProgress.ProgressTemplate = new LiteralTemplate(ProgressHTML); + return updateProgress; + } + + [Obsolete("Deprecated in DNN 5.4, MS AJax is now required for DotNetNuke 5.0. Developers can work directly with the UpdateProgress")] + public static Control CreateUpdateProgressControl(string AssociatedUpdatePanelID, Control ProgressControl) + { + var updateProgress = new UpdateProgress(); + updateProgress.ID = AssociatedUpdatePanelID + "_Prog"; + updateProgress.AssociatedUpdatePanelID = AssociatedUpdatePanelID; + updateProgress.ProgressTemplate = new LiteralTemplate(ProgressControl); + return updateProgress; + } + + [Obsolete("Deprecated in DNN 5.0, MS AJax is now required for DotNetNuke 5.0 and above - value no longer read from Host.EnableAjax")] + public static bool IsHostEnabled() + { + return true; + } + + [Obsolete("Deprecated in DNN 5.4, Replaced by GetScriptManager")] + public static Control ScriptManagerControl(Page objPage) + { + return objPage.FindControl("ScriptManager"); + } + + [Obsolete("Deprecated in DNN 5.4, Developers can work directly with the ScriptManager")] + public static void SetScriptManagerProperty(Page objPage, string PropertyName, object[] Args) + { + ScriptManager scriptManager = GetScriptManager(objPage); + if (scriptManager != null) + { + Reflection.SetProperty(scriptManager.GetType(), PropertyName, scriptManager, Args); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Framework/BaseHttpHandler.cs b/DNN Platform/Library/Framework/BaseHttpHandler.cs new file mode 100644 index 00000000000..c65515db6a6 --- /dev/null +++ b/DNN Platform/Library/Framework/BaseHttpHandler.cs @@ -0,0 +1,272 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Web; + +#endregion + +namespace DotNetNuke.Framework +{ + public abstract class BaseHttpHandler : IHttpHandler + { + private HttpContext _context; + + /// + /// Returns the object for the incoming HTTP request. + /// + public HttpContext Context + { + get + { + return _context; + } + } + + /// + /// Returns the object for the incoming HTTP request. + /// + public HttpRequest Request + { + get + { + return Context.Request; + } + } + + /// + /// Gets the object associated with the Page object. This object + /// allows you to send HTTP response data to a client and contains information about that response. + /// + public HttpResponse Response + { + get + { + return Context.Response; + } + } + + /// + /// Gets the string representation of the body of the incoming request. + /// + public string Content + { + get + { + string _content = string.Empty; + Request.InputStream.Position = 0; + using (var Reader = new StreamReader(Request.InputStream)) + { + _content = Reader.ReadToEnd(); + } + + return _content; + } + } + + /// + /// Gets a value indicating whether this handler + /// requires users to be authenticated. + /// + /// + /// true if authentication is required + /// otherwise, false. + /// + public virtual bool RequiresAuthentication + { + get + { + return true; + } + } + + /// + /// Gets a value indicating whether the requester + /// has the necessary permissions. + /// + /// + /// By default all authenticated users have permssions. + /// This property is only enforced if is true + /// + /// + /// true if the user has the appropriate permissions + /// otherwise, false. + /// + public virtual bool HasPermission + { + get + { + return Context.User.Identity.IsAuthenticated; + } + } + + /// + /// Gets the content MIME type for the response object. + /// + /// + public virtual string ContentMimeType + { + get + { + return "text/plain"; + } + } + + /// + /// Gets the content encoding for the response object. + /// + /// + public virtual Encoding ContentEncoding + { + get + { + return Encoding.UTF8; + } + } + + #region IHttpHandler Members + + /// + /// Processs the incoming HTTP request. + /// + /// Context. + public void ProcessRequest(HttpContext context) + { + _context = context; + + SetResponseCachePolicy(Response.Cache); + + if (!ValidateParameters()) + { + RespondInternalError(); + return; + } + + if (RequiresAuthentication && !HasPermission) + { + RespondForbidden(); + return; + } + + Response.ContentType = ContentMimeType; + Response.ContentEncoding = ContentEncoding; + + HandleRequest(); + } + + public virtual bool IsReusable + { + get + { + return true; + } + } + + #endregion + + /// + /// Handles the request. This is where you put your + /// business logic. + /// + /// + ///

    This method should result in a call to one + /// (or more) of the following methods:

    + ///

    context.Response.BinaryWrite();

    + ///

    context.Response.Write();

    + ///

    context.Response.WriteFile();

    + ///

    + /// + /// someStream.Save(context.Response.OutputStream); + /// + ///

    + ///

    etc...

    + ///

    + /// If you want a download box to show up with a + /// pre-populated filename, add this call here + /// (supplying a real filename). + ///

    + ///

    + /// Response.AddHeader("Content-Disposition" + /// , "attachment; filename=\"" + Filename + "\""); + ///

    + ///
    + public abstract void HandleRequest(); + + /// + /// Validates the parameters. Inheriting classes must + /// implement this and return true if the parameters are + /// valid, otherwise false. + /// + /// true if the parameters are valid, + /// otherwise false + public abstract bool ValidateParameters(); + + /// + /// Sets the cache policy. Unless a handler overrides + /// this method, handlers will not allow a respons to be + /// cached. + /// + /// Cache. + public virtual void SetResponseCachePolicy(HttpCachePolicy cache) + { + cache.SetCacheability(HttpCacheability.NoCache); + cache.SetNoStore(); + cache.SetExpires(DateTime.MinValue); + } + + /// + /// Helper method used to Respond to the request + /// that the file was not found. + /// + protected void RespondFileNotFound() + { + Response.StatusCode = Convert.ToInt32(HttpStatusCode.NotFound); + Response.End(); + } + + /// + /// Helper method used to Respond to the request + /// that an error occurred in processing the request. + /// + protected void RespondInternalError() + { + // It's really too bad that StatusCode property + // is not of type HttpStatusCode. + Response.StatusCode = Convert.ToInt32(HttpStatusCode.InternalServerError); + Response.End(); + } + + /// + /// Helper method used to Respond to the request + /// that the request in attempting to access a resource + /// that the user does not have access to. + /// + protected void RespondForbidden() + { + Response.StatusCode = Convert.ToInt32(HttpStatusCode.Forbidden); + Response.End(); + } + } +} diff --git a/DNN Platform/Library/Framework/CDefault.cs b/DNN Platform/Library/Framework/CDefault.cs new file mode 100644 index 00000000000..22998b4c97b --- /dev/null +++ b/DNN Platform/Library/Framework/CDefault.cs @@ -0,0 +1,110 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Web.Caching; +using System.Web.UI; +using System.Web.UI.HtmlControls; + +//using DotNetNuke.UI.Utilities; +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.UI.Utilities; + +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : CDefault + /// + /// ----------------------------------------------------------------------------- + /// + /// + /// + /// + /// + /// + /// [sun1] 1/19/2004 Created + /// + /// ----------------------------------------------------------------------------- + public class CDefault : PageBase + { + public string Author = ""; + public string Comment = ""; + public string Copyright = ""; + public string Description = ""; + public string Generator = ""; + public string KeyWords = ""; + public new string Title = ""; + + protected override void RegisterAjaxScript() + { + if (Page.Form != null) + { + ServicesFrameworkInternal.Instance.RegisterAjaxScript(Page); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Allows the scroll position on the page to be moved to the top of the passed in control. + /// + /// Control to scroll to + /// + /// + /// + /// [Jon Henning] 3/30/2005 Created + /// + /// ----------------------------------------------------------------------------- + public void ScrollToControl(Control objControl) + { + if (ClientAPI.BrowserSupportsFunctionality(ClientAPI.ClientFunctionality.Positioning)) + { + ClientAPI.RegisterClientReference(this, ClientAPI.ClientNamespaceReferences.dnn_dom_positioning); + ClientAPI.RegisterClientVariable(this, "ScrollToControl", objControl.ClientID, true); + DNNClientAPI.SetScrollTop(Page); + } + } + + [Obsolete("Deprecated in DotNetNuke 6.0. Replaced by RegisterStyleSheet")] + public void AddStyleSheet(string id, string href, bool isFirst) + { + RegisterStyleSheet(this, href, isFirst); + } + + [Obsolete("Deprecated in DotNetNuke 6.0. Replaced by RegisterStyleSheet")] + public void AddStyleSheet(string id, string href) + { + RegisterStyleSheet(this, href, false); + } + + } +} diff --git a/DNN Platform/Library/Framework/CachePageStatePersister.cs b/DNN Platform/Library/Framework/CachePageStatePersister.cs new file mode 100644 index 00000000000..d69cc62f3d5 --- /dev/null +++ b/DNN Platform/Library/Framework/CachePageStatePersister.cs @@ -0,0 +1,131 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Text; +using System.Web.Caching; +using System.Web.UI; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Framework + /// Project: DotNetNuke + /// Class: CachePageStatePersister + /// ----------------------------------------------------------------------------- + /// + /// CachePageStatePersister provides a cache based page state peristence mechanism + /// + /// + /// [cnurse] 11/30/2006 documented + /// + /// ----------------------------------------------------------------------------- + public class CachePageStatePersister : PageStatePersister + { + private const string VIEW_STATE_CACHEKEY = "__VIEWSTATE_CACHEKEY"; + + /// ----------------------------------------------------------------------------- + /// + /// Creates the CachePageStatePersister + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public CachePageStatePersister(Page page) : base(page) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Loads the Page State from the Cache + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void Load() + { + //Get the cache key from the web form data + string key = Page.Request.Params[VIEW_STATE_CACHEKEY]; + + //Abort if cache key is not available or valid + if (string.IsNullOrEmpty(key) || !key.StartsWith("VS_")) + { + throw new ApplicationException("Missing valid " + VIEW_STATE_CACHEKEY); + } + var state = DataCache.GetCache(key); + if (state != null) + { + //Set view state and control state + ViewState = state.First; + ControlState = state.Second; + } + //Remove this ViewState from the cache as it has served its purpose + if (!Page.IsCallback) + { + DataCache.RemoveCache(key); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the Page State to the Cache + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void Save() + { + //No processing needed if no states available + if (ViewState == null && ControlState == null) + { + return; + } + + //Generate a unique cache key + var key = new StringBuilder(); + { + key.Append("VS_"); + key.Append(Page.Session == null ? Guid.NewGuid().ToString() : Page.Session.SessionID); + key.Append("_"); + key.Append(DateTime.Now.Ticks.ToString()); + } + + //Save view state and control state separately + var state = new Pair(ViewState, ControlState); + + //Add view state and control state to cache + DNNCacheDependency objDependency = null; + DataCache.SetCache(key.ToString(), state, objDependency, DateTime.Now.AddMinutes(Page.Session.Timeout), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); + + //Register hidden field to store cache key in + Page.ClientScript.RegisterHiddenField(VIEW_STATE_CACHEKEY, key.ToString()); + } + } +} diff --git a/DNN Platform/Library/Framework/DiskPageStatePersister.cs b/DNN Platform/Library/Framework/DiskPageStatePersister.cs new file mode 100644 index 00000000000..71ad52bf2b3 --- /dev/null +++ b/DNN Platform/Library/Framework/DiskPageStatePersister.cs @@ -0,0 +1,171 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Text; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Framework + /// Project: DotNetNuke + /// Class: DiskPageStatePersister + /// ----------------------------------------------------------------------------- + /// + /// DiskPageStatePersister provides a disk (stream) based page state peristence mechanism + /// + /// + /// [cnurse] 11/30/2006 documented + /// + /// ----------------------------------------------------------------------------- + public class DiskPageStatePersister : PageStatePersister + { + /// ----------------------------------------------------------------------------- + /// + /// Creates the DiskPageStatePersister + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public DiskPageStatePersister(Page page) : base(page) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The CacheDirectory property is used to return the location of the "Cache" + /// Directory for the Portal + /// + /// + /// + /// + /// [cnurse] 11/30/2006 Created + /// + /// ----------------------------------------------------------------------------- + public string CacheDirectory + { + get + { + return PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath + "Cache"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The StateFileName property is used to store the FileName for the State + /// + /// + /// + /// + /// [cnurse] 11/30/2006 Created + /// + /// ----------------------------------------------------------------------------- + public string StateFileName + { + get + { + var key = new StringBuilder(); + { + key.Append("VIEWSTATE_"); + key.Append(Page.Session.SessionID); + key.Append("_"); + key.Append(Page.Request.RawUrl); + } + return CacheDirectory + "\\" + Globals.CleanFileName(key.ToString()) + ".txt"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Loads the Page State from the Cache + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void Load() + { + StreamReader reader = null; + //Read the state string, using the StateFormatter. + try + { + reader = new StreamReader(StateFileName); + + string serializedStatePair = reader.ReadToEnd(); + + IStateFormatter formatter = StateFormatter; + + //Deserialize returns the Pair object that is serialized in + //the Save method. + var statePair = (Pair) formatter.Deserialize(serializedStatePair); + ViewState = statePair.First; + ControlState = statePair.Second; + } + finally + { + if (reader != null) + { + reader.Close(); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the Page State to the Cache + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void Save() + { + //No processing needed if no states available + if (ViewState == null && ControlState == null) + { + return; + } + if (Page.Session != null) + { + if (!Directory.Exists(CacheDirectory)) + { + Directory.CreateDirectory(CacheDirectory); + } + + //Write a state string, using the StateFormatter. + var writer = new StreamWriter(StateFileName, false); + IStateFormatter formatter = StateFormatter; + var statePair = new Pair(ViewState, ControlState); + string serializedState = formatter.Serialize(statePair); + writer.Write(serializedState); + writer.Close(); + } + } + } +} diff --git a/DNN Platform/Library/Framework/IServiceFrameworkInternals.cs b/DNN Platform/Library/Framework/IServiceFrameworkInternals.cs new file mode 100644 index 00000000000..9dc89f70d40 --- /dev/null +++ b/DNN Platform/Library/Framework/IServiceFrameworkInternals.cs @@ -0,0 +1,16 @@ +using System; +using System.Web.UI; + +namespace DotNetNuke.Framework +{ + internal interface IServiceFrameworkInternals + { + bool IsAjaxAntiForgerySupportRequired { get; } + + void RegisterAjaxAntiForgery(Page page); + + bool IsAjaxScriptSupportRequired { get; } + + void RegisterAjaxScript(Page page); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/IServicesFramework.cs b/DNN Platform/Library/Framework/IServicesFramework.cs new file mode 100644 index 00000000000..1be20909dab --- /dev/null +++ b/DNN Platform/Library/Framework/IServicesFramework.cs @@ -0,0 +1,38 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. +using System; + +namespace DotNetNuke.Framework +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IServicesFramework + { + /// + /// Will cause anti forgery tokens to be included in the current page + /// + void RequestAjaxAntiForgerySupport(); + + /// + /// Will cause ajax scripts to be included in the current page + /// + void RequestAjaxScriptSupport(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Internal/Reflection/AssemblyWrapper.cs b/DNN Platform/Library/Framework/Internal/Reflection/AssemblyWrapper.cs new file mode 100644 index 00000000000..45afbb8c2dd --- /dev/null +++ b/DNN Platform/Library/Framework/Internal/Reflection/AssemblyWrapper.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Reflection; + +namespace DotNetNuke.Framework.Internal.Reflection +{ + internal class AssemblyWrapper : IAssembly + { + private readonly Assembly _assembly; + + public AssemblyWrapper(Assembly assembly) + { + _assembly = assembly; + } + + public Type[] GetTypes() + { + return _assembly.GetTypes(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Internal/Reflection/IAssembly.cs b/DNN Platform/Library/Framework/Internal/Reflection/IAssembly.cs new file mode 100644 index 00000000000..06dd514e000 --- /dev/null +++ b/DNN Platform/Library/Framework/Internal/Reflection/IAssembly.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Framework.Internal.Reflection +{ + //interface to allowing mocking of System.Reflection.Assembly + public interface IAssembly + { + Type[] GetTypes(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Internal/Reflection/IAssemblyLocator.cs b/DNN Platform/Library/Framework/Internal/Reflection/IAssemblyLocator.cs new file mode 100644 index 00000000000..6cc01effd06 --- /dev/null +++ b/DNN Platform/Library/Framework/Internal/Reflection/IAssemblyLocator.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System.Collections.Generic; + +namespace DotNetNuke.Framework.Internal.Reflection +{ + public interface IAssemblyLocator + { + IEnumerable Assemblies { get; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Internal/Reflection/ITypeLocator.cs b/DNN Platform/Library/Framework/Internal/Reflection/ITypeLocator.cs new file mode 100644 index 00000000000..acd0f1f6113 --- /dev/null +++ b/DNN Platform/Library/Framework/Internal/Reflection/ITypeLocator.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Framework.Internal.Reflection +{ + internal interface ITypeLocator + { + IEnumerable GetAllMatchingTypes(Predicate predicate); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Internal/Reflection/TypeLocator.cs b/DNN Platform/Library/Framework/Internal/Reflection/TypeLocator.cs new file mode 100644 index 00000000000..aed08791c72 --- /dev/null +++ b/DNN Platform/Library/Framework/Internal/Reflection/TypeLocator.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace DotNetNuke.Framework.Internal.Reflection +{ + internal class TypeLocator : ITypeLocator, IAssemblyLocator + { + private IAssemblyLocator _assemblyLocator; + + internal IAssemblyLocator AssemblyLocator + { + get { return _assemblyLocator ?? (_assemblyLocator = this); } + set { _assemblyLocator = value; } + } + + public IEnumerable GetAllMatchingTypes(Predicate predicate) + { + foreach (var assembly in AssemblyLocator.Assemblies) + { + Type[] types; + try + { + types = assembly.GetTypes(); + } + catch (ReflectionTypeLoadException ex) + { + //some assemblies don't want to be reflected but they still + //expose types in the exception + types = ex.Types ?? new Type[0]; + } + + foreach (var type in types) + { + if(type != null) + { + if(predicate(type)) + { + yield return type; + } + } + } + } + } + + IEnumerable IAssemblyLocator.Assemblies + { + //this method is not readily testable as the assemblies in the current app domain + //will vary depending on the test runner and test configuration + get + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + yield return new AssemblyWrapper(assembly); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/PageBase.cs b/DNN Platform/Library/Framework/PageBase.cs new file mode 100644 index 00000000000..8fa97ba54ed --- /dev/null +++ b/DNN Platform/Library/Framework/PageBase.cs @@ -0,0 +1,673 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Globalization; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Icons; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Modules; +using DotNetNuke.Web.Client.ClientResourceManagement; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Framework + /// Project: DotNetNuke + /// Class: PageBase + /// ----------------------------------------------------------------------------- + /// + /// PageBase provides a custom DotNetNuke base class for pages + /// + /// + /// [cnurse] 11/30/2006 documented + /// + /// ----------------------------------------------------------------------------- + public abstract class PageBase : Page + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (PageBase)); + + private PageStatePersister _persister; + #region Private Members + + private readonly NameValueCollection _htmlAttributes = new NameValueCollection(); + private readonly ArrayList _localizedControls; + private CultureInfo _pageCulture; + private string _localResourceFile; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// Creates the Page + /// + /// + /// [cnurse] 11/30/2006 Documented + /// + /// ----------------------------------------------------------------------------- + protected PageBase() + { + _localizedControls = new ArrayList(); + } + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// PageStatePersister returns an instance of the class that will be used to persist the Page State + /// + /// A System.Web.UI.PageStatePersister + /// + /// [cnurse] 11/30/2005 Created + /// + /// ----------------------------------------------------------------------------- + protected override PageStatePersister PageStatePersister + { + get + { + //Set ViewState Persister to default (as defined in Base Class) + if (_persister == null) + { + _persister = base.PageStatePersister; + + if (Globals.Status == Globals.UpgradeStatus.None) + { + switch (Host.PageStatePersister) + { + case "M": + _persister = new CachePageStatePersister(this); + break; + case "D": + _persister = new DiskPageStatePersister(this); + break; + } + } + } + + return _persister; + } + } + + #endregion + + #region Public Properties + + public PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + public NameValueCollection HtmlAttributes + { + get + { + return _htmlAttributes; + } + } + + public CultureInfo PageCulture + { + get + { + return _pageCulture ?? (_pageCulture = Localization.GetPageLocale(PortalSettings)); + } + } + + public string LocalResourceFile + { + get + { + string fileRoot; + string[] page = Request.ServerVariables["SCRIPT_NAME"].Split('/'); + if (String.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = TemplateSourceDirectory + "/" + Localization.LocalResourceDirectory + "/" + page[page.GetUpperBound(0)] + ".resx"; + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + #endregion + + #region Private Methods + + private string GetErrorUrl(string url, Exception exc, bool hideContent = true) + { + if (Request.QueryString["error"] != null) + { + url += (url.IndexOf("?", StringComparison.Ordinal) == -1 ? "?" : "&") + "error=terminate"; + } + else + { + url += (url.IndexOf("?", StringComparison.Ordinal) == -1 ? "?" : "&") + "error=" + (exc == null || UserController.GetCurrentUserInfo() == null || !UserController.GetCurrentUserInfo().IsSuperUser ? "An unexpected error has occurred" : Server.UrlEncode(exc.Message)); + if (!Globals.IsAdminControl() && hideContent) + { + url += "&content=0"; + } + } + + return url; + } + + private bool IsViewStateFailure(Exception e) + { + return !User.Identity.IsAuthenticated && e != null && e.InnerException is ViewStateException; + } + + private void IterateControls(ControlCollection controls, ArrayList affectedControls, string resourceFileRoot) + { + foreach (Control c in controls) + { + ProcessControl(c, affectedControls, true, resourceFileRoot); + } + } + + #endregion + + #region Protected Methods + + protected virtual void RegisterAjaxScript() + { + if (ServicesFrameworkInternal.Instance.IsAjaxScriptSupportRequired) + { + ServicesFrameworkInternal.Instance.RegisterAjaxScript(Page); + } + } + + protected override void OnError(EventArgs e) + { + base.OnError(e); + Exception exc = Server.GetLastError(); + Logger.Fatal("An error has occurred while loading page.", exc); + + string strURL = Globals.ApplicationURL(); + if (exc is HttpException && !IsViewStateFailure(exc)) + { + if (PortalSettings.ErrorPage500 != -1) + { + string url = GetErrorUrl("~/Default.aspx?tabid=" + PortalSettings.ErrorPage500, exc, false); + HttpContext.Current.Response.Redirect(url); + } + else + { + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer("~/ErrorPage.aspx"); + } + } + + strURL = GetErrorUrl(strURL, exc); + Exceptions.ProcessPageLoadException(exc, strURL); + } + + protected override void OnInit(EventArgs e) + { + var isInstallPage = HttpContext.Current.Request.Url.LocalPath.ToLower().Contains("installwizard.aspx"); + if (!isInstallPage) + { + Localization.SetThreadCultures(PageCulture, PortalSettings); + } + + AJAX.AddScriptManager(this, !isInstallPage); + + var dnncoreFilePath = HttpContext.Current.IsDebuggingEnabled + ? "~/js/Debug/dnncore.js" + : "~/js/dnncore.js"; + + ClientResourceManager.RegisterScript(this, dnncoreFilePath); + + base.OnInit(e); + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + //Because we have delayed registration of the jQuery script, + //Modules can override the standard behavior by including their own script on the page. + //The module must register the script with the "jQuery" key and should notify user + //of potential version conflicts with core jQuery support. + if (jQuery.IsRequested) + { + jQuery.RegisterJQuery(Page); + } + if (jQuery.IsUIRequested) + { + jQuery.RegisterJQueryUI(Page); + } + if (jQuery.AreDnnPluginsRequested) + { + jQuery.RegisterDnnJQueryPlugins(Page); + } + if (jQuery.IsHoverIntentRequested) + { + jQuery.RegisterHoverIntent(Page); + } + + if(ServicesFrameworkInternal.Instance.IsAjaxAntiForgerySupportRequired) + { + ServicesFrameworkInternal.Instance.RegisterAjaxAntiForgery(Page); + } + + RegisterAjaxScript(); + } + + protected override void Render(HtmlTextWriter writer) + { + IterateControls(Controls, _localizedControls, LocalResourceFile); + RemoveKeyAttribute(_localizedControls); + AJAX.RemoveScriptManager(this); + base.Render(writer); + } + + + #endregion + + #region Public Methods + + /// + /// GetControlAttribute looks a the type of control and does it's best to find an AttributeCollection. + /// + /// Control to find the AttributeCollection on + /// ArrayList that hold the controls that have been localized. This is later used for the removal of the key attribute. + /// Name of key to search for. + /// A string containing the key for the specified control or null if a key attribute wasn't found + internal static string GetControlAttribute(Control control, ArrayList affectedControls, string attributeName) + { + AttributeCollection attributeCollection = null; + string key = null; + if (!(control is LiteralControl)) + { + if (control is WebControl) + { + var webControl = (WebControl)control; + attributeCollection = webControl.Attributes; + key = attributeCollection[attributeName]; + } + else + { + if (control is HtmlControl) + { + var htmlControl = (HtmlControl)control; + attributeCollection = htmlControl.Attributes; + key = attributeCollection[attributeName]; + } + else + { + if (control is UserControl) + { + var userControl = (UserControl)control; + attributeCollection = userControl.Attributes; + key = attributeCollection[attributeName]; + } + else + { + Type controlType = control.GetType(); + PropertyInfo attributeProperty = controlType.GetProperty("Attributes", typeof(AttributeCollection)); + if (attributeProperty != null) + { + attributeCollection = (AttributeCollection)attributeProperty.GetValue(control, null); + key = attributeCollection[attributeName]; + } + } + } + } + } + if (key != null && affectedControls != null) + { + affectedControls.Add(attributeCollection); + } + return key; + } + + /// + /// ProcessControl peforms the high level localization for a single control and optionally it's children. + /// + /// Control to find the AttributeCollection on + /// ArrayList that hold the controls that have been localized. This is later used for the removal of the key attribute. + /// If true, causes this method to process children of this controls. + /// Root Resource File. + internal void ProcessControl(Control control, ArrayList affectedControls, bool includeChildren, string resourceFileRoot) + { + if (!control.Visible) return; + + //Perform the substitution if a key was found + string key = GetControlAttribute(control, affectedControls, Localization.KeyName); + if (!string.IsNullOrEmpty(key)) + { + //Translation starts here .... + string value = Localization.GetString(key, resourceFileRoot); + if (control is Label) + { + var label = (Label)control; + if (!String.IsNullOrEmpty(value)) + { + label.Text = value; + } + } + if (control is LinkButton) + { + var linkButton = (LinkButton)control; + if (!String.IsNullOrEmpty(value)) + { + MatchCollection imgMatches = Regex.Matches(value, "<(a|link|img|script|input|form).[^>]*(href|src|action)=(\\\"|'|)(.[^\\\"']*)(\\\"|'|)[^>]*>", RegexOptions.IgnoreCase); + foreach (Match match in imgMatches) + { + if ((match.Groups[match.Groups.Count - 2].Value.IndexOf("~", StringComparison.Ordinal) != -1)) + { + string resolvedUrl = Page.ResolveUrl(match.Groups[match.Groups.Count - 2].Value); + value = value.Replace(match.Groups[match.Groups.Count - 2].Value, resolvedUrl); + } + } + linkButton.Text = value; + if (string.IsNullOrEmpty(linkButton.ToolTip)) + { + linkButton.ToolTip = value; + } + } + } + if (control is HyperLink) + { + var hyperLink = (HyperLink)control; + if (!String.IsNullOrEmpty(value)) + { + hyperLink.Text = value; + } + } + if (control is ImageButton) + { + var imageButton = (ImageButton)control; + if (!String.IsNullOrEmpty(value)) + { + imageButton.AlternateText = value; + } + } + if (control is Button) + { + var button = (Button)control; + if (!String.IsNullOrEmpty(value)) + { + button.Text = value; + } + } + if (control is HtmlImage) + { + var htmlImage = (HtmlImage)control; + if (!String.IsNullOrEmpty(value)) + { + htmlImage.Alt = value; + } + } + if (control is CheckBox) + { + var checkBox = (CheckBox)control; + if (!String.IsNullOrEmpty(value)) + { + checkBox.Text = value; + } + } + if (control is BaseValidator) + { + var baseValidator = (BaseValidator)control; + if (!String.IsNullOrEmpty(value)) + { + baseValidator.ErrorMessage = value; + } + } + if (control is Image) + { + var image = (Image)control; + if (!String.IsNullOrEmpty(value)) + { + image.AlternateText = value; + image.ToolTip = value; + } + } + } + + //Translate listcontrol items here + if (control is ListControl) + { + var listControl = (ListControl)control; + for (int i = 0; i <= listControl.Items.Count - 1; i++) + { + AttributeCollection attributeCollection = listControl.Items[i].Attributes; + key = attributeCollection[Localization.KeyName]; + if (key != null) + { + string value = Localization.GetString(key, resourceFileRoot); + if (!String.IsNullOrEmpty(value)) + { + listControl.Items[i].Text = value; + } + } + if (key != null && affectedControls != null) + { + affectedControls.Add(attributeCollection); + } + } + } + + + //UrlRewriting Issue - ResolveClientUrl gets called instead of ResolveUrl + //Manual Override to ResolveUrl + if (control is Image) + { + var image = (Image)control; + if (image.ImageUrl.IndexOf("~", StringComparison.Ordinal) != -1) + { + image.ImageUrl = Page.ResolveUrl(image.ImageUrl); + } + + //Check for IconKey + if (string.IsNullOrEmpty(image.ImageUrl)) + { + string iconKey = GetControlAttribute(control, affectedControls, IconController.IconKeyName); + string iconSize = GetControlAttribute(control, affectedControls, IconController.IconSizeName); + string iconStyle = GetControlAttribute(control, affectedControls, IconController.IconStyleName); + image.ImageUrl = IconController.IconURL(iconKey, iconSize, iconStyle); + } + } + + //UrlRewriting Issue - ResolveClientUrl gets called instead of ResolveUrl + //Manual Override to ResolveUrl + if (control is HtmlImage) + { + var htmlImage = (HtmlImage)control; + if (htmlImage.Src.IndexOf("~", StringComparison.Ordinal) != -1) + { + htmlImage.Src = Page.ResolveUrl(htmlImage.Src); + } + + //Check for IconKey + if (string.IsNullOrEmpty(htmlImage.Src)) + { + string iconKey = GetControlAttribute(control, affectedControls, IconController.IconKeyName); + string iconSize = GetControlAttribute(control, affectedControls, IconController.IconSizeName); + string iconStyle = GetControlAttribute(control, affectedControls, IconController.IconStyleName); + htmlImage.Src = IconController.IconURL(iconKey, iconSize, iconStyle); + } + } + + //UrlRewriting Issue - ResolveClientUrl gets called instead of ResolveUrl + //Manual Override to ResolveUrl + if (control is HyperLink) + { + HyperLink ctrl; + ctrl = (HyperLink)control; + if ((ctrl.NavigateUrl.IndexOf("~", StringComparison.Ordinal) != -1)) + { + ctrl.NavigateUrl = Page.ResolveUrl(ctrl.NavigateUrl); + } + if ((ctrl.ImageUrl.IndexOf("~", StringComparison.Ordinal) != -1)) + { + ctrl.ImageUrl = Page.ResolveUrl(ctrl.ImageUrl); + } + + //Check for IconKey + if (string.IsNullOrEmpty(ctrl.ImageUrl)) + { + string iconKey = GetControlAttribute(control, affectedControls, IconController.IconKeyName); + string iconSize = GetControlAttribute(control, affectedControls, IconController.IconSizeName); + string iconStyle = GetControlAttribute(control, affectedControls, IconController.IconStyleName); + ctrl.ImageUrl = IconController.IconURL(iconKey, iconSize, iconStyle); + } + } + + //Process child controls + if (includeChildren && control.HasControls()) + { + var objModuleControl = control as IModuleControl; + if (objModuleControl == null) + { + PropertyInfo pi = control.GetType().GetProperty("LocalResourceFile"); + if (pi != null && pi.GetValue(control, null) != null) + { + //If controls has a LocalResourceFile property use this + IterateControls(control.Controls, affectedControls, pi.GetValue(control, null).ToString()); + } + else + { + //Pass Resource File Root through + IterateControls(control.Controls, affectedControls, resourceFileRoot); + } + } + else + { + //Get Resource File Root from Controls LocalResourceFile Property + IterateControls(control.Controls, affectedControls, objModuleControl.LocalResourceFile); + } + } + } + + /// + /// RemoveKeyAttribute remove the key attribute from the control. If this isn't done, then the HTML output will have + /// a bad attribute on it which could cause some older browsers problems. + /// + /// ArrayList that hold the controls that have been localized. This is later used for the removal of the key attribute. + public static void RemoveKeyAttribute(ArrayList affectedControls) + { + if (affectedControls == null) + { + return; + } + int i; + for (i = 0; i <= affectedControls.Count - 1; i++) + { + var ac = (AttributeCollection)affectedControls[i]; + ac.Remove(Localization.KeyName); + ac.Remove(IconController.IconKeyName); + ac.Remove(IconController.IconSizeName); + ac.Remove(IconController.IconStyleName); + } + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DNN 6.1. Replaced by ClientResourceManager.RegisterStyleSheet.")] + protected static void AddStyleSheetInternal(Page page, string id, string styleSheet, bool isFirst) + { + Control objCSS = page.FindControl("CSS"); + if (objCSS != null) + { + Control objCtrl = page.Header.FindControl(id); + if (objCtrl == null) + { + var objLink = new HtmlLink { ID = id }; + objLink.Attributes["rel"] = "stylesheet"; + objLink.Attributes["type"] = "text/css"; + objLink.Href = styleSheet; + if (isFirst) + { + int iLink; + for (iLink = 0; iLink <= objCSS.Controls.Count - 1; iLink++) + { + if (objCSS.Controls[iLink] is HtmlLink) + { + break; + } + } + objCSS.Controls.AddAt(iLink, objLink); + } + else + { + objCSS.Controls.Add(objLink); + } + } + } + } + + [Obsolete("Deprecated in DNN 6.1. Replaced by ClientResourceManager.RegisterStyleSheet.")] + public static void RegisterStyleSheet(Page page, string styleSheet) + { + RegisterStyleSheet(page, styleSheet, false); + } + + [Obsolete("Deprecated in DNN 6.1. Replaced by ClientResourceManager.RegisterStyleSheet.")] + public static void RegisterStyleSheet(Page page, string styleSheet, bool isFirst) + { + if (isFirst) + { + ClientResourceManager.RegisterStyleSheet(page, styleSheet, 0); + } + else + { + ClientResourceManager.RegisterStyleSheet(page, styleSheet); + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Providers/Provider.cs b/DNN Platform/Library/Framework/Providers/Provider.cs new file mode 100644 index 00000000000..0bad8c72f65 --- /dev/null +++ b/DNN Platform/Library/Framework/Providers/Provider.cs @@ -0,0 +1,78 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Specialized; +using System.Xml; + +#endregion + +namespace DotNetNuke.Framework.Providers +{ + public class Provider + { + private readonly NameValueCollection _ProviderAttributes = new NameValueCollection(); + private readonly string _ProviderName; + private readonly string _ProviderType; + + public Provider(XmlAttributeCollection Attributes) + { + //Set the name of the provider + _ProviderName = Attributes["name"].Value; + + //Set the type of the provider + _ProviderType = Attributes["type"].Value; + + //Store all the attributes in the attributes bucket + foreach (XmlAttribute Attribute in Attributes) + { + if (Attribute.Name != "name" && Attribute.Name != "type") + { + _ProviderAttributes.Add(Attribute.Name, Attribute.Value); + } + } + } + + public string Name + { + get + { + return _ProviderName; + } + } + + public string Type + { + get + { + return _ProviderType; + } + } + + public NameValueCollection Attributes + { + get + { + return _ProviderAttributes; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Providers/ProviderConfiguration.cs b/DNN Platform/Library/Framework/Providers/ProviderConfiguration.cs new file mode 100644 index 00000000000..ad1c7e56039 --- /dev/null +++ b/DNN Platform/Library/Framework/Providers/ProviderConfiguration.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.Xml; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Framework.Providers +{ + public class ProviderConfiguration + { + private readonly Hashtable _Providers = new Hashtable(); + private string _DefaultProvider; + + public string DefaultProvider + { + get + { + return _DefaultProvider; + } + } + + public Hashtable Providers + { + get + { + return _Providers; + } + } + + public static ProviderConfiguration GetProviderConfiguration(string strProvider) + { + return (ProviderConfiguration) Config.GetSection("dotnetnuke/" + strProvider); + } + + internal void LoadValuesFromConfigurationXml(XmlNode node) + { + XmlAttributeCollection attributeCollection = node.Attributes; + + //Get the default provider + _DefaultProvider = attributeCollection["defaultProvider"].Value; + + //Read child nodes + foreach (XmlNode child in node.ChildNodes) + { + if (child.Name == "providers") + { + GetProviders(child); + } + } + } + + internal void GetProviders(XmlNode node) + { + foreach (XmlNode Provider in node.ChildNodes) + { + switch (Provider.Name) + { + case "add": + Providers.Add(Provider.Attributes["name"].Value, new Provider(Provider.Attributes)); + break; + case "remove": + Providers.Remove(Provider.Attributes["name"].Value); + break; + case "clear": + Providers.Clear(); + break; + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Providers/ProviderConfigurationHandler.cs b/DNN Platform/Library/Framework/Providers/ProviderConfigurationHandler.cs new file mode 100644 index 00000000000..4b8aefc1461 --- /dev/null +++ b/DNN Platform/Library/Framework/Providers/ProviderConfigurationHandler.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Configuration; +using System.Xml; + +#endregion + +namespace DotNetNuke.Framework.Providers +{ + [Obsolete("This class is obsolete. It is no longer used to load provider configurations, as there are medium trust issues")] + internal class ProviderConfigurationHandler : IConfigurationSectionHandler + { + #region IConfigurationSectionHandler Members + + public virtual object Create(object parent, object context, XmlNode node) + { + var objProviderConfiguration = new ProviderConfiguration(); + objProviderConfiguration.LoadValuesFromConfigurationXml(node); + return objProviderConfiguration; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/Reflection.cs b/DNN Platform/Library/Framework/Reflection.cs new file mode 100644 index 00000000000..2eacfbdc5ba --- /dev/null +++ b/DNN Platform/Library/Framework/Reflection.cs @@ -0,0 +1,423 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Web.Compilation; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework.Providers; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Framework + /// Project : DotNetNuke + /// Class : Reflection + /// ----------------------------------------------------------------------------- + /// + /// Library responsible for reflection + /// + /// + /// + /// + /// [Nik Kalyani] 10/15/2004 Replaced brackets in parameter names + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public class Reflection + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Reflection)); + #region Public Shared Methods + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The created Object + /// Overload for creating an object from a Provider configured in web.config + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType) + { + return CreateObject(ObjectProviderType, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// Caching switch + /// The created Object + /// Overload for creating an object from a Provider configured in web.config + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, bool UseCache) + { + return CreateObject(ObjectProviderType, "", "", "", UseCache); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The namespace of the object to create. + /// The assembly of the object to create. + /// The created Object + /// Overload for creating an object from a Provider including NameSpace and + /// AssemblyName ( this allows derived providers to share the same config ) + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, string ObjectNamespace, string ObjectAssemblyName) + { + return CreateObject(ObjectProviderType, "", ObjectNamespace, ObjectAssemblyName, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The namespace of the object to create. + /// The assembly of the object to create. + /// Caching switch + /// The created Object + /// Overload for creating an object from a Provider including NameSpace and + /// AssemblyName ( this allows derived providers to share the same config ) + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, string ObjectNamespace, string ObjectAssemblyName, bool UseCache) + { + return CreateObject(ObjectProviderType, "", ObjectNamespace, ObjectAssemblyName, UseCache); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The name of the Provider + /// The namespace of the object to create. + /// The assembly of the object to create. + /// The created Object + /// Overload for creating an object from a Provider including NameSpace, + /// AssemblyName and ProviderName + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, string ObjectProviderName, string ObjectNamespace, string ObjectAssemblyName) + { + return CreateObject(ObjectProviderType, ObjectProviderName, ObjectNamespace, ObjectAssemblyName, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The name of the Provider + /// The namespace of the object to create. + /// The assembly of the object to create. + /// Caching switch + /// The created Object + /// Overload for creating an object from a Provider including NameSpace, + /// AssemblyName and ProviderName + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, string ObjectProviderName, string ObjectNamespace, string ObjectAssemblyName, bool UseCache) + { + return CreateObject(ObjectProviderType, ObjectProviderName, ObjectNamespace, ObjectAssemblyName, UseCache, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of Object to create (data/navigation) + /// The name of the Provider + /// The namespace of the object to create. + /// The assembly of the object to create. + /// Caching switch + /// Whether append provider name as part of the assembly name. + /// The created Object + /// Overload for creating an object from a Provider including NameSpace, + /// AssemblyName and ProviderName + /// + /// [benz] 2/16/2012 Created + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string ObjectProviderType, string ObjectProviderName, string ObjectNamespace, string ObjectAssemblyName, bool UseCache, bool fixAssemblyName) + { + string TypeName = ""; + + //get the provider configuration based on the type + ProviderConfiguration objProviderConfiguration = ProviderConfiguration.GetProviderConfiguration(ObjectProviderType); + if (!String.IsNullOrEmpty(ObjectNamespace) && !String.IsNullOrEmpty(ObjectAssemblyName)) + { + //if both the Namespace and AssemblyName are provided then we will construct an "assembly qualified typename" - ie. "NameSpace.ClassName, AssemblyName" + if (String.IsNullOrEmpty(ObjectProviderName)) + { + //dynamically create the typename from the constants ( this enables private assemblies to share the same configuration as the base provider ) + TypeName = ObjectNamespace + "." + objProviderConfiguration.DefaultProvider + ", " + ObjectAssemblyName + (fixAssemblyName ? "." + objProviderConfiguration.DefaultProvider : string.Empty); + } + else + { + //dynamically create the typename from the constants ( this enables private assemblies to share the same configuration as the base provider ) + TypeName = ObjectNamespace + "." + ObjectProviderName + ", " + ObjectAssemblyName + (fixAssemblyName ? "." + ObjectProviderName : string.Empty); + } + } + else + { + //if only the Namespace is provided then we will construct an "full typename" - ie. "NameSpace.ClassName" + if (!String.IsNullOrEmpty(ObjectNamespace)) + { + if (String.IsNullOrEmpty(ObjectProviderName)) + { + //dynamically create the typename from the constants ( this enables private assemblies to share the same configuration as the base provider ) + TypeName = ObjectNamespace + "." + objProviderConfiguration.DefaultProvider; + } + else + { + //dynamically create the typename from the constants ( this enables private assemblies to share the same configuration as the base provider ) + TypeName = ObjectNamespace + "." + ObjectProviderName; + } + } + else + { + //if neither Namespace or AssemblyName are provided then we will get the typename from the default provider + if (String.IsNullOrEmpty(ObjectProviderName)) + { + //get the typename of the default Provider from web.config + TypeName = ((Provider) objProviderConfiguration.Providers[objProviderConfiguration.DefaultProvider]).Type; + } + else + { + //get the typename of the specified ProviderName from web.config + TypeName = ((Provider) objProviderConfiguration.Providers[ObjectProviderName]).Type; + } + } + } + return CreateObject(TypeName, TypeName, UseCache); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The fully qualified TypeName + /// The Cache Key + /// The created Object + /// Overload that takes a fully-qualified typename and a Cache Key + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string TypeName, string CacheKey) + { + return CreateObject(TypeName, CacheKey, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The fully qualified TypeName + /// The Cache Key + /// Caching switch + /// The created Object + /// Overload that takes a fully-qualified typename and a Cache Key + /// + /// [cnurse] 10/13/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(string TypeName, string CacheKey, bool UseCache) + { + return Activator.CreateInstance(CreateType(TypeName, CacheKey, UseCache)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of object to create + /// + /// Generic version + /// ----------------------------------------------------------------------------- + public static T CreateObject() + { + //dynamically create the object + return Activator.CreateInstance(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Creates an object + /// + /// The type of object to create + /// + /// ----------------------------------------------------------------------------- + public static object CreateObject(Type type) + { + return Activator.CreateInstance(type); + } + + public static Type CreateType(string TypeName) + { + return CreateType(TypeName, "", true, false); + } + + public static Type CreateType(string TypeName, bool IgnoreErrors) + { + return CreateType(TypeName, "", true, IgnoreErrors); + } + + public static Type CreateType(string TypeName, string CacheKey, bool UseCache) + { + return CreateType(TypeName, CacheKey, UseCache, false); + } + + public static Type CreateType(string TypeName, string CacheKey, bool UseCache, bool IgnoreErrors) + { + if (String.IsNullOrEmpty(CacheKey)) + { + CacheKey = TypeName; + } + Type type = null; + + //use the cache for performance + if (UseCache) + { + type = (Type) DataCache.GetCache(CacheKey); + } + + //is the type in the cache? + if (type == null) + { + try + { + //use reflection to get the type of the class + type = BuildManager.GetType(TypeName, true, true); + if (UseCache) + { + //insert the type into the cache + DataCache.SetCache(CacheKey, type); + } + } + catch (Exception exc) + { + if (!IgnoreErrors) + { + Logger.Error(TypeName, exc); ; + } + } + } + return type; + } + + public static object CreateInstance(Type Type) + { + if (Type != null) + { + return Type.InvokeMember("", BindingFlags.CreateInstance, null, null, null, null); + } + else + { + return null; + } + } + + public static object GetProperty(Type Type, string PropertyName, object Target) + { + if (Type != null) + { + return Type.InvokeMember(PropertyName, BindingFlags.GetProperty, null, Target, null); + } + else + { + return null; + } + } + + public static void SetProperty(Type Type, string PropertyName, object Target, object[] Args) + { + if (Type != null) + { + Type.InvokeMember(PropertyName, BindingFlags.SetProperty, null, Target, Args); + } + } + + public static void InvokeMethod(Type Type, string PropertyName, object Target, object[] Args) + { + if (Type != null) + { + Type.InvokeMember(PropertyName, BindingFlags.InvokeMethod, null, Target, Args); + } + } + + //dynamically create a default Provider from a ProviderType - this method was used by the CachingProvider to avoid a circular dependency + [Obsolete("This method has been deprecated. Please use CreateObject(ByVal ObjectProviderType As String, ByVal UseCache As Boolean) As Object")] + internal static object CreateObjectNotCached(string ObjectProviderType) + { + string TypeName = ""; + Type objType = null; + + //get the provider configuration based on the type + ProviderConfiguration objProviderConfiguration = ProviderConfiguration.GetProviderConfiguration(ObjectProviderType); + + //get the typename of the Base DataProvider from web.config + TypeName = ((Provider) objProviderConfiguration.Providers[objProviderConfiguration.DefaultProvider]).Type; + try + { + //use reflection to get the type of the class + objType = BuildManager.GetType(TypeName, true, true); + } + catch (Exception exc) + { + //could not load the type + Exceptions.LogException(exc); + } + + //dynamically create the object + return Activator.CreateInstance(objType); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/SecurityPolicy.cs b/DNN Platform/Library/Framework/SecurityPolicy.cs new file mode 100644 index 00000000000..1f2549c3004 --- /dev/null +++ b/DNN Platform/Library/Framework/SecurityPolicy.cs @@ -0,0 +1,177 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Net; +using System.Security; +using System.Security.Permissions; +using System.Web; + +#endregion + +namespace DotNetNuke.Framework +{ + public class SecurityPolicy + { + public const string ReflectionPermission = "ReflectionPermission"; + public const string WebPermission = "WebPermission"; + public const string AspNetHostingPermission = "AspNetHostingPermission"; + private static bool m_Initialized; + private static bool m_ReflectionPermission; + private static bool m_WebPermission; + private static bool m_AspNetHostingPermission; + + public static string Permissions + { + get + { + string strPermissions = ""; + if (HasReflectionPermission()) + { + strPermissions += ", " + ReflectionPermission; + } + if (HasWebPermission()) + { + strPermissions += ", " + WebPermission; + } + if (HasAspNetHostingPermission()) + { + strPermissions += ", " + AspNetHostingPermission; + } + if (!String.IsNullOrEmpty(strPermissions)) + { + strPermissions = strPermissions.Substring(2); + } + return strPermissions; + } + } + + private static void GetPermissions() + { + if (!m_Initialized) + { + //test RelectionPermission + CodeAccessPermission securityTest; + try + { + securityTest = new ReflectionPermission(PermissionState.Unrestricted); + securityTest.Demand(); + m_ReflectionPermission = true; + } + catch + { + //code access security error + m_ReflectionPermission = false; + } + + //test WebPermission + try + { + securityTest = new WebPermission(PermissionState.Unrestricted); + securityTest.Demand(); + m_WebPermission = true; + } + catch + { + //code access security error + m_WebPermission = false; + } + + //test WebHosting Permission (Full Trust) + try + { + securityTest = new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted); + securityTest.Demand(); + m_AspNetHostingPermission = true; + } + catch + { + //code access security error + m_AspNetHostingPermission = false; + } + m_Initialized = true; + } + } + + public static bool HasAspNetHostingPermission() + { + GetPermissions(); + return m_AspNetHostingPermission; + } + + public static bool HasReflectionPermission() + { + GetPermissions(); + return m_ReflectionPermission; + } + + public static bool HasWebPermission() + { + GetPermissions(); + return m_WebPermission; + } + + public static bool HasPermissions(string permissions, ref string permission) + { + bool _HasPermission = true; + if (!String.IsNullOrEmpty(permissions)) + { + foreach (string per in (permissions + ";").Split(Convert.ToChar(";"))) + { + permission = per; + if (!String.IsNullOrEmpty(permission.Trim())) + { + switch (permission) + { + case AspNetHostingPermission: + if (HasAspNetHostingPermission() == false) + { + _HasPermission = false; + } + break; + case ReflectionPermission: + if (HasReflectionPermission() == false) + { + _HasPermission = false; + } + break; + case WebPermission: + if (HasWebPermission() == false) + { + _HasPermission = false; + } + break; + } + } + } + } + return _HasPermission; + } + + [Obsolete("Replaced by correctly spelt method")] + public static bool HasRelectionPermission() + { + GetPermissions(); + return m_ReflectionPermission; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/ServiceLocator.cs b/DNN Platform/Library/Framework/ServiceLocator.cs new file mode 100644 index 00000000000..741520bff7c --- /dev/null +++ b/DNN Platform/Library/Framework/ServiceLocator.cs @@ -0,0 +1,90 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. +using System; + +namespace DotNetNuke.Framework +{ + /// + /// Provides a readily testable way to manage a Singleton + /// + /// The interface that the controller provides + /// The type of the controller itself, used to call the GetFactory override + public abstract class ServiceLocator where TSelf : ServiceLocator, new() + { +// ReSharper disable StaticFieldInGenericType +// ReSharper disable InconsistentNaming + private static Lazy _instance = new Lazy(InitInstance, true); +// ReSharper restore InconsistentNaming + private static TContract _testableInstance; + private static bool _useTestable; +// ReSharper restore StaticFieldInGenericType + + protected static Func Factory { get; set; } + + private static TContract InitInstance() + { + if (Factory == null) + { + var controllerInstance = new TSelf(); + Factory = controllerInstance.GetFactory(); + } + + return Factory(); + } + + /// + /// Returns a singleton of T + /// + public static TContract Instance + { + get + { + if(_useTestable) + { + return _testableInstance; + } + + return _instance.Value; + } + } + + /// + /// Registers an instance to use for the Singleton + /// + /// Intended for unit testing purposes, not thread safe + /// + public static void SetTestableInstance(TContract instance) + { + _testableInstance = instance; + _useTestable = true; + } + + /// + /// Clears the current instance, a new instance will be initialized when next requested + /// + /// Intended for unit testing purposes, not thread safe + public static void ClearInstance() + { + _useTestable = false; + _testableInstance = default(TContract); + _instance = new Lazy(InitInstance, true); + } + + protected abstract Func GetFactory(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/ServicesFramework.cs b/DNN Platform/Library/Framework/ServicesFramework.cs new file mode 100644 index 00000000000..063cf7e76f4 --- /dev/null +++ b/DNN Platform/Library/Framework/ServicesFramework.cs @@ -0,0 +1,34 @@ +// // DotNetNuke® - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. + +using System; +using DotNetNuke.ComponentModel; + +namespace DotNetNuke.Framework +{ + /// + /// Enables modules to support Services Framework features + /// + public class ServicesFramework : ServiceLocator + { + protected override Func GetFactory() + { + return () => new ServicesFrameworkImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/ServicesFrameworkImpl.cs b/DNN Platform/Library/Framework/ServicesFrameworkImpl.cs new file mode 100644 index 00000000000..a74fae3da6a --- /dev/null +++ b/DNN Platform/Library/Framework/ServicesFrameworkImpl.cs @@ -0,0 +1,108 @@ +// // DotNetNuke - http://www.dotnetnuke.com +// // Copyright (c) 2002-2013 +// // by DotNetNuke Corporation +// // +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// // documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// // to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// // +// // The above copyright notice and this permission notice shall be included in all copies or substantial portions +// // of the Software. +// // +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// // DEALINGS IN THE SOFTWARE. + +using System.Globalization; +using System.Web.Helpers; +using System.Web.UI; +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.UI.Utilities; +using DotNetNuke.Web.Client.ClientResourceManagement; + +namespace DotNetNuke.Framework +{ + internal class ServicesFrameworkImpl : IServicesFramework, IServiceFrameworkInternals + { + private const string AntiForgeryKey = "dnnAntiForgeryRequested"; + private const string ScriptKey = "dnnSFAjaxScriptRequested"; + + public void RequestAjaxAntiForgerySupport() + { + RequestAjaxScriptSupport(); + SetKey(AntiForgeryKey); + } + + public bool IsAjaxAntiForgerySupportRequired + { + get { return CheckKey(AntiForgeryKey); } + } + + public void RegisterAjaxAntiForgery(Page page) + { + var ctl = page.FindControl("ClientResourcesFormBottom"); + if(ctl != null) + { + ctl.Controls.Add(new LiteralControl(AntiForgery.GetHtml().ToHtmlString())); + } + } + + public bool IsAjaxScriptSupportRequired + { + get{ return CheckKey(ScriptKey); } + } + + public void RequestAjaxScriptSupport() + { + jQuery.RequestRegistration(); + SetKey(ScriptKey); + } + + public void RegisterAjaxScript(Page page) + { + var portalSettings = TestablePortalController.Instance.GetCurrentPortalSettings(); + if (portalSettings == null) return; + var path = portalSettings.PortalAlias.HTTPAlias; + int index = path.IndexOf('/'); + if (index > 0) + { + path = path.Substring(index); + } + else + { + path = "/"; + } + path = path.EndsWith("/") ? path : path + "/"; + ClientAPI.RegisterClientReference(page, ClientAPI.ClientNamespaceReferences.dnn); + ClientAPI.RegisterClientVariable(page, "sf_siteRoot", path, /*overwrite*/ true); + ClientAPI.RegisterClientVariable(page, "sf_tabId", PortalSettings.Current.ActiveTab.TabID.ToString(CultureInfo.InvariantCulture), /*overwrite*/ true); + + string scriptPath; + if(HttpContextSource.Current.IsDebuggingEnabled) + { + scriptPath = "~/js/Debug/dnn.servicesframework.js"; + } + else + { + scriptPath = "~/js/dnn.servicesframework.js"; + } + + ClientResourceManager.RegisterScript(page, scriptPath); + } + + private static void SetKey(string key) + { + HttpContextSource.Current.Items[key] = true; + } + + private static bool CheckKey(string antiForgeryKey) + { + return HttpContextSource.Current.Items.Contains(antiForgeryKey); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/ServicesFrameworkInternal.cs b/DNN Platform/Library/Framework/ServicesFrameworkInternal.cs new file mode 100644 index 00000000000..8ff757c0cc5 --- /dev/null +++ b/DNN Platform/Library/Framework/ServicesFrameworkInternal.cs @@ -0,0 +1,12 @@ +using System; + +namespace DotNetNuke.Framework +{ + internal class ServicesFrameworkInternal : ServiceLocator + { + protected override Func GetFactory() + { + return () => new ServicesFrameworkImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Framework/UserControlBase.cs b/DNN Platform/Library/Framework/UserControlBase.cs new file mode 100644 index 00000000000..2f443dce05a --- /dev/null +++ b/DNN Platform/Library/Framework/UserControlBase.cs @@ -0,0 +1,62 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Framework +{ + /// ----------------------------------------------------------------------------- + /// + /// The UserControlBase class defines a custom base class inherited by all + /// user controls within the Portal. + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class UserControlBase : UserControl + { + public bool IsHostMenu + { + get + { + return Globals.IsHostTab(PortalSettings.ActiveTab.TabID); + } + } + + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + } +} diff --git a/DNN Platform/Library/Framework/jQuery.cs b/DNN Platform/Library/Framework/jQuery.cs new file mode 100644 index 00000000000..fc5fca48945 --- /dev/null +++ b/DNN Platform/Library/Framework/jQuery.cs @@ -0,0 +1,517 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.Caching; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Utilities; +using DotNetNuke.Web.Client.ClientResourceManagement; + +using DataCache = DotNetNuke.UI.Utilities.DataCache; +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.Framework +{ + using Web.Client; + + public class jQuery + { + private const string jQueryDebugFile = "~/Resources/Shared/Scripts/jquery/jquery.js"; + private const string jQueryMinFile = "~/Resources/Shared/Scripts/jquery/jquery.min.js"; + private const string jQueryMigrateDebugFile = "~/Resources/Shared/Scripts/jquery/jquery-migrate.js"; + private const string jQueryMigrateMinFile = "~/Resources/Shared/Scripts/jquery/jquery-migrate.min.js"; + private const string jQueryVersionKey = "jQueryVersionKey"; + private const string jQueryVersionMatch = "(?<=(jquery|core_version)\\s*[:=]\\s*\")(.*)(?=\")"; + + /// + /// Returns the default URL for a hosted version of the jQuery script + /// + /// + /// Google hosts versions of many popular javascript libraries on their CDN. + /// Using the hosted version increases the likelihood that the file is already + /// cached in the users browser. + /// + public const string DefaultHostedUrl = "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"; + + private const string jQueryUIDebugFile = "~/Resources/Shared/Scripts/jquery/jquery-ui.js"; + private const string jQueryUIMinFile = "~/Resources/Shared/Scripts/jquery/jquery-ui.min.js"; + private const string jQueryHoverIntentFile = "~/Resources/Shared/Scripts/jquery/jquery.hoverIntent.min.js"; + private const string jQueryUIVersionKey = "jQueryUIVersionKey"; + private const string jQueryUIVersionMatch = "(?<=version:\\s\")(.*)(?=\")"; + public const string DefaultUIHostedUrl = "http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"; + + #region Public Properties + + /// + /// Gets the HostSetting for the URL of the hosted version of the jQuery script. + /// + /// + /// + /// This is a simple wrapper around the Host.jQueryUrl property + public static string HostedUrl + { + get + { + if (Globals.Status != Globals.UpgradeStatus.None) + { + return String.Empty; + } + + return Host.jQueryUrl; + } + } + + /// + /// Gets the HostSetting for the URL of the hosted version of the jQuery migrated script. + /// + /// + /// + /// This is a simple wrapper around the Host.jQueryUrl property + public static string HostedMigrateUrl + { + get + { + if (Globals.Status != Globals.UpgradeStatus.None) + { + return String.Empty; + } + + return Host.jQueryMigrateUrl; + } + } + + /// + /// Gets the HostSetting for the URL of the hosted version of the jQuery UI script. + /// + /// + /// + /// This is a simple wrapper around the Host.jQueryUIUrl property + public static string HostedUIUrl + { + get + { + if (Globals.Status != Globals.UpgradeStatus.None) + { + return String.Empty; + } + + return Host.jQueryUIUrl; + } + } + + /// + /// Checks whether the jQuery core script file exists locally. + /// + /// + /// This property checks for both the minified version and the full uncompressed version of jQuery. + /// These files should exist in the /Resources/Shared/Scripts/jquery directory. + /// + public static bool IsInstalled + { + get + { + string minFile = JQueryFileMapPath(true); + string dbgFile = JQueryFileMapPath(false); + return File.Exists(minFile) || File.Exists(dbgFile); + } + } + + /// + /// Checks whether the jQuery UI core script file exists locally. + /// + /// + /// This property checks for both the minified version and the full uncompressed version of jQuery UI. + /// These files should exist in the /Resources/Shared/Scripts/jquery directory. + /// + public static bool IsUIInstalled + { + get + { + string minFile = JQueryUIFileMapPath(true); + string dbgFile = JQueryUIFileMapPath(false); + return File.Exists(minFile) || File.Exists(dbgFile); + } + } + public static bool IsRequested + { + get + { + return GetSettingAsBoolean("jQueryRequested", false); + } + } + + public static bool IsUIRequested + { + get + { + return GetSettingAsBoolean("jQueryUIRequested", false); + } + } + + public static bool AreDnnPluginsRequested + { + get + { + return GetSettingAsBoolean("jQueryDnnPluginsRequested", false); + } + } + + public static bool IsHoverIntentRequested + { + get + { + return GetSettingAsBoolean("jQueryHoverIntentRequested", false); + } + } + + /// + /// Gets the HostSetting to determine if we should use the standard jQuery script or the minified jQuery script. + /// + /// + /// + /// This is a simple wrapper around the Host.jQueryDebug property + public static bool UseDebugScript + { + get + { + if (Globals.Status != Globals.UpgradeStatus.None) + { + return false; + } + + return Host.jQueryDebug; + } + } + + /// + /// Gets the HostSetting to determine if we should use a hosted version of the jQuery script. + /// + /// + /// + /// This is a simple wrapper around the Host.jQueryHosted property + public static bool UseHostedScript + { + get + { + if (Globals.Status != Globals.UpgradeStatus.None) + { + return false; + } + + return Host.jQueryHosted; + } + } + + /// + /// Gets the version string for the local jQuery script + /// + /// + /// + /// + /// This only evaluates the version in the full jQuery file and assumes that the minified script + /// is the same version as the full script. + /// + public static string Version + { + get + { + string ver = Convert.ToString(DataCache.GetCache(jQueryVersionKey)); + if (string.IsNullOrEmpty(ver)) + { + if (IsInstalled) + { + string jqueryFileName = JQueryFileMapPath(false); + string jfiletext = File.ReadAllText(jqueryFileName); + Match verMatch = Regex.Match(jfiletext, jQueryVersionMatch); + if (verMatch != null) + { + ver = verMatch.Value; + DataCache.SetCache(jQueryVersionKey, ver, new CacheDependency(jqueryFileName)); + } + else + { + ver = Localization.GetString("jQuery.UnknownVersion.Text"); + } + } + else + { + ver = Localization.GetString("jQuery.NotInstalled.Text"); + } + } + return ver; + } + } + + /// + /// Gets the version string for the local jQuery UI script + /// + /// + /// + /// + /// This only evaluates the version in the full jQuery UI file and assumes that the minified script + /// is the same version as the full script. + /// + public static string UIVersion + { + get + { + string ver = Convert.ToString(DataCache.GetCache(jQueryUIVersionKey)); + if (string.IsNullOrEmpty(ver)) + { + if (IsUIInstalled) + { + string jqueryUIFileName = JQueryUIFileMapPath(false); + string jfiletext = File.ReadAllText(jqueryUIFileName); + Match verMatch = Regex.Match(jfiletext, jQueryUIVersionMatch); + if (verMatch != null) + { + ver = verMatch.Value; + DataCache.SetCache(jQueryUIVersionKey, ver, new CacheDependency(jqueryUIFileName)); + } + else + { + ver = Localization.GetString("jQueryUI.UnknownVersion.Text"); + } + } + else + { + ver = Localization.GetString("jQueryUI.NotInstalled.Text"); + } + } + return ver; + } + } + #endregion + + #region Private Methods + + private static bool GetSettingAsBoolean(string key, bool defaultValue) + { + bool retValue = defaultValue; + try + { + object setting = HttpContext.Current.Items[key]; + if (setting != null) + { + retValue = Convert.ToBoolean(setting); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + return retValue; + } + + #endregion + + #region Public Methods + + public static string JQueryFileMapPath(bool getMinFile) + { + return HttpContext.Current.Server.MapPath(JQueryFile(getMinFile)); + } + + public static string JQueryUIFileMapPath(bool getMinFile) + { + return HttpContext.Current.Server.MapPath(JQueryUIFile(getMinFile)); + } + + public static string JQueryFile(bool getMinFile) + { + string jfile = jQueryDebugFile; + if (getMinFile) + { + jfile = jQueryMinFile; + } + return jfile; + } + + public static string JQueryMigrateFile(bool getMinFile) + { + string jfile = jQueryMigrateDebugFile; + if (getMinFile) + { + jfile = jQueryMigrateMinFile; + } + return jfile; + } + + public static string JQueryUIFile(bool getMinFile) + { + string jfile = jQueryUIDebugFile; + if (getMinFile) + { + jfile = jQueryUIMinFile; + } + return jfile; + } + + public static string GetJQueryScriptReference() + { + string scriptsrc = HostedUrl; + if (!UseHostedScript) + { + scriptsrc = JQueryFile(!UseDebugScript); + } + return scriptsrc; + } + + public static string GetJQueryMigrateScriptReference() + { + string scriptsrc = HostedMigrateUrl; + if (!UseHostedScript || string.IsNullOrEmpty(scriptsrc)) + { + scriptsrc = JQueryMigrateFile(!UseDebugScript); + } + return scriptsrc; + } + + public static string GetJQueryUIScriptReference() + { + string scriptsrc = HostedUIUrl; + if (!UseHostedScript) + { + scriptsrc = JQueryUIFile(!UseDebugScript); + } + return scriptsrc; + } + + public static void RegisterJQuery(Page page) + { + ClientResourceManager.RegisterScript(page, GetJQueryScriptReference(), FileOrder.Js.jQuery, "DnnPageHeaderProvider"); + ClientResourceManager.RegisterScript(page, GetJQueryMigrateScriptReference(), FileOrder.Js.jQueryMigrate, "DnnPageHeaderProvider"); + } + + public static void RegisterJQueryUI(Page page) + { + RegisterJQuery(page); + ClientResourceManager.RegisterScript(page, GetJQueryUIScriptReference(), FileOrder.Js.jQueryUI, "DnnPageHeaderProvider"); + } + + public static void RegisterDnnJQueryPlugins(Page page) + { + //This method maybe called when Page.Form hasn't initialized yet, in that situation if needed should reference dnn js manually. + //such as call jQuery.RegisterDnnJQueryPlugins in Control.OnInit. + if (page.Form != null) + { + ClientAPI.RegisterClientReference(page, ClientAPI.ClientNamespaceReferences.dnn); + } + + RegisterJQueryUI(page); + RegisterHoverIntent(page); + ClientResourceManager.RegisterScript(page, "~/Resources/Shared/Scripts/dnn.jquery.js"); + } + + public static void RegisterHoverIntent(Page page) + { + ClientResourceManager.RegisterScript(page, jQueryHoverIntentFile, FileOrder.Js.HoverIntent); + } + + public static void RegisterFileUpload(Page page) + { + ClientResourceManager.RegisterScript(page, "~/Resources/Shared/Scripts/jquery/jquery.iframe-transport.js"); + ClientResourceManager.RegisterScript(page, "~/Resources/Shared/Scripts/jquery/jquery.fileupload.js"); + } + + public static void RequestRegistration() + { + HttpContext.Current.Items["jQueryRequested"] = true; + } + + public static void RequestUIRegistration() + { + HttpContext.Current.Items["jQueryUIRequested"] = true; + } + + public static void RequestDnnPluginsRegistration() + { + HttpContext.Current.Items["jQueryDnnPluginsRequested"] = true; + } + + public static void RequestHoverIntentRegistration() + { + HttpContext.Current.Items["jQueryHoverIntentRequested"] = true; + } + + /// + /// Active the page with keep alive, so that authentication will not expire. + /// + /// The page instance. + public static void KeepAlive(Page page) + { + var cookieTimeout = Config.GetAuthCookieTimeout(); + if(cookieTimeout <= 0 || page.ClientScript.IsClientScriptBlockRegistered("PageKeepAlive")) + { + return; + } + + if(cookieTimeout > 5) + { + cookieTimeout = 5; // ping server in 5 minutes to make sure the server is not IDLE. + } + RequestRegistration(); + + var seconds = (cookieTimeout*60 - 30)*1000; //ping server 30 seconds before cookie is time out. + var scriptBlock = string.Format("(function($){{setInterval(function(){{$.get(location.href)}}, {1});}}(jQuery));", Globals.ApplicationPath, seconds); + ScriptManager.RegisterClientScriptBlock(page, page.GetType(), "PageKeepAlive", scriptBlock, true); + } + + #endregion + + #region Obsolete Members + + [Obsolete("Deprecated in DNN 5.1. Replaced by IsRequested.")] + public static bool IsRquested + { + get + { + return IsRequested; + } + } + + [Obsolete("Deprecated in DNN 6.0 Replaced by RegisterJQuery.")] + public static void RegisterScript(Page page) + { + RegisterScript(page, GetJQueryScriptReference()); + } + + [Obsolete("Deprecated in DNN 6.0 Replaced by RegisterJQuery.")] + public static void RegisterScript(Page page, string script) + { + ClientResourceManager.RegisterScript(page, script); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Modules/Console/Components/ConsoleController.cs b/DNN Platform/Library/Modules/Console/Components/ConsoleController.cs new file mode 100644 index 00000000000..2256f2cde04 --- /dev/null +++ b/DNN Platform/Library/Modules/Console/Components/ConsoleController.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Exceptions; + +#endregion + +namespace DotNetNuke.Modules.Console.Components +{ + public class ConsoleController + { + public static IList GetSizeValues() + { + IList returnValue = new List(); + returnValue.Add("IconFile"); + returnValue.Add("IconFileLarge"); + returnValue.Add("IconNone"); + return returnValue; + } + + public static IList GetViewValues() + { + IList returnValue = new List(); + returnValue.Add("Hide"); + returnValue.Add("Show"); + return returnValue; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/DashboardControl.cs b/DNN Platform/Library/Modules/Dashboard/Components/DashboardControl.cs new file mode 100644 index 00000000000..9996cc9eec1 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/DashboardControl.cs @@ -0,0 +1,178 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components +{ + [Serializable] + public class DashboardControl : IComparable + { + private string _ControllerClass; + private int _DashboardControlID; + private string _DashboardControlKey; + private string _DashboardControlLocalResources; + private string _DashboardControlSrc; + private bool _IsDirty; + private bool _IsEnabled; + private int _PackageID; + private int _ViewOrder; + + public string ControllerClass + { + get + { + return _ControllerClass; + } + set + { + _ControllerClass = value; + } + } + + public int DashboardControlID + { + get + { + return _DashboardControlID; + } + set + { + _DashboardControlID = value; + } + } + + public string DashboardControlKey + { + get + { + return _DashboardControlKey; + } + set + { + _DashboardControlKey = value; + } + } + + public string DashboardControlLocalResources + { + get + { + return _DashboardControlLocalResources; + } + set + { + _DashboardControlLocalResources = value; + } + } + + public string DashboardControlSrc + { + get + { + return _DashboardControlSrc; + } + set + { + _DashboardControlSrc = value; + } + } + + public bool IsDirty + { + get + { + return _IsDirty; + } + } + + public bool IsEnabled + { + get + { + return _IsEnabled; + } + set + { + if (_IsEnabled != value) + { + _IsDirty = true; + } + _IsEnabled = value; + } + } + + public string LocalizedTitle + { + get + { + return Localization.GetString(DashboardControlKey + ".Title", "~/" + DashboardControlLocalResources); + } + } + + public int PackageID + { + get + { + return _PackageID; + } + set + { + _PackageID = value; + } + } + + public int ViewOrder + { + get + { + return _ViewOrder; + } + set + { + if (_ViewOrder != value) + { + _IsDirty = true; + } + _ViewOrder = value; + } + } + + #region IComparable Members + + public int CompareTo(object obj) + { + var dashboardControl = obj as DashboardControl; + if (dashboardControl == null) + { + throw new ArgumentException("object is not a DashboardControl"); + } + return ViewOrder.CompareTo(dashboardControl.ViewOrder); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/DashboardController.cs b/DNN Platform/Library/Modules/Dashboard/Components/DashboardController.cs new file mode 100644 index 00000000000..0ed3354405c --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/DashboardController.cs @@ -0,0 +1,104 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; +using DotNetNuke.Modules.Dashboard.Data; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components +{ + public class DashboardController + { + public static int AddDashboardControl(DashboardControl dashboardControl) + { + return DataService.AddDashboardControl(dashboardControl.PackageID, + dashboardControl.DashboardControlKey, + dashboardControl.IsEnabled, + dashboardControl.DashboardControlSrc, + dashboardControl.DashboardControlLocalResources, + dashboardControl.ControllerClass, + dashboardControl.ViewOrder); + } + + public static void DeleteControl(DashboardControl dashboardControl) + { + DataService.DeleteDashboardControl(dashboardControl.DashboardControlID); + } + + public static void Export(string filename) + { + string fullName = Path.Combine(Globals.HostMapPath, filename); + var settings = new XmlWriterSettings(); + using (XmlWriter writer = XmlWriter.Create(fullName, settings)) + { + //Write start of Dashboard + writer.WriteStartElement("dashboard"); + foreach (DashboardControl dashboard in GetDashboardControls(true)) + { + var controller = Activator.CreateInstance(Reflection.CreateType(dashboard.ControllerClass)) as IDashboardData; + if (controller != null) + { + controller.ExportData(writer); + } + } + + //Write end of Host + writer.WriteEndElement(); + writer.Flush(); + } + } + + public static DashboardControl GetDashboardControlByKey(string dashboardControlKey) + { + return CBO.FillObject(DataService.GetDashboardControlByKey(dashboardControlKey)); + } + + public static DashboardControl GetDashboardControlByPackageId(int packageId) + { + return CBO.FillObject(DataService.GetDashboardControlByPackageId(packageId)); + } + + public static List GetDashboardControls(bool isEnabled) + { + return CBO.FillCollection(DataService.GetDashboardControls(isEnabled)); + } + + public static void UpdateDashboardControl(DashboardControl dashboardControl) + { + DataService.UpdateDashboardControl(dashboardControl.DashboardControlID, + dashboardControl.DashboardControlKey, + dashboardControl.IsEnabled, + dashboardControl.DashboardControlSrc, + dashboardControl.DashboardControlLocalResources, + dashboardControl.ControllerClass, + dashboardControl.ViewOrder); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/DataService.cs b/DNN Platform/Library/Modules/Dashboard/Components/DataService.cs new file mode 100644 index 00000000000..8aa670c4e14 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/DataService.cs @@ -0,0 +1,120 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Data; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Data +{ + public class DataService + { + private static readonly DataProvider provider = DataProvider.Instance(); + private static string moduleQualifier = "Dashboard_"; + + private static string GetFullyQualifiedName(string name) + { + return String.Concat(moduleQualifier, name); + } + + public static int AddDashboardControl(int packageId, string dashboardControlKey, bool isEnabled, string dashboardControlSrc, string dashboardControlLocalResources, string controllerClass, + int viewOrder) + { + return provider.ExecuteScalar(GetFullyQualifiedName("AddControl"), + packageId, + dashboardControlKey, + isEnabled, + dashboardControlSrc, + dashboardControlLocalResources, + controllerClass, + viewOrder); + } + + public static void DeleteDashboardControl(int dashboardControlId) + { + provider.ExecuteNonQuery(GetFullyQualifiedName("DeleteControl"), dashboardControlId); + } + + public static IDataReader GetDashboardControlByKey(string dashboardControlKey) + { + return provider.ExecuteReader(GetFullyQualifiedName("GetDashboardControlByKey"), dashboardControlKey); + } + + public static IDataReader GetDashboardControlByPackageId(int packageId) + { + return provider.ExecuteReader(GetFullyQualifiedName("GetDashboardControlByPackageId"), packageId); + } + + public static IDataReader GetDashboardControls(bool isEnabled) + { + return provider.ExecuteReader(GetFullyQualifiedName("GetControls"), isEnabled); + } + + public static IDataReader GetDbInfo() + { + return provider.ExecuteReader(GetFullyQualifiedName("GetDbInfo")); + } + + public static IDataReader GetDbFileInfo() + { + return provider.ExecuteReader(GetFullyQualifiedName("GetDbFileInfo")); + } + + public static IDataReader GetDbBackups() + { + return provider.ExecuteReader(GetFullyQualifiedName("GetDbBackups")); + } + + public static IDataReader GetInstalledModules() + { + return provider.ExecuteReader(GetFullyQualifiedName("GetInstalledModules")); + } + + public static IDataReader GetPortals() + { + string cultureCode = Localization.SystemLocale; + return provider.GetPortals(cultureCode); + } + + public static IDataReader GetServerErrors() + { + return provider.ExecuteReader(GetFullyQualifiedName("GetServerErrors")); + } + + public static void UpdateDashboardControl(int dashboardControlId, string dashboardControlKey, bool isEnabled, string dashboardControlSrc, string dashboardControlLocalResources, + string controllerClass, int viewOrder) + { + provider.ExecuteNonQuery(GetFullyQualifiedName("UpdateControl"), + dashboardControlId, + dashboardControlKey, + isEnabled, + dashboardControlSrc, + dashboardControlLocalResources, + controllerClass, + viewOrder); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Database/BackupInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Database/BackupInfo.cs new file mode 100644 index 00000000000..c3b6e8d3788 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Database/BackupInfo.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Database +{ + public class BackupInfo + { + public string Name { get; set; } + + public DateTime StartDate { get; set; } + + public DateTime FinishDate { get; set; } + + public long Size { get; set; } + + public string BackupType { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Database/DatabaseController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Database/DatabaseController.cs new file mode 100644 index 00000000000..00898841ce4 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Database/DatabaseController.cs @@ -0,0 +1,107 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Modules.Dashboard.Data; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Database +{ + public class DatabaseController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + DbInfo database = GetDbInfo(); + + //Write start of Database + writer.WriteStartElement("database"); + + writer.WriteElementString("productVersion", database.ProductVersion); + writer.WriteElementString("servicePack", database.ServicePack); + writer.WriteElementString("productEdition", database.ProductEdition); + writer.WriteElementString("softwarePlatform", database.SoftwarePlatform); + + //Write start of Backups + writer.WriteStartElement("backups"); + + //Iterate through Backups + foreach (BackupInfo backup in database.Backups) + { + writer.WriteStartElement("backup"); + writer.WriteElementString("name", backup.Name); + writer.WriteElementString("backupType", backup.BackupType); + writer.WriteElementString("size", backup.Size.ToString()); + writer.WriteElementString("startDate", backup.StartDate.ToString()); + writer.WriteElementString("finishDate", backup.FinishDate.ToString()); + writer.WriteEndElement(); + } + + //Write end of Backups + writer.WriteEndElement(); + + //Write start of Files + writer.WriteStartElement("files"); + + //Iterate through Files + foreach (DbFileInfo dbFile in database.Files) + { + writer.WriteStartElement("file"); + writer.WriteElementString("name", dbFile.Name); + writer.WriteElementString("fileType", dbFile.FileType); + writer.WriteElementString("shortFileName", dbFile.ShortFileName); + writer.WriteElementString("fileName", dbFile.FileName); + writer.WriteElementString("size", dbFile.Size.ToString()); + writer.WriteElementString("megabytes", dbFile.Megabytes.ToString()); + writer.WriteEndElement(); + } + + //Write end of Files + writer.WriteEndElement(); + + //Write end of Database + writer.WriteEndElement(); + } + + #endregion + + public static DbInfo GetDbInfo() + { + return CBO.FillObject(DataService.GetDbInfo()); + } + + public static List GetDbBackups() + { + return CBO.FillCollection(DataService.GetDbBackups()); + } + + public static List GetDbFileInfo() + { + return CBO.FillCollection(DataService.GetDbFileInfo()); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Database/DbFileInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Database/DbFileInfo.cs new file mode 100644 index 00000000000..626ea640758 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Database/DbFileInfo.cs @@ -0,0 +1,60 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Database +{ + public class DbFileInfo + { + public string FileType { get; set; } + + public string Name { get; set; } + + public long Size { get; set; } + + public decimal Megabytes + { + get + { + return Convert.ToDecimal((Size/1024)); + } + } + + public string FileName { get; set; } + + public string ShortFileName + { + get + { + if(FileName.IndexOf('\\') == FileName.LastIndexOf('\\')) + { + return FileName; + } + + return string.Format("{0}...{1}", FileName.Substring(0, FileName.IndexOf('\\') + 1), FileName.Substring(FileName.LastIndexOf('\\', FileName.LastIndexOf('\\') - 1))); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Database/DbInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Database/DbInfo.cs new file mode 100644 index 00000000000..5fe2d9cbca1 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Database/DbInfo.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Database +{ + public class DbInfo + { + public string ProductVersion { get; set; } + + public string ServicePack { get; set; } + + public string ProductEdition { get; set; } + + public string SoftwarePlatform { get; set; } + + public List Backups + { + get + { + return DatabaseController.GetDbBackups(); + } + } + + public List Files + { + get + { + return DatabaseController.GetDbFileInfo(); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Host/HostController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Host/HostController.cs new file mode 100644 index 00000000000..803437f1569 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Host/HostController.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Host +{ + public class HostController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + var host = new HostInfo(); + + //Write start of Host + writer.WriteStartElement("host"); + + host.WriteXml(writer); + + //Write end of Host + writer.WriteEndElement(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Host/HostInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Host/HostInfo.cs new file mode 100644 index 00000000000..61c1050dd6d --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Host/HostInfo.cs @@ -0,0 +1,193 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Application; +using DotNetNuke.Framework; +using DotNetNuke.Framework.Providers; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Host +{ + [XmlRoot("hostInfo")] + public class HostInfo : IXmlSerializable + { + public string CachingProvider + { + get + { + return ProviderConfiguration.GetProviderConfiguration("caching").DefaultProvider; + } + } + + public string DataProvider + { + get + { + return ProviderConfiguration.GetProviderConfiguration("data").DefaultProvider; + } + } + + public string FriendlyUrlProvider + { + get + { + return ProviderConfiguration.GetProviderConfiguration("friendlyUrl").DefaultProvider; + } + } + + public string FriendlyUrlEnabled + { + get + { + return Entities.Host.Host.UseFriendlyUrls.ToString(); + } + } + + public string FriendlyUrlType + { + get + { + var urlprovider = (Provider) ProviderConfiguration.GetProviderConfiguration("friendlyUrl").Providers[FriendlyUrlProvider]; + return (urlprovider.Attributes["urlformat"] == "humanfriendly") ? "humanfriendly" : "searchfriendly"; + } + } + + public string HostGUID + { + get + { + return Entities.Host.Host.GUID; + } + } + + public string HtmlEditorProvider + { + get + { + return ProviderConfiguration.GetProviderConfiguration("htmlEditor").DefaultProvider; + } + } + + public string LoggingProvider + { + get + { + return ProviderConfiguration.GetProviderConfiguration("logging").DefaultProvider; + } + } + + public string Permissions + { + get + { + return SecurityPolicy.Permissions; + } + } + + public string Product + { + get + { + return DotNetNukeContext.Current.Application.Description; + } + } + + public string SchedulerMode + { + get + { + return Entities.Host.Host.SchedulerMode.ToString(); + } + } + + public string Version + { + get + { + return DotNetNukeContext.Current.Application.Version.ToString(3); + } + } + + public string WebFarmEnabled + { + get + { + return Services.Cache.CachingProvider.Instance().IsWebFarm().ToString(); + } + } + + public string JQueryVersion + { + get + { + return jQuery.Version; + } + } + + public string JQueryUIVersion + { + get + { + return jQuery.UIVersion; + } + } + + #region IXmlSerializable Members + + public XmlSchema GetSchema() + { + throw new NotImplementedException(); + } + + public void ReadXml(XmlReader reader) + { + throw new NotImplementedException(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteElementString("hostGUID", HostGUID); + writer.WriteElementString("version", Version); + writer.WriteElementString("permissions", Permissions); + writer.WriteElementString("dataProvider", DataProvider); + writer.WriteElementString("cachingProvider", CachingProvider); + writer.WriteElementString("friendlyUrlProvider", FriendlyUrlProvider); + writer.WriteElementString("friendlyUrlEnabled", FriendlyUrlEnabled); + writer.WriteElementString("friendlyUrlType", FriendlyUrlType); + writer.WriteElementString("htmlEditorProvider", HtmlEditorProvider); + writer.WriteElementString("loggingProvider", LoggingProvider); + writer.WriteElementString("schedulerMode", SchedulerMode); + writer.WriteElementString("webFarmEnabled", WebFarmEnabled); + + writer.WriteElementString("JQueryVersion", JQueryVersion); + writer.WriteElementString("JQueryUIVersion", JQueryUIVersion); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/IDashboardData.cs b/DNN Platform/Library/Modules/Dashboard/Components/IDashboardData.cs new file mode 100644 index 00000000000..beec88b7bae --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/IDashboardData.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components +{ + public interface IDashboardData + { + void ExportData(XmlWriter writer); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModuleInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModuleInfo.cs new file mode 100644 index 00000000000..092a5ca3b6c --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModuleInfo.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Modules +{ + public class ModuleInfo + { + public int DesktopModuleId { get; set; } + + public int Instances { get; set; } + + public string FriendlyName { get; set; } + + public string ModuleName { get; set; } + + public string Version { get; set; } + + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("module"); + + writer.WriteElementString("moduleName", ModuleName); + writer.WriteElementString("friendlyName", FriendlyName); + writer.WriteElementString("version", Version); + writer.WriteElementString("instances", Instances.ToString()); + + //Write end of Host Info + writer.WriteEndElement(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModulesController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModulesController.cs new file mode 100644 index 00000000000..45e08e871a0 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Modules/ModulesController.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Modules.Dashboard.Data; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Modules +{ + public class ModulesController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + //Write start of Installed Modules + writer.WriteStartElement("installedModules"); + + //Iterate through Installed Modules + foreach (ModuleInfo module in GetInstalledModules()) + { + module.WriteXml(writer); + } + + //Write end of Installed Modules + writer.WriteEndElement(); + } + + #endregion + + public static List GetInstalledModules() + { + return CBO.FillCollection(DataService.GetInstalledModules()); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalInfo.cs new file mode 100644 index 00000000000..f110961813c --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalInfo.cs @@ -0,0 +1,100 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Portals +{ + public class PortalInfo + { + private int _Pages = Null.NullInteger; + private int _Roles = Null.NullInteger; + private int _Users = Null.NullInteger; + + public Guid GUID { get; set; } + + public int Pages + { + get + { + if (_Pages < 0) + { + var controller = new TabController(); + _Pages = controller.GetTabCount(PortalID); + } + return _Pages; + } + } + + public int PortalID { get; set; } + + public string PortalName { get; set; } + + public int Roles + { + get + { + if (_Roles < 0) + { + _Roles = TestableRoleController.Instance.GetRoles(PortalID, r => r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).Count; + } + return _Roles; + } + } + + public int Users + { + get + { + if (_Users < 0) + { + _Users = UserController.GetUserCountByPortal(PortalID); + } + return _Users; + } + } + + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("portal"); + writer.WriteElementString("portalName", PortalName); + writer.WriteElementString("GUID", GUID.ToString()); + writer.WriteElementString("pages", Pages.ToString()); + writer.WriteElementString("users", Users.ToString()); + writer.WriteElementString("roles", Roles.ToString()); + + //Write end of Host Info + writer.WriteEndElement(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalsController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalsController.cs new file mode 100644 index 00000000000..08835d7bb88 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Portals/PortalsController.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Modules.Dashboard.Data; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Portals +{ + public class PortalsController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + //Write start of Portals + writer.WriteStartElement("portals"); + + //Iterate through Portals + foreach (PortalInfo portal in GetPortals()) + { + portal.WriteXml(writer); + } + + //Write end of Portals + writer.WriteEndElement(); + } + + #endregion + + public static List GetPortals() + { + return CBO.FillCollection(DataService.GetPortals()); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerController.cs new file mode 100644 index 00000000000..1dd4fe767ce --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerController.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Server +{ + public class ServerController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + var host = new ServerInfo(); + + //Write start of Host + writer.WriteStartElement("server"); + + host.WriteXml(writer); + + //Write end of Host + writer.WriteEndElement(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerInfo.cs new file mode 100644 index 00000000000..ebc165707a1 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Server/ServerInfo.cs @@ -0,0 +1,150 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Net; +using System.Security.Principal; +using System.Web; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Server +{ + /// + /// This class manages the Server Information for the site + /// + [XmlRoot("serverInfo")] + public class ServerInfo : IXmlSerializable + { + public string Framework + { + get + { + return Environment.Version.ToString(); + } + } + + public string HostName + { + get + { + return Dns.GetHostName(); + } + } + + public string Identity + { + get + { + return WindowsIdentity.GetCurrent().Name; + } + } + + public string IISVersion + { + get + { + return HttpContext.Current.Request.ServerVariables["SERVER_SOFTWARE"]; + } + } + + public string OSVersion + { + get + { + return Environment.OSVersion.ToString(); + } + } + + public string PhysicalPath + { + get + { + return Globals.ApplicationMapPath; + } + } + + public string Url + { + get + { + return Globals.GetDomainName(HttpContext.Current.Request); + } + } + + public string RelativePath + { + get + { + string path; + if (string.IsNullOrEmpty(Globals.ApplicationPath)) + { + path = "/"; + } + else + { + path = Globals.ApplicationPath; + } + return path; + } + } + + public string ServerTime + { + get + { + return DateTime.Now.ToString(); + } + } + + #region IXmlSerializable Members + + public XmlSchema GetSchema() + { + throw new NotImplementedException(); + } + + public void ReadXml(XmlReader reader) + { + throw new NotImplementedException(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteElementString("osVersion", OSVersion); + writer.WriteElementString("iisVersion", IISVersion); + writer.WriteElementString("framework", Framework); + writer.WriteElementString("identity", Identity); + writer.WriteElementString("hostName", HostName); + writer.WriteElementString("physicalPath", PhysicalPath); + writer.WriteElementString("url", Url); + writer.WriteElementString("relativePath", RelativePath); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinInfo.cs b/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinInfo.cs new file mode 100644 index 00000000000..715853cc4e5 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinInfo.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Skins +{ + public class SkinInfo + { + public bool InUse { get; set; } + + public string SkinFile { get; set; } + + public string SkinName { get; set; } + + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("skin"); + + writer.WriteElementString("skinName", SkinName); + writer.WriteElementString("inUse", InUse.ToString()); + + //Write end of Host Info + writer.WriteEndElement(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinsController.cs b/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinsController.cs new file mode 100644 index 00000000000..cfe1a72b749 --- /dev/null +++ b/DNN Platform/Library/Modules/Dashboard/Components/Skins/SkinsController.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Modules.Dashboard.Components.Skins +{ + public class SkinsController : IDashboardData + { + #region IDashboardData Members + + public void ExportData(XmlWriter writer) + { + //Write start of Installed Skins + writer.WriteStartElement("installedSkins"); + + //Iterate through Installed Skins + foreach (SkinInfo skin in GetInstalledSkins()) + { + skin.WriteXml(writer); + } + + //Write end of Installed Skins + writer.WriteEndElement(); + } + + #endregion + + private static bool isFallbackSkin(string skinPath) + { + SkinDefaults defaultSkin = SkinDefaults.GetSkinDefaults(SkinDefaultType.SkinInfo); + string defaultSkinPath = (Globals.HostMapPath + SkinController.RootSkin + defaultSkin.Folder).Replace("/", "\\"); + if (defaultSkinPath.EndsWith("\\")) + { + defaultSkinPath = defaultSkinPath.Substring(0, defaultSkinPath.Length - 1); + } + return skinPath.IndexOf(defaultSkinPath, StringComparison.CurrentCultureIgnoreCase) != -1; + } + + public static List GetInstalledSkins() + { + var list = new List(); + foreach (string folder in Directory.GetDirectories(Path.Combine(Globals.HostMapPath, "Skins"))) + { + if (!folder.EndsWith(Globals.glbHostSkinFolder)) + { + var skin = new SkinInfo(); + skin.SkinName = folder.Substring(folder.LastIndexOf("\\") + 1); + skin.InUse = isFallbackSkin(folder) || !SkinController.CanDeleteSkin(folder, ""); + list.Add(skin); + } + } + return list; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/HtmlEditorProvider.cs b/DNN Platform/Library/Modules/HtmlEditorProvider.cs new file mode 100644 index 00000000000..68112c7a193 --- /dev/null +++ b/DNN Platform/Library/Modules/HtmlEditorProvider.cs @@ -0,0 +1,54 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Modules.HTMLEditorProvider +{ + public abstract class HtmlEditorProvider : UserControlBase + { + public abstract Control HtmlEditorControl { get; } + public abstract ArrayList AdditionalToolbars { get; set; } + public abstract string ControlID { get; set; } + public abstract string RootImageDirectory { get; set; } + public abstract string Text { get; set; } + public abstract Unit Width { get; set; } + public abstract Unit Height { get; set; } + + //return the provider + public static HtmlEditorProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + public abstract void AddToolbar(); + + public abstract void Initialize(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/NavigationProvider.cs b/DNN Platform/Library/Modules/NavigationProvider.cs new file mode 100644 index 00000000000..841b8086e0e --- /dev/null +++ b/DNN Platform/Library/Modules/NavigationProvider.cs @@ -0,0 +1,1009 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Web.UI; + +using DotNetNuke.Framework; +using DotNetNuke.UI.Skins; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Modules.NavigationProvider +{ + public abstract class NavigationProvider : UserControlBase + { + #region Delegates + + public delegate void NodeClickEventHandler(NavigationEventArgs args); + + public delegate void PopulateOnDemandEventHandler(NavigationEventArgs args); + + #endregion + + #region Alignment enum + + public enum Alignment + { + Left, + Right, + Center, + Justify + } + + #endregion + + #region HoverAction enum + + public enum HoverAction + { + Expand, + None + } + + #endregion + + #region HoverDisplay enum + + public enum HoverDisplay + { + Highlight, + Outset, + None + } + + #endregion + + #region Orientation enum + + public enum Orientation + { + Horizontal, + Vertical + } + + #endregion + + #region "Properties" + + public abstract Control NavigationControl { get; } + public abstract string ControlID { get; set; } + public abstract bool SupportsPopulateOnDemand { get; } + + public virtual string PathImage + { + get + { + return ""; + } + set + { + } + } + + public virtual string PathSystemImage + { + get + { + return ""; + } + set + { + } + } + + public virtual string PathSystemScript + { + get + { + return ""; + } + set + { + } + } + + public virtual string WorkImage + { + get + { + return ""; + } + set + { + } + } + + public virtual string IndicateChildImageSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string IndicateChildImageRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string IndicateChildImageExpandedSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string IndicateChildImageExpandedRoot + { + get + { + return ""; + } + set + { + } + } + + public abstract string CSSControl { get; set; } + + public virtual string CSSContainerRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSContainerSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNode + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSIcon + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeHover + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeHoverSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeHoverRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSBreak + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSIndicateChildSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSIndicateChildRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSBreadCrumbSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSBreadCrumbRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeSelectedSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSNodeSelectedRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSSeparator + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSLeftSeparator + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSRightSeparator + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSLeftSeparatorSelection + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSRightSeparatorSelection + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSLeftSeparatorBreadCrumb + { + get + { + return ""; + } + set + { + } + } + + public virtual string CSSRightSeparatorBreadCrumb + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleBackColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleForeColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleHighlightColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleIconBackColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleSelectionBorderColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleSelectionColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleSelectionForeColor + { + get + { + return ""; + } + set + { + } + } + + public virtual decimal StyleControlHeight + { + get + { + return 25; + } + set + { + } + } + + public virtual decimal StyleBorderWidth + { + get + { + return 0; + } + set + { + } + } + + public virtual decimal StyleNodeHeight + { + get + { + return 25; + } + set + { + } + } + + public virtual decimal StyleIconWidth + { + get + { + return 0; + } + set + { + } + } + + public virtual string StyleFontNames + { + get + { + return ""; + } + set + { + } + } + + public virtual decimal StyleFontSize + { + get + { + return 0; + } + set + { + } + } + + public virtual string StyleFontBold + { + get + { + return "False"; + } + set + { + } + } + + public virtual string StyleRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string StyleSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string EffectsStyle + { + get + { + return ""; + } + set + { + } + } + + public virtual string EffectsTransition + { + get + { + return "'"; + } + set + { + } + } + + public virtual double EffectsDuration + { + get + { + return -1; + } + set + { + } + } + + public virtual string EffectsShadowColor + { + get + { + return ""; + } + set + { + } + } + + public virtual string EffectsShadowDirection + { + get + { + return ""; + } + set + { + } + } + + public virtual int EffectsShadowStrength + { + get + { + return -1; + } + set + { + } + } + + public virtual Orientation ControlOrientation + { + get + { + return Orientation.Horizontal; + } + set + { + } + } + + public virtual Alignment ControlAlignment + { + get + { + return Alignment.Left; + } + set + { + } + } + + public virtual string ForceDownLevel + { + get + { + return false.ToString(); + } + set + { + } + } + + public virtual decimal MouseOutHideDelay + { + get + { + return -1; + } + set + { + } + } + + public virtual HoverDisplay MouseOverDisplay + { + get + { + return HoverDisplay.Highlight; + } + set + { + } + } + + public virtual HoverAction MouseOverAction + { + get + { + return HoverAction.Expand; + } + set + { + } + } + + public virtual string ForceCrawlerDisplay + { + get + { + return "False"; + } + set + { + } + } + + public virtual bool IndicateChildren + { + get + { + return true; + } + set + { + } + } + + public virtual string SeparatorHTML + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorLeftHTML + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorRightHTML + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorLeftHTMLActive + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorRightHTMLActive + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorLeftHTMLBreadCrumb + { + get + { + return ""; + } + set + { + } + } + + public virtual string SeparatorRightHTMLBreadCrumb + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeLeftHTMLSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeLeftHTMLRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeRightHTMLSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeRightHTMLRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeLeftHTMLBreadCrumbSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeRightHTMLBreadCrumbSub + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeLeftHTMLBreadCrumbRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual string NodeRightHTMLBreadCrumbRoot + { + get + { + return ""; + } + set + { + } + } + + public virtual bool PopulateNodesFromClient + { + get + { + return false; + } + set + { + } + } + + public virtual List CustomAttributes + { + get + { + return null; + } + set + { + } + } + + + #endregion + + #region "Methods" + + public event NodeClickEventHandler NodeClick; + public event PopulateOnDemandEventHandler PopulateOnDemand; + + public static NavigationProvider Instance(string FriendlyName) + { + return (NavigationProvider) Reflection.CreateObject("navigationControl", FriendlyName, "", ""); + } + + public abstract void Initialize(); + + public abstract void Bind(DNNNodeCollection objNodes); + + public virtual void ClearNodes() + { + } + + protected void RaiseEvent_NodeClick(DNNNode objNode) + { + if (NodeClick != null) + { + NodeClick(new NavigationEventArgs(objNode.ID, objNode)); + } + } + + protected void RaiseEvent_NodeClick(string strID) + { + if (NodeClick != null) + { + NodeClick(new NavigationEventArgs(strID, null)); + } + } + + protected void RaiseEvent_PopulateOnDemand(DNNNode objNode) + { + if (PopulateOnDemand != null) + { + PopulateOnDemand(new NavigationEventArgs(objNode.ID, objNode)); + } + } + + protected void RaiseEvent_PopulateOnDemand(string strID) + { + if (PopulateOnDemand != null) + { + PopulateOnDemand(new NavigationEventArgs(strID, null)); + } + } + + #endregion + } + + public class NavigationEventArgs + { + public string ID; + public DNNNode Node; + + public NavigationEventArgs(string strID, DNNNode objNode) + { + ID = strID; + Node = objNode; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/SearchInput/SearchInputController.cs b/DNN Platform/Library/Modules/SearchInput/SearchInputController.cs new file mode 100644 index 00000000000..18e69a41177 --- /dev/null +++ b/DNN Platform/Library/Modules/SearchInput/SearchInputController.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Modules.SearchInput +{ + public class SearchInputController + { + public ArrayList GetSearchResultModules(int PortalID) + { + return CBO.FillCollection(DataProvider.Instance().GetSearchResultModules(PortalID), typeof (SearchResultsModuleInfo)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Modules/SearchInput/SearchResultsModuleInfo.cs b/DNN Platform/Library/Modules/SearchInput/SearchResultsModuleInfo.cs new file mode 100644 index 00000000000..857e12c90f2 --- /dev/null +++ b/DNN Platform/Library/Modules/SearchInput/SearchResultsModuleInfo.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Modules.SearchInput +{ + public class SearchResultsModuleInfo + { + public int TabID { get; set; } + + public string SearchTabName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/AspNetMembershipProvider.cs b/DNN Platform/Library/Security/Membership/AspNetMembershipProvider.cs new file mode 100644 index 00000000000..a3fa63b0904 --- /dev/null +++ b/DNN Platform/Library/Security/Membership/AspNetMembershipProvider.cs @@ -0,0 +1,1868 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography; +using System.Text; +using System.Web; +using System.Web.Security; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Users; +using DotNetNuke.Entities.Users.Membership; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Security.Membership +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Provider.AspNetProvider + /// Class: AspNetMembershipProvider + /// ----------------------------------------------------------------------------- + /// + /// The AspNetMembershipProvider overrides the default MembershipProvider to provide + /// an AspNet Membership Component (MemberRole) implementation + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class AspNetMembershipProvider : MembershipProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AspNetMembershipProvider)); + + #region Private Members + + private readonly DataProvider _dataProvider = DataProvider.Instance(); + + #endregion + + #region Public Properties + + public override bool CanEditProviderProperties + { + get { return false; } + } + + public override int MaxInvalidPasswordAttempts + { + get { return System.Web.Security.Membership.MaxInvalidPasswordAttempts; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override int MinNonAlphanumericCharacters + { + get { return System.Web.Security.Membership.MinRequiredNonAlphanumericCharacters; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override int MinPasswordLength + { + get { return System.Web.Security.Membership.MinRequiredPasswordLength; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override int PasswordAttemptWindow + { + get { return System.Web.Security.Membership.PasswordAttemptWindow; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override PasswordFormat PasswordFormat + { + get + { + switch (System.Web.Security.Membership.Provider.PasswordFormat) + { + case MembershipPasswordFormat.Encrypted: + return PasswordFormat.Encrypted; + case MembershipPasswordFormat.Hashed: + return PasswordFormat.Hashed; + default: + return PasswordFormat.Clear; + } + } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override bool PasswordResetEnabled + { + get { return System.Web.Security.Membership.EnablePasswordReset; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override bool PasswordRetrievalEnabled + { + get { return System.Web.Security.Membership.EnablePasswordRetrieval; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override string PasswordStrengthRegularExpression + { + get { return System.Web.Security.Membership.PasswordStrengthRegularExpression; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override bool RequiresQuestionAndAnswer + { + get { return System.Web.Security.Membership.RequiresQuestionAndAnswer; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + public override bool RequiresUniqueEmail + { + get { return System.Web.Security.Membership.Provider.RequiresUniqueEmail; } + set + { + throw new NotSupportedException( + "Provider properties for AspNetMembershipProvider must be set in web.config"); + } + } + + #endregion + + #region Private Methods + + private static bool AutoUnlockUser(MembershipUser aspNetUser) + { + if (Host.AutoAccountUnlockDuration != 0) + { + if (aspNetUser.LastLockoutDate < DateTime.Now.AddMinutes(-1*Host.AutoAccountUnlockDuration)) + { + //Unlock user in Data Store + if (aspNetUser.UnlockUser()) + { + return true; + } + } + } + return false; + } + + private UserCreateStatus CreateDNNUser(ref UserInfo user) + { + var objSecurity = new PortalSecurity(); + string userName = objSecurity.InputFilter(user.Username, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string email = objSecurity.InputFilter(user.Email, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string lastName = objSecurity.InputFilter(user.LastName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string firstName = objSecurity.InputFilter(user.FirstName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + var createStatus = UserCreateStatus.Success; + string displayName = objSecurity.InputFilter(user.DisplayName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + if (displayName.Contains("<")) + { + displayName = HttpUtility.HtmlEncode(displayName); + } + bool updatePassword = user.Membership.UpdatePassword; + bool isApproved = user.Membership.Approved; + try + { + user.UserID = + Convert.ToInt32(_dataProvider.AddUser(user.PortalID, + userName, + firstName, + lastName, + user.AffiliateID, + user.IsSuperUser, + email, + displayName, + updatePassword, + isApproved, + UserController.GetCurrentUserInfo().UserID)); + } + catch (Exception ex) + { + //Clear User (duplicate User information) + Exceptions.LogException(ex); + user = null; + createStatus = UserCreateStatus.ProviderError; + } + return createStatus; + } + + private static UserCreateStatus CreateMemberhipUser(UserInfo user) + { + var portalSecurity = new PortalSecurity(); + string userName = portalSecurity.InputFilter(user.Username, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string email = portalSecurity.InputFilter(user.Email, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + MembershipCreateStatus status; + if (MembershipProviderConfig.RequiresQuestionAndAnswer) + { + System.Web.Security.Membership.CreateUser(userName, + user.Membership.Password, + email, + user.Membership.PasswordQuestion, + user.Membership.PasswordAnswer, + true, + out status); + } + else + { + System.Web.Security.Membership.CreateUser(userName, + user.Membership.Password, + email, + null, + null, + true, + out status); + } + var createStatus = UserCreateStatus.Success; + switch (status) + { + case MembershipCreateStatus.DuplicateEmail: + createStatus = UserCreateStatus.DuplicateEmail; + break; + case MembershipCreateStatus.DuplicateProviderUserKey: + createStatus = UserCreateStatus.DuplicateProviderUserKey; + break; + case MembershipCreateStatus.DuplicateUserName: + createStatus = UserCreateStatus.DuplicateUserName; + break; + case MembershipCreateStatus.InvalidAnswer: + createStatus = UserCreateStatus.InvalidAnswer; + break; + case MembershipCreateStatus.InvalidEmail: + createStatus = UserCreateStatus.InvalidEmail; + break; + case MembershipCreateStatus.InvalidPassword: + createStatus = UserCreateStatus.InvalidPassword; + break; + case MembershipCreateStatus.InvalidProviderUserKey: + createStatus = UserCreateStatus.InvalidProviderUserKey; + break; + case MembershipCreateStatus.InvalidQuestion: + createStatus = UserCreateStatus.InvalidQuestion; + break; + case MembershipCreateStatus.InvalidUserName: + createStatus = UserCreateStatus.InvalidUserName; + break; + case MembershipCreateStatus.ProviderError: + createStatus = UserCreateStatus.ProviderError; + break; + case MembershipCreateStatus.UserRejected: + createStatus = UserCreateStatus.UserRejected; + break; + } + return createStatus; + } + + private static void DeleteMembershipUser(UserInfo user) + { + try + { + System.Web.Security.Membership.DeleteUser(user.Username, true); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + private static ArrayList FillUserCollection(int portalId, IDataReader dr, ref int totalRecords) + { + //Note: the DataReader returned from this method should contain 2 result sets. The first set + // contains the TotalRecords, that satisfy the filter, the second contains the page + // of data + var arrUsers = new ArrayList(); + try + { + while (dr.Read()) + { + //fill business object + UserInfo user = FillUserInfo(portalId, dr, false); + //add to collection + arrUsers.Add(user); + } + //Get the next result (containing the total) + dr.NextResult(); + + //Get the total no of records from the second result + totalRecords = Globals.GetTotalRecords(ref dr); + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arrUsers; + } + + private static IList FillUserList(int portalId, IDataReader dr) + { + var users = new List(); + try + { + while (dr.Read()) + { + //fill business object + UserInfo user = FillUserAndProfile(portalId, dr); + //add to collection + users.Add(user); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return users; + } + + private static UserInfo FillUserAndProfile(int portalId, IDataReader dr) + { + UserInfo user = null; + bool bContinue = (String.Equals(dr.GetName(0), "UserID", StringComparison.InvariantCultureIgnoreCase)); + + //Ensure the data reader returned is valid + if (bContinue) + { + user = new UserInfo + { + PortalID = Null.SetNullInteger(dr["PortalID"]), + IsSuperUser = Null.SetNullBoolean(dr["IsSuperUser"]), + IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]), + UserID = Null.SetNullInteger(dr["UserID"]), + DisplayName = Null.SetNullString(dr["DisplayName"]), + Username = Null.SetNullString(dr["Username"]), + Email = Null.SetNullString(dr["Email"]), + AffiliateID = Null.SetNullInteger(dr["AffiliateID"]) + }; + user.AffiliateID = Null.SetNullInteger(Null.SetNull(dr["AffiliateID"], user.AffiliateID)); + + UserController.GetUserMembership(user); + user.Membership.UpdatePassword = Null.SetNullBoolean(dr["UpdatePassword"]); + if (!user.IsSuperUser) + { + user.Membership.Approved = Null.SetNullBoolean(dr["Authorised"]); + } + if (user.PortalID == Null.NullInteger) + { + user.PortalID = portalId; + } + + var userProfile = new UserProfile(user); + userProfile.InitialiseProfile(portalId); + + for (int i = 0; i < dr.FieldCount; i++) + { + switch (dr.GetName(i)) + { + case "PortalID": + case "IsSuperUser": + case "IsDeleted": + case "UserID": + case "DisplayName": + case "Username": + case "Email": + case "AffiliateID": + case "UpdatePassword": + case "Authorised": + case "CreateDate": + case "LastActivityDate": + case "LastLockoutDate": + case "LastLoginDate": + case "LastPasswordChangedDate": + case "IsLockedOut": + case "PasswordQuestion": + case "IsApproved": + case "PasswordResetToken": + case "PasswordResetExpiration": + break; + default: + //Probably a profile property + string name = dr.GetName(i); + userProfile.SetProfileProperty(name, Null.SetNullString(dr[name])); + break; + } + } + + user.Profile = userProfile; + } + return user; + } + + private static UserInfo FillUserInfo(int portalId, IDataReader dr, bool closeDataReader) + { + UserInfo user = null; + try + { + //read datareader + bool bContinue = true; + if (closeDataReader) + { + bContinue = false; + if (dr.Read()) + { + //Ensure the data reader returned is valid + if (string.Equals(dr.GetName(0), "UserID", StringComparison.InvariantCultureIgnoreCase)) + { + bContinue = true; + } + } + } + if (bContinue) + { + user = new UserInfo + { + PortalID = Null.SetNullInteger(dr["PortalID"]), + IsSuperUser = Null.SetNullBoolean(dr["IsSuperUser"]), + UserID = Null.SetNullInteger(dr["UserID"]), + FirstName = Null.SetNullString(dr["FirstName"]), + LastName = Null.SetNullString(dr["LastName"]), + DisplayName = Null.SetNullString(dr["DisplayName"]) + }; + + var schema = dr.GetSchemaTable(); + if (schema != null) + { + if (schema.Select("ColumnName = 'IsDeleted'").Length > 0) + { + user.IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]); + } + if (schema.Select("ColumnName = 'VanityUrl'").Length > 0) + { + user.VanityUrl = Null.SetNullString(dr["VanityUrl"]); + } + } + + user.AffiliateID = Null.SetNullInteger(Null.SetNull(dr["AffiliateID"], user.AffiliateID)); + user.Username = Null.SetNullString(dr["Username"]); + UserController.GetUserMembership(user); + user.Email = Null.SetNullString(dr["Email"]); + user.Membership.UpdatePassword = Null.SetNullBoolean(dr["UpdatePassword"]); + + if (schema != null) + { + if (schema.Select("ColumnName = 'PasswordResetExpiration'").Length > 0) + { + user.PasswordResetExpiration = Null.SetNullDateTime(dr["PasswordResetExpiration"]); + } + if (schema.Select("ColumnName = 'PasswordResetToken'").Length > 0) + { + user.PasswordResetToken = Null.SetNullGuid(dr["PasswordResetToken"]); + } + } + if (!user.IsSuperUser) + { + user.Membership.Approved = Null.SetNullBoolean(dr["Authorised"]); + } + if (user.PortalID == Null.NullInteger) + { + user.PortalID = portalId; + } + + user.FillBaseProperties(dr); + } + } + finally + { + CBO.CloseDataReader(dr, closeDataReader); + } + return user; + } + + private static void FillUserMembership(MembershipUser aspNetUser, UserInfo user) + { + //Fill Membership Property + if (aspNetUser != null) + { + if (user.Membership == null) + { + user.Membership = new UserMembership(user); + } + user.Membership.CreatedDate = aspNetUser.CreationDate; + user.Membership.LastActivityDate = aspNetUser.LastActivityDate; + user.Membership.LastLockoutDate = aspNetUser.LastLockoutDate; + user.Membership.LastLoginDate = aspNetUser.LastLoginDate; + user.Membership.LastPasswordChangeDate = aspNetUser.LastPasswordChangedDate; + user.Membership.LockedOut = aspNetUser.IsLockedOut; + user.Membership.PasswordQuestion = aspNetUser.PasswordQuestion; + user.Membership.IsDeleted = user.IsDeleted; + + if (user.IsSuperUser) + { + //For superusers the Approved info is stored in aspnet membership + user.Membership.Approved = aspNetUser.IsApproved; + } + } + } + + private static MembershipUser GetMembershipUser(UserInfo user) + { + return GetMembershipUser(user.Username); + } + + private static MembershipUser GetMembershipUser(string userName) + { + return + CBO.GetCachedObject( + new CacheItemArgs(GetCacheKey(userName), DataCache.UserCacheTimeOut, DataCache.UserCachePriority, + userName), GetMembershipUserCallBack); + } + + private static string GetCacheKey(string userName) + { + return String.Format("MembershipUser_{0}", userName); + } + + private static object GetMembershipUserCallBack(CacheItemArgs cacheItemArgs) + { + string userName = cacheItemArgs.ParamList[0].ToString(); + + return System.Web.Security.Membership.GetUser(userName); + } + + private void AddPasswordHistory(string password,int retained) + { + HashAlgorithm ha = HashAlgorithm.Create(); + byte[] newSalt = GetRandomSaltValue(); + byte[] bytePassword = Encoding.Unicode.GetBytes(password); + byte[] inputBuffer = new byte[bytePassword.Length + 16]; + Buffer.BlockCopy(bytePassword, 0, inputBuffer, 0, bytePassword.Length); + Buffer.BlockCopy(newSalt, 0, inputBuffer, bytePassword.Length, 16); + byte[] bhashedPassword = ha.ComputeHash(inputBuffer); + string hashedPassword = Convert.ToBase64String(bhashedPassword); + + _dataProvider.AddPasswordHistory(UserController.GetCurrentUserInfo().UserID, hashedPassword, Convert.ToBase64String(newSalt),retained); + } + + private byte[] GetRandomSaltValue() + { + RNGCryptoServiceProvider rcsp = new RNGCryptoServiceProvider(); + byte[] bSalt = new byte[16]; + rcsp.GetBytes(bSalt); + return bSalt; + } + + private bool GetPasswordHistory(string password) + { + //use default algorithm (SHA1CryptoServiceProvider ) + HashAlgorithm ha = HashAlgorithm.Create(); + bool foundMatch = false; + + var t = new MembershipPasswordController(); + List history = t.GetPasswordHistory(); + foreach (var ph in history) + { + string oldEncodedPassword = ph.Password; + string oldEncodedSalt = ph.PasswordSalt; + byte[] oldSalt = Convert.FromBase64String(oldEncodedSalt); + byte[] bytePassword = Encoding.Unicode.GetBytes(password); + byte[] inputBuffer = new byte[bytePassword.Length + 16]; + Buffer.BlockCopy(bytePassword, 0, inputBuffer, 0, bytePassword.Length); + Buffer.BlockCopy(oldSalt, 0, inputBuffer, bytePassword.Length, 16); + byte[] bhashedPassword = ha.ComputeHash(inputBuffer); + string hashedPassword = Convert.ToBase64String(bhashedPassword); + if (hashedPassword == oldEncodedPassword) + foundMatch = true; + } + + return foundMatch; + } + + private UserInfo GetUserByAuthToken(int portalId, string userToken, string authType) + { + IDataReader dr = _dataProvider.GetUserByAuthToken(portalId, userToken, authType); + UserInfo objUserInfo = FillUserInfo(portalId, dr, true); + return objUserInfo; + } + + private static void UpdateUserMembership(UserInfo user) + { + var portalSecurity = new PortalSecurity(); + string email = portalSecurity.InputFilter(user.Email, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + + //Persist the Membership Properties to the AspNet Data Store + MembershipUser membershipUser = System.Web.Security.Membership.GetUser(user.Username); + membershipUser.Email = email; + membershipUser.LastActivityDate = DateTime.Now; + if (user.IsSuperUser) + { + membershipUser.IsApproved = user.Membership.Approved; + } + System.Web.Security.Membership.UpdateUser(membershipUser); + DataCache.RemoveCache(GetCacheKey(user.Username)); + } + + private static UserLoginStatus ValidateLogin(string username, string authType, UserInfo user, + UserLoginStatus loginStatus, string password, ref bool bValid, + int portalId) + { + if (loginStatus != UserLoginStatus.LOGIN_USERLOCKEDOUT && + (loginStatus != UserLoginStatus.LOGIN_USERNOTAPPROVED || user.IsInRole("Unverified Users"))) + { + if (authType == "DNN") + { + if (user.IsSuperUser) + { + if (ValidateUser(username, password)) + { + loginStatus = UserLoginStatus.LOGIN_SUPERUSER; + bValid = true; + } + } + else + { + if (ValidateUser(username, password)) + { + loginStatus = UserLoginStatus.LOGIN_SUCCESS; + bValid = true; + } + } + } + else + { + if (user.IsSuperUser) + { + loginStatus = UserLoginStatus.LOGIN_SUPERUSER; + bValid = true; + } + else + { + loginStatus = UserLoginStatus.LOGIN_SUCCESS; + bValid = true; + } + } + } + return loginStatus; + } + + private static bool ValidateUser(string username, string password) + { + return System.Web.Security.Membership.ValidateUser(username, password); + } + + #endregion + + #region Public Methods + /// + /// add new userportal record (used for creating sites with existing user) + /// + /// portalid + /// userid + public override void AddUserPortal(int portalId, int userId) + { + Requires.NotNullOrEmpty("portalId", portalId.ToString()); + Requires.NotNullOrEmpty("userId", userId.ToString()); + _dataProvider.AddUserPortal(portalId, userId); + } + + /// + /// function supports the ability change username + /// + /// user id + /// updated username + public override void ChangeUsername(int userId, string newUsername) + { + Requires.NotNull("userId", userId); + Requires.NotNullOrEmpty("newUsername", newUsername); + + _dataProvider.ChangeUsername(userId, newUsername); + var objEventLog = new EventLogController(); + objEventLog.AddLog("userId", + userId.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.USERNAME_UPDATED); + DataCache.ClearCache(); + } + + /// ----------------------------------------------------------------------------- + /// + /// ChangePassword attempts to change the users password + /// + /// + /// + /// The user to update. + /// The old password. + /// The new password. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public override bool ChangePassword(UserInfo user, string oldPassword, string newPassword) + { + MembershipUser aspnetUser = GetMembershipUser(user); + var settings = new MembershipPasswordSettings(user.PortalID); + + if (settings.EnablePasswordHistory) + { + if (GetPasswordHistory(newPassword) == false) + { + AddPasswordHistory(newPassword,settings.NumberOfPasswordsStored); + } + else + { + throw new SecurityException("Cannot use that password"); + } + + } + + if (string.IsNullOrEmpty(oldPassword)) + { + aspnetUser.UnlockUser(); + oldPassword = aspnetUser.GetPassword(); + } + bool retValue = aspnetUser.ChangePassword(oldPassword, newPassword); + if (retValue && PasswordRetrievalEnabled && !RequiresQuestionAndAnswer) + { + string confirmPassword = aspnetUser.GetPassword(); + if (confirmPassword == newPassword) + { + user.Membership.Password = confirmPassword; + } + else + { + retValue = false; + } + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// ChangePasswordQuestionAndAnswer attempts to change the users password Question + /// and PasswordAnswer + /// + /// + /// + /// The user to update. + /// The password. + /// The new password question. + /// The new password answer. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public override bool ChangePasswordQuestionAndAnswer(UserInfo user, string password, string passwordQuestion, + string passwordAnswer) + { + MembershipUser aspnetUser = GetMembershipUser(user); + if (password == Null.NullString) + { + password = aspnetUser.GetPassword(); + } + return aspnetUser.ChangePasswordQuestionAndAnswer(password, passwordQuestion, passwordAnswer); + } + + private UserCreateStatus ValidateForProfanity(UserInfo user) + { + var portalSecurity = new PortalSecurity(); + var createStatus = UserCreateStatus.AddUser; + + Hashtable settings = UserController.GetUserSettings(user.PortalID); + bool useProfanityFilter = Convert.ToBoolean(settings["Registration_UseProfanityFilter"]); + + //Validate Profanity + if (useProfanityFilter) + { + if (!portalSecurity.ValidateInput(user.Username, PortalSecurity.FilterFlag.NoProfanity)) + { + createStatus = UserCreateStatus.InvalidUserName; + } + if (!String.IsNullOrEmpty(user.DisplayName)) + { + if (!portalSecurity.ValidateInput(user.DisplayName, PortalSecurity.FilterFlag.NoProfanity)) + { + createStatus = UserCreateStatus.InvalidDisplayName; + } + } + } + return createStatus; + } + + private void ValidateForDuplicateDisplayName(UserInfo user, ref UserCreateStatus createStatus) + { + Hashtable settings = UserController.GetUserSettings(user.PortalID); + bool requireUniqueDisplayName = Convert.ToBoolean(settings["Registration_RequireUniqueDisplayName"]); + + if (requireUniqueDisplayName) + { + UserInfo duplicateUser = GetUserByDisplayName(Null.NullInteger, user.DisplayName); + if (duplicateUser != null) + { + createStatus = UserCreateStatus.DuplicateDisplayName; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateUser persists a User to the Data Store + /// + /// + /// + /// The user to persist to the Data Store. + /// A UserCreateStatus enumeration indicating success or reason for failure. + /// ----------------------------------------------------------------------------- + public override UserCreateStatus CreateUser(ref UserInfo user) + { + UserCreateStatus createStatus = ValidateForProfanity(user); + + if (createStatus == UserCreateStatus.AddUser) + { + ValidateForDuplicateDisplayName(user, ref createStatus); + } + + if (createStatus == UserCreateStatus.AddUser) + { + try + { + //check if username exists in database for any portal + UserInfo objVerifyUser = GetUserByUserName(Null.NullInteger, user.Username); + if (objVerifyUser != null) + { + //the username exists so we should now verify the password + if (ValidateUser(user.Username, user.Membership.Password)) + { + //check if user exists for the portal specified + objVerifyUser = GetUserByUserName(user.PortalID, user.Username); + if (objVerifyUser != null) + { + if (objVerifyUser.PortalID == user.PortalID && !user.IsSuperUser) + { + createStatus = UserCreateStatus.UserAlreadyRegistered; + } + else + { + //SuperUser who is not part of portal + createStatus = UserCreateStatus.AddUserToPortal; + } + } + else + { + createStatus = UserCreateStatus.AddUserToPortal; + } + } + else + { + //not the same person - prevent registration + createStatus = UserCreateStatus.UsernameAlreadyExists; + } + } + else + { + //the user does not exist + createStatus = UserCreateStatus.AddUser; + } + + //If new user - add to aspnet membership + if (createStatus == UserCreateStatus.AddUser) + { + createStatus = CreateMemberhipUser(user); + } + + //If asp user has been successfully created or we are adding a existing user + //to a new portal + if (createStatus == UserCreateStatus.Success || createStatus == UserCreateStatus.AddUserToPortal) + { + //Create the DNN User Record + createStatus = CreateDNNUser(ref user); + if (createStatus == UserCreateStatus.Success) + { + //Persist the Profile to the Data Store + ProfileController.UpdateUserProfile(user); + } + } + } + catch (Exception exc) //an unexpected error occurred + { + Exceptions.LogException(exc); + createStatus = UserCreateStatus.UnexpectedError; + } + } + + return createStatus; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteUser deletes a single User from the Data Store + /// + /// + /// + /// The user to delete from the Data Store. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public override bool DeleteUser(UserInfo user) + { + bool retValue = true; + try + { + _dataProvider.DeleteUserFromPortal(user.UserID, user.PortalID); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + retValue = false; + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes all UserOnline inof from the database that has activity outside of the + /// time window + /// + /// + /// + /// Time Window in Minutes + /// ----------------------------------------------------------------------------- + public override void DeleteUsersOnline(int timeWindow) + { + _dataProvider.DeleteUsersOnline(timeWindow); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates a new random password (Length = Minimum Length + 4) + /// + /// A String + /// ----------------------------------------------------------------------------- + public override string GeneratePassword() + { + return GeneratePassword(MinPasswordLength + 4); + } + + /// ----------------------------------------------------------------------------- + /// + /// Generates a new random password + /// + /// The length of password to generate. + /// A String + /// ----------------------------------------------------------------------------- + public override string GeneratePassword(int length) + { + return System.Web.Security.Membership.GeneratePassword(length, MinNonAlphanumericCharacters); + } + + public override ArrayList GetDeletedUsers(int portalId) + { + return FillUserCollection(portalId, _dataProvider.GetDeletedUsers(portalId)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a collection of Online Users + /// + /// The Id of the Portal + /// An ArrayList of UserInfo objects + /// ----------------------------------------------------------------------------- + public override ArrayList GetOnlineUsers(int portalId) + { + int totalRecords = 0; + return FillUserCollection(portalId, _dataProvider.GetOnlineUsers(portalId), ref totalRecords); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Current Password Information for the User + /// + /// + /// + /// The user to delete from the Data Store. + /// The answer to the Password Question, ues to confirm the user + /// has the right to obtain the password. + /// A String + /// ----------------------------------------------------------------------------- + public override string GetPassword(UserInfo user, string passwordAnswer) + { + MembershipUser aspnetUser = GetMembershipUser(user); + if (aspnetUser.IsLockedOut) + { + AutoUnlockUser(aspnetUser); + } + return RequiresQuestionAndAnswer ? aspnetUser.GetPassword(passwordAnswer) : aspnetUser.GetPassword(); + } + + public override ArrayList GetUnAuthorizedUsers(int portalId) + { + return GetUnAuthorizedUsers(portalId, false, false); + } + + public override ArrayList GetUnAuthorizedUsers(int portalId, bool includeDeleted, bool superUsersOnly) + { + return FillUserCollection(portalId, + _dataProvider.GetUnAuthorizedUsers(portalId, includeDeleted, superUsersOnly)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByUserName retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The id of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo GetUser(int portalId, int userId) + { + IDataReader dr = _dataProvider.GetUser(portalId, userId); + UserInfo objUserInfo = FillUserInfo(portalId, dr, true); + return objUserInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByDisplayName retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The displayName of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo GetUserByDisplayName(int portalId, string displayName) + { + IDataReader dr = _dataProvider.GetUserByDisplayName(portalId, displayName); + UserInfo objUserInfo = FillUserInfo(portalId, dr, true); + return objUserInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByUserName retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The username of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo GetUserByUserName(int portalId, string username) + { + IDataReader dr = _dataProvider.GetUserByUsername(portalId, username); + UserInfo objUserInfo = FillUserInfo(portalId, dr, true); + return objUserInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserByVanityUrl retrieves a User from the DataStore + /// + /// + /// + /// The Id of the Portal + /// The vanityUrl of the user being retrieved from the Data Store. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo GetUserByVanityUrl(int portalId, string vanityUrl) + { + UserInfo user = null; + if (!String.IsNullOrEmpty(vanityUrl)) + { + IDataReader dr = _dataProvider.GetUserByVanityUrl(portalId, vanityUrl); + user = FillUserInfo(portalId, dr, true); + } + return user; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserCountByPortal gets the number of users in the portal + /// + /// + /// + /// The Id of the Portal + /// The no of users + /// ----------------------------------------------------------------------------- + public override int GetUserCountByPortal(int portalId) + { + return _dataProvider.GetUserCountByPortal(portalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserMembership retrieves the UserMembership information from the Data Store + /// + /// + /// + /// The user whose Membership information we are retrieving. + /// ----------------------------------------------------------------------------- + public override void GetUserMembership(ref UserInfo user) + { + //Get AspNet MembershipUser + MembershipUser aspnetUser = GetMembershipUser(user); + + //Fill Membership Property + FillUserMembership(aspnetUser, user); + + //Get Online Status + user.Membership.IsOnLine = IsUserOnline(user); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsers(portalId, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsers gets all the users of the portal + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include deleted users. + /// Only select super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords, + bool includeDeleted, bool superUsersOnly) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + + return FillUserCollection(portalId, _dataProvider.GetAllUsers(portalId, pageIndex, pageSize, includeDeleted, + superUsersOnly), ref totalRecords); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public override IList GetUsersAdvancedSearch(int portalId, int userId, int filterUserId, + int filterRoleId, int relationshipTypeId, + bool isAdmin, int pageIndex, int pageSize, + string sortColumn, + bool sortAscending, string propertyNames, + string propertyValues) + { + return FillUserList(portalId, + _dataProvider.GetUsersAdvancedSearch(portalId, userId, filterUserId, filterRoleId, + relationshipTypeId, isAdmin, pageIndex, pageSize, + sortColumn, sortAscending, propertyNames, + propertyValues)); + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public override IList GetUsersBasicSearch(int portalId, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyName, + string propertyValue) + { + return FillUserList(portalId, _dataProvider.GetUsersBasicSearch(portalId, pageIndex, pageSize, + sortColumn, sortAscending, propertyName, + propertyValue)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByEmail gets all the users of the portal whose email matches a provided + /// filter expression + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The email address to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, + ref int totalRecords) + { + return GetUsersByEmail(portalId, emailToMatch, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByEmail gets all the users of the portal whose email matches a provided + /// filter expression + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The email address to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include deleted users. + /// Only select super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, + ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + + return FillUserCollection(portalId, + _dataProvider.GetUsersByEmail(portalId, emailToMatch, pageIndex, pageSize, + includeDeleted, superUsersOnly), ref totalRecords); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByUserName gets all the users of the portal whose username matches a provided + /// filter expression + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The username to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, + ref int totalRecords) + { + return GetUsersByUserName(portalId, userNameToMatch, pageIndex, pageSize, ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByUserName gets all the users of the portal whose username matches a provided + /// filter expression + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The username to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include deleted users. + /// Only select super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, + ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + + return FillUserCollection(portalId, + _dataProvider.GetUsersByUsername(portalId, userNameToMatch, pageIndex, pageSize, + includeDeleted, superUsersOnly), ref totalRecords); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByDisplayName gets all the users of the portal whose display name matches a provided + /// filter expression + /// + /// If all records are required, (ie no paging) set pageSize = -1 + /// The Id of the Portal + /// The display name to use to find a match. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include deleted users. + /// Only select super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByDisplayName(int portalId, string nameToMatch, int pageIndex, int pageSize, + ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + + return FillUserCollection(portalId, + _dataProvider.GetUsersByDisplayname(portalId, nameToMatch, pageIndex, pageSize, + includeDeleted, superUsersOnly), ref totalRecords); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByProfileProperty gets all the users of the portal whose profile matches + /// the profile property pased as a parameter + /// + /// + /// + /// The Id of the Portal + /// The name of the property being matched. + /// The value of the property being matched. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, + int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByProfileProperty(portalId, propertyName, propertyValue, pageIndex, pageSize, + ref totalRecords, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUsersByProfileProperty gets all the users of the portal whose profile matches + /// the profile property pased as a parameter + /// + /// + /// + /// The Id of the Portal + /// The name of the property being matched. + /// The value of the property being matched. + /// The page of records to return. + /// The size of the page + /// The total no of records that satisfy the criteria. + /// Include deleted users. + /// Only select super users. + /// An ArrayList of UserInfo objects. + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, + int pageIndex, int pageSize, ref int totalRecords, + bool includeDeleted, bool superUsersOnly) + { + if (pageIndex == -1) + { + pageIndex = 0; + pageSize = int.MaxValue; + } + + return FillUserCollection(portalId, + _dataProvider.GetUsersByProfileProperty(portalId, propertyName, propertyValue, + pageIndex, pageSize, includeDeleted, + superUsersOnly), ref totalRecords); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the user in question is online + /// + /// + /// + /// The user. + /// A Boolean indicating whether the user is online. + /// ----------------------------------------------------------------------------- + public override bool IsUserOnline(UserInfo user) + { + bool isOnline = false; + var objUsersOnline = new UserOnlineController(); + if (objUsersOnline.IsEnabled()) + { + Hashtable userList = objUsersOnline.GetUserList(); + var onlineUser = (OnlineUserInfo) userList[user.UserID.ToString()]; + if (onlineUser != null) + { + isOnline = true; + } + else + { + //Next try the Database + onlineUser = + (OnlineUserInfo) + CBO.FillObject(_dataProvider.GetOnlineUser(user.UserID), typeof (OnlineUserInfo)); + if (onlineUser != null) + { + isOnline = true; + } + } + } + return isOnline; + } + + public override bool RemoveUser(UserInfo user) + { + bool retValue = true; + + try + { + foreach (var relationship in user.Social.UserRelationships) + { + RelationshipController.Instance.DeleteUserRelationship(relationship); + } + + _dataProvider.RemoveUser(user.UserID, user.PortalID); + + //Prior to removing membership, ensure user is not present in any other portal + UserInfo otherUser = GetUserByUserName(Null.NullInteger, user.Username); + if (otherUser == null) + { + DeleteMembershipUser(user); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + retValue = false; + } + + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// ResetPassword resets a user's password and returns the newly created password + /// + /// + /// + /// The user to update. + /// The answer to the user's password Question. + /// The new Password. + /// ----------------------------------------------------------------------------- + public override string ResetPassword(UserInfo user, string passwordAnswer) + { + //Get AspNet MembershipUser + MembershipUser aspnetUser = GetMembershipUser(user); + + return RequiresQuestionAndAnswer ? aspnetUser.ResetPassword(passwordAnswer) : aspnetUser.ResetPassword(); + } + + /// + /// function sets user specific password reset token and timeout + /// works for all PasswordFormats as it resets and then changes the password + /// so old password is not required + /// method does not support RequiresQuestionAndAnswer + /// + /// + public override bool ResetAndChangePassword(UserInfo user,string newPassword) + { + if (RequiresQuestionAndAnswer) + { + return false; + } + + //Get AspNet MembershipUser + MembershipUser aspnetUser = GetMembershipUser(user); + + string resetPassword = ResetPassword(user,String.Empty); + return aspnetUser.ChangePassword(resetPassword, newPassword); + } + + public override bool RestoreUser(UserInfo user) + { + bool retValue = true; + + try + { + _dataProvider.RestoreUser(user.UserID, user.PortalID); + } + catch (Exception ex) + { + Exceptions.LogException(ex); + retValue = false; + } + + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Unlocks the User's Account + /// + /// + /// + /// The user whose account is being Unlocked. + /// True if successful, False if unsuccessful. + /// ----------------------------------------------------------------------------- + public override bool UnLockUser(UserInfo user) + { + MembershipUser membershipUser = System.Web.Security.Membership.GetUser(user.Username); + bool retValue = false; + if (membershipUser != null) + { + retValue = membershipUser.UnlockUser(); + } + DataCache.RemoveCache(GetCacheKey(user.Username)); + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateUser persists a user to the Data Store + /// + /// + /// + /// The user to persist to the Data Store. + /// ----------------------------------------------------------------------------- + public override void UpdateUser(UserInfo user) + { + var objSecurity = new PortalSecurity(); + string firstName = objSecurity.InputFilter(user.FirstName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string lastName = objSecurity.InputFilter(user.LastName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string email = objSecurity.InputFilter(user.Email, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + string displayName = objSecurity.InputFilter(user.DisplayName, + PortalSecurity.FilterFlag.NoScripting | + PortalSecurity.FilterFlag.NoAngleBrackets | + PortalSecurity.FilterFlag.NoMarkup); + if (displayName.Contains("<")) + { + displayName = HttpUtility.HtmlEncode(displayName); + } + string vanityUrl = HttpContext.Current.Server.HtmlEncode(user.VanityUrl); + + bool updatePassword = user.Membership.UpdatePassword; + bool isApproved = user.Membership.Approved; + if (String.IsNullOrEmpty(displayName)) + { + displayName = firstName + " " + lastName; + } + + //Persist the Membership to the Data Store + UpdateUserMembership(user); + + //Persist the DNN User to the Database + _dataProvider.UpdateUser(user.UserID, + user.PortalID, + firstName, + lastName, + user.IsSuperUser, + email, + displayName, + vanityUrl, + updatePassword, + isApproved, + false, + user.LastIPAddress, + user.PasswordResetToken, + user.PasswordResetExpiration, + user.IsDeleted, + UserController.GetCurrentUserInfo().UserID); + + //Persist the Profile to the Data Store + ProfileController.UpdateUserProfile(user); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates UserOnline info + /// time window + /// + /// List of users to update + /// ----------------------------------------------------------------------------- + public override void UpdateUsersOnline(Hashtable userList) + { + _dataProvider.UpdateUsersOnline(userList); + } + + /// ----------------------------------------------------------------------------- + /// + /// UserLogin attempts to log the user in, and returns the User if successful + /// + /// + /// + /// The Id of the Portal the user belongs to + /// The user name of the User attempting to log in + /// The password of the User attempting to log in + /// The verification code of the User attempting to log in + /// An enumerated value indicating the login status. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo UserLogin(int portalId, string username, string password, string verificationCode, + ref UserLoginStatus loginStatus) + { + return UserLogin(portalId, username, password, "DNN", verificationCode, ref loginStatus); + } + + /// ----------------------------------------------------------------------------- + /// + /// UserLogin attempts to log the user in, and returns the User if successful + /// + /// + /// + /// The Id of the Portal the user belongs to + /// The user name of the User attempting to log in + /// The password of the User attempting to log in (may not be used by all Auth types) + /// The type of Authentication Used + /// The verification code of the User attempting to log in + /// An enumerated value indicating the login status. + /// The User as a UserInfo object + /// ----------------------------------------------------------------------------- + public override UserInfo UserLogin(int portalId, string username, string password, string authType, + string verificationCode, ref UserLoginStatus loginStatus) + { + //For now, we are going to ignore the possibility that the User may exist in the + //Global Data Store but not in the Local DataStore ie. A shared Global Data Store + + //Initialise Login Status to Failure + loginStatus = UserLoginStatus.LOGIN_FAILURE; + + DataCache.ClearUserCache(portalId, username); + DataCache.ClearCache(GetCacheKey(username)); + + //Get a light-weight (unhydrated) DNN User from the Database, we will hydrate it later if neccessary + UserInfo user = (authType == "DNN") + ? GetUserByUserName(portalId, username) + : GetUserByAuthToken(portalId, username, authType); + if (user != null && !user.IsDeleted) + { + //Get AspNet MembershipUser + MembershipUser aspnetUser = GetMembershipUser(user); + + //Fill Membership Property from AspNet MembershipUser + FillUserMembership(aspnetUser, user); + + //Check if the User is Locked Out (and unlock if AutoUnlock has expired) + if (aspnetUser.IsLockedOut) + { + if (AutoUnlockUser(aspnetUser)) + { + //Unlock User + user.Membership.LockedOut = false; + } + else + { + loginStatus = UserLoginStatus.LOGIN_USERLOCKEDOUT; + } + } + + //Check in a verified situation whether the user is Approved + if (user.Membership.Approved == false && user.IsSuperUser == false) + { + //Check Verification code + var ps = new PortalSecurity(); + if (verificationCode == ps.EncryptString(portalId + "-" + user.UserID, Config.GetDecryptionkey())) + { + UserController.ApproveUser(user); + } + else + { + loginStatus = UserLoginStatus.LOGIN_USERNOTAPPROVED; + } + } + + //Verify User Credentials + bool bValid = false; + loginStatus = ValidateLogin(username, authType, user, loginStatus, password, ref bValid, portalId); + if (!bValid) + { + //Clear the user object + user = null; + } + } + else + { + //Clear the user object + user = null; + } + return user; + } + + #endregion + + public static ArrayList FillUserCollection(int portalId, IDataReader dr) + { + //Note: the DataReader returned from this method should contain 2 result sets. The first set + // contains the TotalRecords, that satisfy the filter, the second contains the page + // of data + var arrUsers = new ArrayList(); + try + { + while (dr.Read()) + { + //fill business object + UserInfo user = FillUserInfo(portalId, dr, false); + //add to collection + arrUsers.Add(user); + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arrUsers; + } + + #region Obsolete Methods + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override ArrayList GetUnAuthorizedUsers(int portalId, bool isHydrated) + { + return GetUnAuthorizedUsers(portalId); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override UserInfo GetUser(int portalId, int userId, bool isHydrated) + { + return GetUser(portalId, userId); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override UserInfo GetUserByUserName(int portalId, string username, bool isHydrated) + { + return GetUserByUserName(portalId, username); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override ArrayList GetUsers(int portalId, bool isHydrated, int pageIndex, int pageSize, + ref int totalRecords) + { + return GetUsers(portalId, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override ArrayList GetUsersByEmail(int portalId, bool isHydrated, string emailToMatch, int pageIndex, + int pageSize, ref int totalRecords) + { + return GetUsersByEmail(portalId, emailToMatch, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override ArrayList GetUsersByUserName(int portalId, bool isHydrated, string userNameToMatch, + int pageIndex, int pageSize, ref int totalRecords) + { + return GetUsersByUserName(portalId, userNameToMatch, pageIndex, pageSize, ref totalRecords); + } + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public override ArrayList GetUsersByProfileProperty(int portalId, bool isHydrated, string propertyName, + string propertyValue, int pageIndex, int pageSize, + ref int totalRecords) + { + return GetUsersByProfileProperty(portalId, propertyName, propertyValue, pageIndex, pageSize, + ref totalRecords); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/MembershipProvider.cs b/DNN Platform/Library/Security/Membership/MembershipProvider.cs new file mode 100644 index 00000000000..f771267d429 --- /dev/null +++ b/DNN Platform/Library/Security/Membership/MembershipProvider.cs @@ -0,0 +1,204 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Security.Membership +{ + public abstract class MembershipProvider + { + #region Abstract Properties + + public abstract bool CanEditProviderProperties { get; } + public abstract int MaxInvalidPasswordAttempts { get; set; } + public abstract int MinPasswordLength { get; set; } + public abstract int MinNonAlphanumericCharacters { get; set; } + public abstract int PasswordAttemptWindow { get; set; } + public abstract PasswordFormat PasswordFormat { get; set; } + public abstract bool PasswordResetEnabled { get; set; } + public abstract bool PasswordRetrievalEnabled { get; set; } + public abstract string PasswordStrengthRegularExpression { get; set; } + public abstract bool RequiresQuestionAndAnswer { get; set; } + public abstract bool RequiresUniqueEmail { get; set; } + + #endregion + + #region Shared/Static Methods + + //return the provider + public static MembershipProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region Abstract Methods + + // Users + public abstract bool ChangePassword(UserInfo user, string oldPassword, string newPassword); + public abstract bool ChangePasswordQuestionAndAnswer(UserInfo user, string password, string passwordQuestion, string passwordAnswer); + public abstract UserCreateStatus CreateUser(ref UserInfo user); + public abstract bool DeleteUser(UserInfo user); + public abstract bool RestoreUser(UserInfo user); + public abstract bool RemoveUser(UserInfo user); + public abstract string GeneratePassword(); + public abstract string GeneratePassword(int length); + public abstract string GetPassword(UserInfo user, string passwordAnswer); + public abstract int GetUserCountByPortal(int portalId); + public abstract void GetUserMembership(ref UserInfo user); + public abstract string ResetPassword(UserInfo user, string passwordAnswer); + public abstract bool UnLockUser(UserInfo user); + public abstract void UpdateUser(UserInfo user); + public abstract UserInfo UserLogin(int portalId, string username, string password, string verificationCode, ref UserLoginStatus loginStatus); + public abstract UserInfo UserLogin(int portalId, string username, string password, string authType, string verificationCode, ref UserLoginStatus loginStatus); + + // Users Online + public abstract void DeleteUsersOnline(int TimeWindow); + public abstract ArrayList GetOnlineUsers(int PortalId); + public abstract bool IsUserOnline(UserInfo user); + public abstract void UpdateUsersOnline(Hashtable UserList); + + // Legacy + public virtual void TransferUsersToMembershipProvider() + { + } + + // Get Users + public abstract UserInfo GetUser(int portalId, int userId); + public abstract UserInfo GetUserByUserName(int portalId, string username); + public abstract ArrayList GetUnAuthorizedUsers(int portalId); + public abstract ArrayList GetDeletedUsers(int portalId); + public abstract ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords); + public abstract ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords); + public abstract ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords); + public abstract ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords); + + #endregion + + #region Virtual Methods + + public virtual UserInfo GetUserByDisplayName(int portalId, string displayName) + { + return null; + } + + public virtual UserInfo GetUserByVanityUrl(int portalId, string vanityUrl) + { + return null; + } + + public virtual ArrayList GetUsers(int portalId, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual ArrayList GetUsersByEmail(int portalId, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual ArrayList GetUsersByUserName(int portalId, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual ArrayList GetUsersByDisplayName(int portalId, string nameToMatch, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual ArrayList GetUsersByProfileProperty(int portalId, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual ArrayList GetUnAuthorizedUsers(int portalId, bool includeDeleted, bool superUsersOnly) + { + throw new NotImplementedException(); + } + + public virtual IList GetUsersAdvancedSearch(int portalId, int userId, int filterUserId, int filterRoleId, int relationTypeId, + bool isAdmin, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyNames, string propertyValues) + { + throw new NotImplementedException(); + } + + public virtual IList GetUsersBasicSearch(int portalId, int pageIndex, int pageSize, string sortColumn, + bool sortAscending, string propertyName, string propertyValue) + { + throw new NotImplementedException(); + } + + public virtual bool ResetAndChangePassword(UserInfo user, string newPassword) + { + throw new NotImplementedException(); + } + + + public virtual void ChangeUsername(int userId, string newUsername) + { + throw new NotImplementedException(); + } + + public virtual void AddUserPortal(int portalId, int userId) + { + throw new NotImplementedException(); + } + + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract ArrayList GetUnAuthorizedUsers(int portalId, bool isHydrated); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract UserInfo GetUser(int portalId, int userId, bool isHydrated); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract UserInfo GetUserByUserName(int portalId, string username, bool isHydrated); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract ArrayList GetUsers(int portalId, bool isHydrated, int pageIndex, int pageSize, ref int totalRecords); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract ArrayList GetUsersByEmail(int portalId, bool isHydrated, string emailToMatch, int pageIndex, int pageSize, ref int totalRecords); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract ArrayList GetUsersByUserName(int portalId, bool isHydrated, string userNameToMatch, int pageIndex, int pageSize, ref int totalRecords); + + [Obsolete("Deprecated in 5.1 as Ishydrated is no longer supported")] + public abstract ArrayList GetUsersByProfileProperty(int portalId, bool isHydrated, string propertyName, string propertyValue, int pageIndex, int pageSize, ref int totalRecords); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/MembershipProviderConfig.cs b/DNN Platform/Library/Security/Membership/MembershipProviderConfig.cs new file mode 100644 index 00000000000..ada7733eb6c --- /dev/null +++ b/DNN Platform/Library/Security/Membership/MembershipProviderConfig.cs @@ -0,0 +1,303 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; + +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Security.Membership +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Membership + /// Class: MembershipProviderConfig + /// ----------------------------------------------------------------------------- + /// + /// The MembershipProviderConfig class provides a wrapper to the Membership providers + /// configuration + /// + /// + /// + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + public class MembershipProviderConfig + { + #region "Private Shared Members" + + private static readonly MembershipProvider memberProvider = MembershipProvider.Instance(); + + #endregion + + #region "Public Shared Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Provider Properties can be edited + /// + /// A Boolean + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public static bool CanEditProviderProperties + { + get + { + return memberProvider.CanEditProviderProperties; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the maximum number of invlaid attempts to login are allowed + /// + /// A Boolean. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(8), Category("Password")] + public static int MaxInvalidPasswordAttempts + { + get + { + return memberProvider.MaxInvalidPasswordAttempts; + } + set + { + memberProvider.MaxInvalidPasswordAttempts = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Mimimum no of Non AlphNumeric characters required + /// + /// An Integer. + /// + /// [cnurse] 02/07/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(5), Category("Password")] + public static int MinNonAlphanumericCharacters + { + get + { + return memberProvider.MinNonAlphanumericCharacters; + } + set + { + memberProvider.MinNonAlphanumericCharacters = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Mimimum Password Length + /// + /// An Integer. + /// + /// [cnurse] 02/07/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(4), Category("Password")] + public static int MinPasswordLength + { + get + { + return memberProvider.MinPasswordLength; + } + set + { + memberProvider.MinPasswordLength = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the window in minutes that the maxium attempts are tracked for + /// + /// A Boolean. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(9), Category("Password")] + public static int PasswordAttemptWindow + { + get + { + return memberProvider.PasswordAttemptWindow; + } + set + { + memberProvider.PasswordAttemptWindow = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Password Format + /// + /// A PasswordFormat enumeration. + /// + /// [cnurse] 02/07/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(1), Category("Password")] + public static PasswordFormat PasswordFormat + { + get + { + return memberProvider.PasswordFormat; + } + set + { + memberProvider.PasswordFormat = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Users's Password can be reset + /// + /// A Boolean. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(3), Category("Password")] + public static bool PasswordResetEnabled + { + get + { + return memberProvider.PasswordResetEnabled; + } + set + { + memberProvider.PasswordResetEnabled = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Users's Password can be retrieved + /// + /// A Boolean. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(2), Category("Password")] + public static bool PasswordRetrievalEnabled + { + get + { + bool enabled = memberProvider.PasswordRetrievalEnabled; + + //If password format is hashed the password cannot be retrieved + if (memberProvider.PasswordFormat == PasswordFormat.Hashed) + { + enabled = false; + } + return enabled; + } + set + { + memberProvider.PasswordRetrievalEnabled = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a Regular Expression that deermines the strength of the password + /// + /// A String. + /// + /// [cnurse] 02/07/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(7), Category("Password")] + public static string PasswordStrengthRegularExpression + { + get + { + return memberProvider.PasswordStrengthRegularExpression; + } + set + { + memberProvider.PasswordStrengthRegularExpression = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether a Question/Answer is required for Password retrieval + /// + /// A Boolean. + /// + /// [cnurse] 02/07/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(6), Category("Password")] + public static bool RequiresQuestionAndAnswer + { + get + { + return memberProvider.RequiresQuestionAndAnswer; + } + set + { + memberProvider.RequiresQuestionAndAnswer = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether a Unique Email is required + /// + /// A Boolean. + /// + /// [cnurse] 02/06/2007 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(0), Category("User")] + public static bool RequiresUniqueEmail + { + get + { + return memberProvider.RequiresUniqueEmail; + } + set + { + memberProvider.RequiresUniqueEmail = value; + } + + #endregion + } + } +} diff --git a/DNN Platform/Library/Security/Membership/PasswordConfig.cs b/DNN Platform/Library/Security/Membership/PasswordConfig.cs new file mode 100644 index 00000000000..e91907e32ac --- /dev/null +++ b/DNN Platform/Library/Security/Membership/PasswordConfig.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; + +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.Security.Membership +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Membership + /// Class: PasswordConfig + /// ----------------------------------------------------------------------------- + /// + /// The PasswordConfig class provides a wrapper any Portal wide Password Settings + /// + /// + /// + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + public class PasswordConfig + { + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Password Expiry time in days + /// + /// An integer. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(0), Category("Password")] + public static int PasswordExpiry + { + get + { + return Host.PasswordExpiry; + } + set + { + HostController.Instance.Update("PasswordExpiry", value.ToString()); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the a Reminder time in days (to remind the user that theire password + /// is about to expire + /// + /// An integer. + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [SortOrder(1), Category("Password")] + public static int PasswordExpiryReminder + { + get + { + return Host.PasswordExpiryReminder; + } + set + { + HostController.Instance.Update("PasswordExpiryReminder", value.ToString()); + } + } + } +} diff --git a/DNN Platform/Library/Security/Membership/PasswordFormat.cs b/DNN Platform/Library/Security/Membership/PasswordFormat.cs new file mode 100644 index 00000000000..48a8acffa17 --- /dev/null +++ b/DNN Platform/Library/Security/Membership/PasswordFormat.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum PasswordFormat + { + Clear = 0, + Hashed = 1, + Encrypted = 2 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/PasswordUpdateStatus.cs b/DNN Platform/Library/Security/Membership/PasswordUpdateStatus.cs new file mode 100644 index 00000000000..311ea47dddf --- /dev/null +++ b/DNN Platform/Library/Security/Membership/PasswordUpdateStatus.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum PasswordUpdateStatus + { + Success, + PasswordMissing, + PasswordNotDifferent, + PasswordResetFailed, + PasswordInvalid, + PasswordMismatch, + InvalidPasswordAnswer, + InvalidPasswordQuestion, + BannedPasswordUsed + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/UserCreateStatus.cs b/DNN Platform/Library/Security/Membership/UserCreateStatus.cs new file mode 100644 index 00000000000..a58c754cf88 --- /dev/null +++ b/DNN Platform/Library/Security/Membership/UserCreateStatus.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum UserCreateStatus + { + AddUser = 0, + UsernameAlreadyExists = 1, + UserAlreadyRegistered = 2, + DuplicateEmail = 3, + DuplicateProviderUserKey = 4, + DuplicateUserName = 5, + InvalidAnswer = 6, + InvalidEmail = 7, + InvalidPassword = 8, + InvalidProviderUserKey = 9, + InvalidQuestion = 10, + InvalidUserName = 11, + ProviderError = 12, + Success = 13, + UnexpectedError = 14, + UserRejected = 15, + PasswordMismatch = 16, + AddUserToPortal = 17, + InvalidDisplayName = 18, + DuplicateDisplayName = 19, + BannedPasswordUsed = 20 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/UserLoginStatus.cs b/DNN Platform/Library/Security/Membership/UserLoginStatus.cs new file mode 100644 index 00000000000..775e429282d --- /dev/null +++ b/DNN Platform/Library/Security/Membership/UserLoginStatus.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum UserLoginStatus + { + LOGIN_FAILURE = 0, + LOGIN_SUCCESS = 1, + LOGIN_SUPERUSER = 2, + LOGIN_USERLOCKEDOUT = 3, + LOGIN_USERNOTAPPROVED = 4, + LOGIN_INSECUREADMINPASSWORD = 5, + LOGIN_INSECUREHOSTPASSWORD = 6 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/UserRegistrationStatus.cs b/DNN Platform/Library/Security/Membership/UserRegistrationStatus.cs new file mode 100644 index 00000000000..1abf1a55552 --- /dev/null +++ b/DNN Platform/Library/Security/Membership/UserRegistrationStatus.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum UserRegistrationStatus + { + AddUser = 0, + AddUserRoles = -1, + UsernameAlreadyExists = -2, + UserAlreadyRegistered = -3, + UnexpectedError = -4 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Membership/UserValidStatus.cs b/DNN Platform/Library/Security/Membership/UserValidStatus.cs new file mode 100644 index 00000000000..76d4534592b --- /dev/null +++ b/DNN Platform/Library/Security/Membership/UserValidStatus.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security.Membership +{ + public enum UserValidStatus + { + VALID = 0, + PASSWORDEXPIRED = 1, + PASSWORDEXPIRING = 2, + UPDATEPROFILE = 3, + UPDATEPASSWORD = 4 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Permissions/CompareDesktopModulePermissions.cs b/DNN Platform/Library/Security/Permissions/CompareDesktopModulePermissions.cs new file mode 100644 index 00000000000..d469cceb37f --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/CompareDesktopModulePermissions.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : CompareDesktopModulePermissions + /// ----------------------------------------------------------------------------- + /// + /// CompareDesktopModulePermissions provides the a custom IComparer implementation for + /// DesktopModulePermissionInfo objects + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + internal class CompareDesktopModulePermissions : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((DesktopModulePermissionInfo) x).DesktopModulePermissionID.CompareTo(((DesktopModulePermissionInfo) y).DesktopModulePermissionID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/CompareFolderPermissions.cs b/DNN Platform/Library/Security/Permissions/CompareFolderPermissions.cs new file mode 100644 index 00000000000..f89613e0c2b --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/CompareFolderPermissions.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : CompareTabPermissions + /// ----------------------------------------------------------------------------- + /// + /// CompareTabPermissions provides the a custom IComparer implementation for + /// TabPermissionInfo objects + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + internal class CompareFolderPermissions : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((FolderPermissionInfo) x).FolderPermissionID.CompareTo(((FolderPermissionInfo) y).FolderPermissionID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/CompareModulePermissions.cs b/DNN Platform/Library/Security/Permissions/CompareModulePermissions.cs new file mode 100644 index 00000000000..de8e056dc2d --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/CompareModulePermissions.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : CompareModulePermissions + /// ----------------------------------------------------------------------------- + /// + /// CompareModulePermissions provides the a custom IComparer implementation for + /// ModulePermissionInfo objects + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + internal class CompareModulePermissions : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((ModulePermissionInfo) x).ModulePermissionID.CompareTo(((ModulePermissionInfo) y).ModulePermissionID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/CompareTabPermissions.cs b/DNN Platform/Library/Security/Permissions/CompareTabPermissions.cs new file mode 100644 index 00000000000..02f016fd1d5 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/CompareTabPermissions.cs @@ -0,0 +1,53 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : CompareTabPermissions + /// ----------------------------------------------------------------------------- + /// + /// CompareTabPermissions provides the a custom IComparer implementation for + /// TabPermissionInfo objects + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + internal class CompareTabPermissions : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((TabPermissionInfo) x).TabPermissionID.CompareTo(((TabPermissionInfo) y).TabPermissionID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/Controls/DesktopModulePermissionsGrid.cs b/DNN Platform/Library/Security/Permissions/Controls/DesktopModulePermissionsGrid.cs new file mode 100644 index 00000000000..99b1ac7ef55 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/Controls/DesktopModulePermissionsGrid.cs @@ -0,0 +1,348 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Security.Permissions.Controls +{ + public class DesktopModulePermissionsGrid : PermissionsGrid + { + #region "Private Members" + + private DesktopModulePermissionCollection _DesktopModulePermissions; + private List _PermissionsList; + private int _PortalDesktopModuleID = -1; + + #endregion + + #region "Protected Properties" + + protected override List PermissionsList + { + get + { + if (_PermissionsList == null && _DesktopModulePermissions != null) + { + _PermissionsList = _DesktopModulePermissions.ToList(); + } + return _PermissionsList; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Permissions Collection + /// + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + public DesktopModulePermissionCollection Permissions + { + get + { + //First Update Permissions in case they have been changed + UpdatePermissions(); + + //Return the DesktopModulePermissions + return _DesktopModulePermissions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Id of the PortalDesktopModule + /// + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int PortalDesktopModuleID + { + get + { + return _PortalDesktopModuleID; + } + set + { + int oldValue = _PortalDesktopModuleID; + _PortalDesktopModuleID = value; + if (_DesktopModulePermissions == null || oldValue != value) + { + GetDesktopModulePermissions(); + } + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the DesktopModulePermissions from the Data Store + /// + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void GetDesktopModulePermissions() + { + _DesktopModulePermissions = new DesktopModulePermissionCollection(DesktopModulePermissionController.GetDesktopModulePermissions(PortalDesktopModuleID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Parse the Permission Keys used to persist the Permissions in the ViewState + /// + /// A string array of settings + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + private DesktopModulePermissionInfo ParseKeys(string[] Settings) + { + var objDesktopModulePermission = new DesktopModulePermissionInfo(); + + //Call base class to load base properties + base.ParsePermissionKeys(objDesktopModulePermission, Settings); + if (String.IsNullOrEmpty(Settings[2])) + { + objDesktopModulePermission.DesktopModulePermissionID = -1; + } + else + { + objDesktopModulePermission.DesktopModulePermissionID = Convert.ToInt32(Settings[2]); + } + objDesktopModulePermission.PortalDesktopModuleID = PortalDesktopModuleID; + return objDesktopModulePermission; + } + + #endregion + + #region "Protected Methods" + + protected override void AddPermission(PermissionInfo permission, int roleId, string roleName, int userId, string displayName, bool allowAccess) + { + var objPermission = new DesktopModulePermissionInfo(permission); + objPermission.PortalDesktopModuleID = PortalDesktopModuleID; + objPermission.RoleID = roleId; + objPermission.RoleName = roleName; + objPermission.AllowAccess = allowAccess; + objPermission.UserID = userId; + objPermission.DisplayName = displayName; + _DesktopModulePermissions.Add(objPermission, true); + + //Clear Permission List + _PermissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Permission + /// + /// The permissions collection + /// The user to add + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + protected override void AddPermission(ArrayList permissions, UserInfo user) + { + //Search DesktopModulePermission Collection for the user + bool isMatch = false; + foreach (DesktopModulePermissionInfo objDesktopModulePermission in _DesktopModulePermissions) + { + if (objDesktopModulePermission.UserID == user.UserID) + { + isMatch = true; + break; + } + } + + //user not found so add new + if (!isMatch) + { + foreach (PermissionInfo objPermission in permissions) + { + if (objPermission.PermissionKey == "DEPLOY") + { + AddPermission(objPermission, int.Parse(Globals.glbRoleNothing), Null.NullString, user.UserID, user.DisplayName, true); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the permissions from the Database + /// + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + protected override ArrayList GetPermissions() + { + return PermissionController.GetPermissionsByPortalDesktopModule(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Load the ViewState + /// + /// The saved state + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + protected override void LoadViewState(object savedState) + { + if (savedState != null) + { + //Load State from the array of objects that was saved with SaveViewState. + var myState = (object[])savedState; + + //Load Base Controls ViewState + if (myState[0] != null) + { + base.LoadViewState(myState[0]); + } + + //Load DesktopModuleId + if (myState[1] != null) + { + PortalDesktopModuleID = Convert.ToInt32(myState[1]); + } + + //Load DesktopModulePermissions + if (myState[2] != null) + { + _DesktopModulePermissions = new DesktopModulePermissionCollection(); + string state = Convert.ToString(myState[2]); + if (!String.IsNullOrEmpty(state)) + { + //First Break the String into individual Keys + string[] permissionKeys = state.Split(new[] { "##" }, StringSplitOptions.None); + foreach (string key in permissionKeys) + { + string[] Settings = key.Split('|'); + _DesktopModulePermissions.Add(ParseKeys(Settings)); + } + } + } + } + } + + protected override void RemovePermission(int permissionID, int roleID, int userID) + { + _DesktopModulePermissions.Remove(permissionID, roleID, userID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the ViewState + /// + /// + /// [cnurse] 02/22/2008 Created + /// + /// ----------------------------------------------------------------------------- + protected override object SaveViewState() + { + var allStates = new object[3]; + + //Save the Base Controls ViewState + allStates[0] = base.SaveViewState(); + + //Save the DesktopModule Id + allStates[1] = PortalDesktopModuleID; + + //Persist the DesktopModulePermisisons + var sb = new StringBuilder(); + if (_DesktopModulePermissions != null) + { + bool addDelimiter = false; + foreach (DesktopModulePermissionInfo objDesktopModulePermission in _DesktopModulePermissions) + { + if (addDelimiter) + { + sb.Append("##"); + } + else + { + addDelimiter = true; + } + sb.Append(BuildKey(objDesktopModulePermission.AllowAccess, + objDesktopModulePermission.PermissionID, + objDesktopModulePermission.DesktopModulePermissionID, + objDesktopModulePermission.RoleID, + objDesktopModulePermission.RoleName, + objDesktopModulePermission.UserID, + objDesktopModulePermission.DisplayName)); + } + } + allStates[2] = sb.ToString(); + return allStates; + } + + /// ----------------------------------------------------------------------------- + /// + /// returns whether or not the derived grid supports Deny permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool SupportsDenyPermissions(PermissionInfo permissionInfo) + { + return true; + } + + #endregion + + #region "Public Methods" + + public void ResetPermissions() + { + GetDesktopModulePermissions(); + _PermissionsList = null; + } + + public override void GenerateDataGrid() + { + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/Controls/FolderPermissionsGrid.cs b/DNN Platform/Library/Security/Permissions/Controls/FolderPermissionsGrid.cs new file mode 100644 index 00000000000..42af7a2edac --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/Controls/FolderPermissionsGrid.cs @@ -0,0 +1,417 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +#endregion + +namespace DotNetNuke.Security.Permissions.Controls +{ + public class FolderPermissionsGrid : PermissionsGrid + { + #region "Private Members" + + private string _folderPath = ""; + protected FolderPermissionCollection FolderPermissions; + private List _permissionsList; + private bool _refreshGrid; + private IList _systemFolderPermissions; + + #endregion + + #region "Protected Properties" + + protected override List PermissionsList + { + get + { + if (_permissionsList == null && FolderPermissions != null) + { + _permissionsList = FolderPermissions.ToList(); + } + return _permissionsList; + } + } + + protected override bool RefreshGrid + { + get + { + return _refreshGrid; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the path of the Folder + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public string FolderPath + { + get + { + return _folderPath; + } + set + { + _folderPath = value; + _refreshGrid = true; + GetFolderPermissions(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Permission Collection + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public FolderPermissionCollection Permissions + { + get + { + //First Update Permissions in case they have been changed + UpdatePermissions(); + + //Return the FolderPermissions + return FolderPermissions; + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the TabPermissions from the Data Store + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected virtual void GetFolderPermissions() + { + FolderPermissions = new FolderPermissionCollection(FolderPermissionController.GetFolderPermissionsCollectionByFolder(PortalId, FolderPath)); + _permissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Parse the Permission Keys used to persist the Permissions in the ViewState + /// + /// A string array of settings + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + private FolderPermissionInfo ParseKeys(string[] settings) + { + var objFolderPermission = new FolderPermissionInfo(); + + //Call base class to load base properties + base.ParsePermissionKeys(objFolderPermission, settings); + if (String.IsNullOrEmpty(settings[2])) + { + objFolderPermission.FolderPermissionID = -1; + } + else + { + objFolderPermission.FolderPermissionID = Convert.ToInt32(settings[2]); + } + objFolderPermission.FolderPath = FolderPath; + return objFolderPermission; + } + + #endregion + + #region "Protected Methods" + + protected override void AddPermission(PermissionInfo permission, int roleId, string roleName, int userId, string displayName, bool allowAccess) + { + var objPermission = new FolderPermissionInfo(permission) + { + FolderPath = FolderPath, + RoleID = roleId, + RoleName = roleName, + AllowAccess = allowAccess, + UserID = userId, + DisplayName = displayName + }; + FolderPermissions.Add(objPermission, true); + + //Clear Permission List + _permissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Permission + /// + /// The permissions collection + /// The user to add + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void AddPermission(ArrayList permissions, UserInfo user) + { + bool isMatch = false; + foreach (FolderPermissionInfo objFolderPermission in FolderPermissions) + { + if (objFolderPermission.UserID == user.UserID) + { + isMatch = true; + break; + } + } + + //user not found so add new + if (!isMatch) + { + foreach (PermissionInfo objPermission in permissions) + { + if (objPermission.PermissionKey == "READ") + { + AddPermission(objPermission, int.Parse(Globals.glbRoleNothing), Null.NullString, user.UserID, user.DisplayName, true); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool GetEnabled(PermissionInfo objPerm, RoleInfo role, int column) + { + return role.RoleID != AdministratorRoleId; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// Default State. + /// A Boolean (True or False) + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override string GetPermission(PermissionInfo objPerm, RoleInfo role, int column, string defaultState) + { + string permission; + if (role.RoleID == AdministratorRoleId && IsPermissionAlwaysGrantedToAdmin(objPerm)) + { + permission = PermissionTypeGrant; + } + else + { + //Call base class method to handle standard permissions + permission = base.GetPermission(objPerm, role, column, defaultState); + } + return permission; + } + + private bool IsPermissionAlwaysGrantedToAdmin(PermissionInfo permissionInfo) + { + return IsSystemFolderPermission(permissionInfo); + } + + private bool IsSystemFolderPermission(PermissionInfo permissionInfo) + { + return _systemFolderPermissions.Any(pi => pi.PermissionID == permissionInfo.PermissionID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the permissions from the Database + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override ArrayList GetPermissions() + { + ArrayList perms = PermissionController.GetPermissionsByFolder(); + _systemFolderPermissions = perms.Cast().ToList(); + return perms; + } + + /// ----------------------------------------------------------------------------- + /// + /// Load the ViewState + /// + /// The saved state + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void LoadViewState(object savedState) + { + if (savedState != null) + { + //Load State from the array of objects that was saved with SaveViewState. + var myState = (object[])savedState; + + //Load Base Controls ViewState + if (myState[0] != null) + { + base.LoadViewState(myState[0]); + } + + //Load FolderPath + if (myState[1] != null) + { + _folderPath = Convert.ToString(myState[1]); + } + + //Load FolderPermissions + if (myState[2] != null) + { + FolderPermissions = new FolderPermissionCollection(); + string state = Convert.ToString(myState[2]); + if (!String.IsNullOrEmpty(state)) + { + //First Break the String into individual Keys + string[] permissionKeys = state.Split(new[] { "##" }, StringSplitOptions.None); + foreach (string key in permissionKeys) + { + string[] settings = key.Split('|'); + FolderPermissions.Add(ParseKeys(settings)); + } + } + } + } + } + + protected override void RemovePermission(int permissionID, int roleID, int userID) + { + FolderPermissions.Remove(permissionID, roleID, userID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the ViewState + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override object SaveViewState() + { + var allStates = new object[3]; + + //Save the Base Controls ViewState + allStates[0] = base.SaveViewState(); + + //Save the Tab Id + allStates[1] = FolderPath; + + //Persist the TabPermisisons + var sb = new StringBuilder(); + if (FolderPermissions != null) + { + bool addDelimiter = false; + foreach (FolderPermissionInfo objFolderPermission in FolderPermissions) + { + if (addDelimiter) + { + sb.Append("##"); + } + else + { + addDelimiter = true; + } + sb.Append(BuildKey(objFolderPermission.AllowAccess, + objFolderPermission.PermissionID, + objFolderPermission.FolderPermissionID, + objFolderPermission.RoleID, + objFolderPermission.RoleName, + objFolderPermission.UserID, + objFolderPermission.DisplayName)); + } + } + allStates[2] = sb.ToString(); + return allStates; + } + + /// ----------------------------------------------------------------------------- + /// + /// returns whether or not the derived grid supports Deny permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool SupportsDenyPermissions(PermissionInfo permissionInfo) + { + return IsSystemFolderPermission(permissionInfo); + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Overrides the Base method to Generate the Data Grid + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void GenerateDataGrid() + { + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/Controls/ModulePermissionsGrid.cs b/DNN Platform/Library/Security/Permissions/Controls/ModulePermissionsGrid.cs new file mode 100644 index 00000000000..d710ff830a2 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/Controls/ModulePermissionsGrid.cs @@ -0,0 +1,529 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Internal; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +#endregion + +namespace DotNetNuke.Security.Permissions.Controls +{ + public class ModulePermissionsGrid : PermissionsGrid + { + #region Private Members + + private bool _InheritViewPermissionsFromTab; + private int _ModuleID = -1; + private ModulePermissionCollection _ModulePermissions; + private List _PermissionsList; + private int _ViewColumnIndex; + + public ModulePermissionsGrid() + { + TabId = -1; + } + + #endregion + + #region Protected Properties + + protected override List PermissionsList + { + get + { + if (_PermissionsList == null && _ModulePermissions != null) + { + _PermissionsList = _ModulePermissions.ToList(); + } + return _PermissionsList; + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets whether the Module inherits the Page's(Tab's) permissions + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public bool InheritViewPermissionsFromTab + { + get + { + return _InheritViewPermissionsFromTab; + } + set + { + _InheritViewPermissionsFromTab = value; + _PermissionsList = null; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Id of the Module + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public int ModuleID + { + get + { + return _ModuleID; + } + set + { + _ModuleID = value; + if (!Page.IsPostBack) + { + GetModulePermissions(); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Id of the Tab associated with this module + /// + /// + /// [cnurse] 24/11/2006 Created + /// + /// ----------------------------------------------------------------------------- + public int TabId { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModulePermission Collection + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public ModulePermissionCollection Permissions + { + get + { + //First Update Permissions in case they have been changed + UpdatePermissions(); + + //Return the ModulePermissions + return _ModulePermissions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModulePermissions from the Data Store + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + private void GetModulePermissions() + { + _ModulePermissions = new ModulePermissionCollection(ModulePermissionController.GetModulePermissions(ModuleID, TabId)); + _PermissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Parse the Permission Keys used to persist the Permissions in the ViewState + /// + /// A string array of settings + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + private ModulePermissionInfo ParseKeys(string[] Settings) + { + var objModulePermission = new ModulePermissionInfo(); + + //Call base class to load base properties + base.ParsePermissionKeys(objModulePermission, Settings); + if (String.IsNullOrEmpty(Settings[2])) + { + objModulePermission.ModulePermissionID = -1; + } + else + { + objModulePermission.ModulePermissionID = Convert.ToInt32(Settings[2]); + } + objModulePermission.ModuleID = ModuleID; + return objModulePermission; + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Permission + /// + /// The permissions collection + /// The user to add + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void AddPermission(ArrayList permissions, UserInfo user) + { + bool isMatch = _ModulePermissions.Cast() + .Any(objModulePermission => objModulePermission.UserID == user.UserID); + + //user not found so add new + if (!isMatch) + { + foreach (PermissionInfo objPermission in permissions) + { + if (objPermission.PermissionKey == "VIEW") + { + AddPermission(objPermission, int.Parse(Globals.glbRoleNothing), Null.NullString, user.UserID, user.DisplayName, true); + } + } + } + } + + protected override void AddPermission(PermissionInfo permission, int roleId, string roleName, int userId, string displayName, bool allowAccess) + { + var objPermission = new ModulePermissionInfo(permission) + { + ModuleID = ModuleID, + RoleID = roleId, + RoleName = roleName, + AllowAccess = allowAccess, + UserID = userId, + DisplayName = displayName + }; + _ModulePermissions.Add(objPermission, true); + + //Clear Permission List + _PermissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool GetEnabled(PermissionInfo objPerm, RoleInfo role, int column) + { + bool enabled; + if (InheritViewPermissionsFromTab && column == _ViewColumnIndex) + { + enabled = false; + } + else + { + enabled = role.RoleID != AdministratorRoleId; + } + return enabled; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The user + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool GetEnabled(PermissionInfo objPerm, UserInfo user, int column) + { + bool enabled; + if (InheritViewPermissionsFromTab && column == _ViewColumnIndex) + { + enabled = false; + } + else + { + enabled = true; + } + return enabled; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// Default State. + /// A Boolean (True or False) + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override string GetPermission(PermissionInfo objPerm, RoleInfo role, int column, string defaultState) + { + string permission; + if (InheritViewPermissionsFromTab && column == _ViewColumnIndex) + { + permission = PermissionTypeNull; + } + else + { + permission = role.RoleID == AdministratorRoleId + ? PermissionTypeGrant + : base.GetPermission(objPerm, role, column, defaultState); + } + return permission; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// Default State. + /// A Boolean (True or False) + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override string GetPermission(PermissionInfo objPerm, UserInfo user, int column, string defaultState) + { + string permission; + if (InheritViewPermissionsFromTab && column == _ViewColumnIndex) + { + permission = PermissionTypeNull; + } + else + { + //Call base class method to handle standard permissions + permission = base.GetPermission(objPerm, user, column, defaultState); + } + return permission; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Permissions from the Data Store + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + protected override ArrayList GetPermissions() + { + var moduleInfo = TestableModuleController.Instance.GetModule(ModuleID, TabId); + + var permissionController = new PermissionController(); + var permissions = permissionController.GetPermissionsByModuleID(ModuleID); + + var permissionList = new ArrayList(); + for (int i = 0; i <= permissions.Count - 1; i++) + { + var permission = (PermissionInfo)permissions[i]; + if (permission.PermissionKey == "VIEW") + { + _ViewColumnIndex = i + 1; + permissionList.Add(permission); + } + else + { + if (!(moduleInfo.IsShared && moduleInfo.IsShareableViewOnly)) + { + permissionList.Add(permission); + } + } + } + return permissionList; + } + + /// ----------------------------------------------------------------------------- + /// + /// Load the ViewState + /// + /// The saved state + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void LoadViewState(object savedState) + { + if (savedState != null) + { + //Load State from the array of objects that was saved with SaveViewState. + var myState = (object[])savedState; + + //Load Base Controls ViewState + if (myState[0] != null) + { + base.LoadViewState(myState[0]); + } + + //Load ModuleID + if (myState[1] != null) + { + ModuleID = Convert.ToInt32(myState[1]); + } + + //Load TabId + if (myState[2] != null) + { + TabId = Convert.ToInt32(myState[2]); + } + + //Load InheritViewPermissionsFromTab + if (myState[3] != null) + { + InheritViewPermissionsFromTab = Convert.ToBoolean(myState[3]); + } + + //Load ModulePermissions + if (myState[4] != null) + { + _ModulePermissions = new ModulePermissionCollection(); + string state = Convert.ToString(myState[4]); + if (!String.IsNullOrEmpty(state)) + { + //First Break the String into individual Keys + string[] permissionKeys = state.Split(new[] { "##" }, StringSplitOptions.None); + foreach (string key in permissionKeys) + { + string[] Settings = key.Split('|'); + _ModulePermissions.Add(ParseKeys(Settings)); + } + } + } + } + } + + protected override void RemovePermission(int permissionID, int roleID, int userID) + { + _ModulePermissions.Remove(permissionID, roleID, userID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the ViewState + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override object SaveViewState() + { + var allStates = new object[5]; + + //Save the Base Controls ViewState + allStates[0] = base.SaveViewState(); + + //Save the ModuleID + allStates[1] = ModuleID; + + //Save the TabID + allStates[2] = TabId; + + //Save the InheritViewPermissionsFromTab + allStates[3] = InheritViewPermissionsFromTab; + + //Persist the ModulePermissions + var sb = new StringBuilder(); + if (_ModulePermissions != null) + { + bool addDelimiter = false; + foreach (ModulePermissionInfo modulePermission in _ModulePermissions) + { + if (addDelimiter) + { + sb.Append("##"); + } + else + { + addDelimiter = true; + } + sb.Append(BuildKey(modulePermission.AllowAccess, + modulePermission.PermissionID, + modulePermission.ModulePermissionID, + modulePermission.RoleID, + modulePermission.RoleName, + modulePermission.UserID, + modulePermission.DisplayName)); + } + } + allStates[4] = sb.ToString(); + return allStates; + } + + /// ----------------------------------------------------------------------------- + /// + /// returns whether or not the derived grid supports Deny permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool SupportsDenyPermissions(PermissionInfo permissionInfo) + { + return true; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Overrides the Base method to Generate the Data Grid + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public override void GenerateDataGrid() + { + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/Controls/PermissionsGrid.cs b/DNN Platform/Library/Security/Permissions/Controls/PermissionsGrid.cs new file mode 100644 index 00000000000..3299e58c4d6 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/Controls/PermissionsGrid.cs @@ -0,0 +1,1210 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.WebControls.Internal; + +#endregion + +namespace DotNetNuke.Security.Permissions.Controls +{ + public abstract class PermissionsGrid : Control, INamingContainer + { + #region Enums + + protected const string PermissionTypeGrant = "True"; + protected const string PermissionTypeDeny = "False"; + protected const string PermissionTypeNull = "Null"; + + #endregion + + #region Private Members + + private readonly DataTable _dtRolePermissions = new DataTable(); + private readonly DataTable _dtUserPermissions = new DataTable(); + private ArrayList _permissions; + private ArrayList _users; + private DropDownList cboRoleGroups; + private LinkButton cmdUser; + private DataGrid rolePermissionsGrid; + private DataGrid userPermissionsGrid; + private Label lblGroups; + private Label lblUser; + private Panel pnlPermissions; + private TextBox txtUser; + + #endregion + + #region Protected Properties + + protected virtual List PermissionsList + { + get + { + return null; + } + } + + protected virtual bool RefreshGrid + { + get + { + return false; + } + } + + #endregion + + #region Public Properties + + /// + /// Registers the scripts neccesary to make the tri-state controls work inside a RadAjaxPanel + /// + /// + /// No need to call this unless using the PermissionGrid inside an ajax control that omits scripts on postback + /// See DesktopModules/Admin/Tabs.ascx.cs for an example of usage + /// + public void RegisterScriptsForAjaxPanel() + { + PermissionTriState.RegisterScripts(Page, this); + } + + #region "DataGrid Properties" + + public TableItemStyle AlternatingItemStyle + { + get + { + return rolePermissionsGrid.AlternatingItemStyle; + } + } + + public bool AutoGenerateColumns + { + get + { + return rolePermissionsGrid.AutoGenerateColumns; + } + set + { + rolePermissionsGrid.AutoGenerateColumns = value; + userPermissionsGrid.AutoGenerateColumns = value; + } + } + + public int CellSpacing + { + get + { + return rolePermissionsGrid.CellSpacing; + } + set + { + rolePermissionsGrid.CellSpacing = value; + userPermissionsGrid.CellSpacing = value; + } + } + + public DataGridColumnCollection Columns + { + get + { + return rolePermissionsGrid.Columns; + } + } + + public TableItemStyle FooterStyle + { + get + { + return rolePermissionsGrid.FooterStyle; + } + } + + public GridLines GridLines + { + get + { + return rolePermissionsGrid.GridLines; + } + set + { + rolePermissionsGrid.GridLines = value; + userPermissionsGrid.GridLines = value; + } + } + + public TableItemStyle HeaderStyle + { + get + { + return rolePermissionsGrid.HeaderStyle; + } + } + + public TableItemStyle ItemStyle + { + get + { + return rolePermissionsGrid.ItemStyle; + } + } + + public DataGridItemCollection Items + { + get + { + return rolePermissionsGrid.Items; + } + } + + public TableItemStyle SelectedItemStyle + { + get + { + return rolePermissionsGrid.SelectedItemStyle; + } + } + + #endregion + + /// + /// Gets the Id of the Administrator Role + /// + /// + /// [cnurse] 01/16/2006 Created + /// + public int AdministratorRoleId + { + get + { + return PortalController.GetCurrentPortalSettings().AdministratorRoleId; + } + } + + /// + /// Gets the Id of the Registered Users Role + /// + /// + /// [cnurse] 01/16/2006 Created + /// + public int RegisteredUsersRoleId + { + get + { + return PortalController.GetCurrentPortalSettings().RegisteredRoleId; + } + } + + /// + /// Gets and Sets whether a Dynamic Column has been added + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + public bool DynamicColumnAdded + { + get + { + return ViewState["ColumnAdded"] != null; + } + set + { + ViewState["ColumnAdded"] = value; + } + } + + /// + /// Gets the underlying Permissions Data Table + /// + /// + /// [cnurse] 01/09/2006 Created + /// + public DataTable dtRolePermissions + { + get + { + return _dtRolePermissions; + } + } + + /// + /// Gets the underlying Permissions Data Table + /// + /// + /// [cnurse] 01/09/2006 Created + /// + public DataTable dtUserPermissions + { + get + { + return _dtUserPermissions; + } + } + + /// + /// Gets the Id of the Portal + /// + /// + /// [cnurse] 01/16/2006 Created + /// + public int PortalId + { + get + { + //Obtain PortalSettings from Current Context + var portalSettings = PortalController.GetCurrentPortalSettings(); + int portalID; + if (Globals.IsHostTab(portalSettings.ActiveTab.TabID)) //if we are in host filemanager then we need to pass a null portal id + { + portalID = Null.NullInteger; + } + else + { + portalID = portalSettings.PortalId; + } + return portalID; + } + } + + /// + /// Gets and Sets the collection of Roles to display + /// + /// + /// [cnurse] 01/09/2006 Created + /// + public ArrayList Roles { get; set; } + + /// + /// Gets and Sets the ResourceFile to localize permissions + /// + /// + /// [vmasanas] 02/24/2006 Created + /// + public string ResourceFile { get; set; } + + #endregion + + #region Abstract Members + + /// + /// Generate the Data Grid + /// + /// + /// [cnurse] 01/09/2006 Created + /// + public abstract void GenerateDataGrid(); + + #endregion + + #region Private Methods + + /// + /// Bind the data to the controls + /// + /// + /// [cnurse] 01/09/2006 Created + /// + private void BindData() + { + EnsureChildControls(); + BindRolesGrid(); + BindUsersGrid(); + } + + /// + /// Bind the Roles data to the Grid + /// + /// + /// [cnurse] 01/09/2006 Created + /// + private void BindRolesGrid() + { + dtRolePermissions.Columns.Clear(); + dtRolePermissions.Rows.Clear(); + + //Add Roles Column + dtRolePermissions.Columns.Add(new DataColumn("RoleId")); + + //Add Roles Column + dtRolePermissions.Columns.Add(new DataColumn("RoleName")); + + for (int i = 0; i <= _permissions.Count - 1; i++) + { + var permissionInfo = (PermissionInfo)_permissions[i]; + + //Add Enabled Column + dtRolePermissions.Columns.Add(new DataColumn(permissionInfo.PermissionName + "_Enabled")); + + //Add Permission Column + dtRolePermissions.Columns.Add(new DataColumn(permissionInfo.PermissionName)); + } + GetRoles(); + + UpdateRolePermissions(); + for (int i = 0; i <= Roles.Count - 1; i++) + { + var role = (RoleInfo)Roles[i]; + var row = dtRolePermissions.NewRow(); + row["RoleId"] = role.RoleID; + row["RoleName"] = Localization.LocalizeRole(role.RoleName); + int j; + for (j = 0; j <= _permissions.Count - 1; j++) + { + PermissionInfo objPerm; + objPerm = (PermissionInfo)_permissions[j]; + row[objPerm.PermissionName + "_Enabled"] = GetEnabled(objPerm, role, j + 1); + if (SupportsDenyPermissions(objPerm)) + { + row[objPerm.PermissionName] = GetPermission(objPerm, role, j + 1, PermissionTypeNull); + } + else + { + if (GetPermission(objPerm, role, j + 1)) + { + row[objPerm.PermissionName] = PermissionTypeGrant; + } + else + { + row[objPerm.PermissionName] = PermissionTypeNull; + } + } + } + dtRolePermissions.Rows.Add(row); + } + rolePermissionsGrid.DataSource = dtRolePermissions; + rolePermissionsGrid.DataBind(); + } + + /// + /// Bind the Users data to the Grid + /// + /// + /// [cnurse] 01/09/2006 Created + /// + private void BindUsersGrid() + { + dtUserPermissions.Columns.Clear(); + dtUserPermissions.Rows.Clear(); + + //Add Roles Column + var col = new DataColumn("UserId"); + dtUserPermissions.Columns.Add(col); + + //Add Roles Column + col = new DataColumn("DisplayName"); + dtUserPermissions.Columns.Add(col); + int i; + for (i = 0; i <= _permissions.Count - 1; i++) + { + PermissionInfo objPerm; + objPerm = (PermissionInfo)_permissions[i]; + + //Add Enabled Column + col = new DataColumn(objPerm.PermissionName + "_Enabled"); + dtUserPermissions.Columns.Add(col); + + //Add Permission Column + col = new DataColumn(objPerm.PermissionName); + dtUserPermissions.Columns.Add(col); + } + if (userPermissionsGrid != null) + { + _users = GetUsers(); + + if (_users.Count != 0) + { + userPermissionsGrid.Visible = true; + UpdateUserPermissions(); + DataRow row; + for (i = 0; i <= _users.Count - 1; i++) + { + var user = (UserInfo)_users[i]; + row = dtUserPermissions.NewRow(); + row["UserId"] = user.UserID; + row["DisplayName"] = user.DisplayName; + int j; + for (j = 0; j <= _permissions.Count - 1; j++) + { + PermissionInfo objPerm; + objPerm = (PermissionInfo)_permissions[j]; + row[objPerm.PermissionName + "_Enabled"] = GetEnabled(objPerm, user, j + 1); + if (SupportsDenyPermissions(objPerm)) + { + row[objPerm.PermissionName] = GetPermission(objPerm, user, j + 1, PermissionTypeNull); + } + else + { + if (GetPermission(objPerm, user, j + 1)) + { + row[objPerm.PermissionName] = PermissionTypeGrant; + } + else + { + row[objPerm.PermissionName] = PermissionTypeNull; + } + } + } + dtUserPermissions.Rows.Add(row); + } + userPermissionsGrid.DataSource = dtUserPermissions; + userPermissionsGrid.DataBind(); + } + else + { + userPermissionsGrid.Visible = false; + } + } + } + + /// + /// Gets the roles from the Database and loads them into the Roles property + /// + /// + /// [cnurse] 01/09/2006 Created + /// + private void GetRoles() + { + var roleController = new RoleController(); + int roleGroupId = -2; + if ((cboRoleGroups != null) && (cboRoleGroups.SelectedValue != null)) + { + roleGroupId = int.Parse(cboRoleGroups.SelectedValue); + } + if (roleGroupId > -2) + { + Roles = new ArrayList(TestableRoleController.Instance.GetRoles(PortalController.GetCurrentPortalSettings().PortalId, r => r.RoleGroupID == roleGroupId && r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).ToArray()); + } + else + { + Roles = new ArrayList(TestableRoleController.Instance.GetRoles(PortalController.GetCurrentPortalSettings().PortalId, r => r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).ToArray()); + } + if (roleGroupId < 0) + { + Roles.Add(new RoleInfo { RoleID = int.Parse(Globals.glbRoleUnauthUser), RoleName = Globals.glbRoleUnauthUserName }); + Roles.Add(new RoleInfo { RoleID = int.Parse(Globals.glbRoleAllUsers), RoleName = Globals.glbRoleAllUsersName }); + } + Roles.Reverse(); + Roles.Sort(new RoleComparer()); + } + + /// + /// Sets up the columns for the Grid + /// + /// + /// [cnurse] 01/09/2006 Created + /// + private void SetUpRolesGrid() + { + rolePermissionsGrid.Columns.Clear(); + var textCol = new BoundColumn { HeaderText = " ", DataField = "RoleName" }; + textCol.ItemStyle.Width = Unit.Parse("150px"); + textCol.ItemStyle.HorizontalAlign = HorizontalAlign.Right; + rolePermissionsGrid.Columns.Add(textCol); + var idCol = new BoundColumn(); + idCol.HeaderText = ""; + idCol.DataField = "roleid"; + idCol.Visible = false; + rolePermissionsGrid.Columns.Add(idCol); + TemplateColumn templateCol; + foreach (PermissionInfo objPermission in _permissions) + { + templateCol = new TemplateColumn(); + var columnTemplate = new PermissionTriStateTemplate(); + columnTemplate.DataField = objPermission.PermissionName; + columnTemplate.EnabledField = objPermission.PermissionName + "_Enabled"; + columnTemplate.SupportDenyMode = SupportsDenyPermissions(objPermission); + templateCol.ItemTemplate = columnTemplate; + + var locName = ""; + if (objPermission.ModuleDefID > 0) + { + if (!String.IsNullOrEmpty(ResourceFile)) + { + //custom permission + locName = Localization.GetString(objPermission.PermissionName + ".Permission", ResourceFile); + } + } + else + { + //system permission + locName = Localization.GetString(objPermission.PermissionName + ".Permission", PermissionProvider.Instance().LocalResourceFile); + } + templateCol.HeaderText = !String.IsNullOrEmpty(locName) ? locName : objPermission.PermissionName; + templateCol.HeaderStyle.HorizontalAlign = HorizontalAlign.Center; + templateCol.HeaderStyle.VerticalAlign = VerticalAlign.Bottom; + templateCol.ItemStyle.HorizontalAlign = HorizontalAlign.Center; + templateCol.ItemStyle.Width = Unit.Parse("70px"); + templateCol.HeaderStyle.Wrap = true; + rolePermissionsGrid.Columns.Add(templateCol); + } + } + + private void SetUpUsersGrid() + { + if (userPermissionsGrid != null) + { + userPermissionsGrid.Columns.Clear(); + var textCol = new BoundColumn(); + textCol.HeaderText = " "; + textCol.DataField = "DisplayName"; + textCol.ItemStyle.Width = Unit.Parse("150px"); + textCol.ItemStyle.HorizontalAlign = HorizontalAlign.Right; + userPermissionsGrid.Columns.Add(textCol); + var idCol = new BoundColumn(); + idCol.HeaderText = ""; + idCol.DataField = "userid"; + idCol.Visible = false; + userPermissionsGrid.Columns.Add(idCol); + TemplateColumn templateCol; + foreach (PermissionInfo objPermission in _permissions) + { + templateCol = new TemplateColumn(); + var columnTemplate = new PermissionTriStateTemplate(); + columnTemplate.DataField = objPermission.PermissionName; + columnTemplate.EnabledField = objPermission.PermissionName + "_Enabled"; + columnTemplate.SupportDenyMode = SupportsDenyPermissions(objPermission); + templateCol.ItemTemplate = columnTemplate; + + + string locName = ""; + if (objPermission.ModuleDefID > 0) + { + if (!String.IsNullOrEmpty(ResourceFile)) + { + //custom permission + locName = Localization.GetString(objPermission.PermissionName + ".Permission", ResourceFile); + } + } + else + { + //system permission + locName = Localization.GetString(objPermission.PermissionName + ".Permission", PermissionProvider.Instance().LocalResourceFile); + } + templateCol.HeaderText = !String.IsNullOrEmpty(locName) ? locName : objPermission.PermissionName; + templateCol.HeaderStyle.VerticalAlign = VerticalAlign.Bottom; + templateCol.ItemStyle.HorizontalAlign = HorizontalAlign.Center; + templateCol.ItemStyle.Width = Unit.Parse("70px"); + templateCol.HeaderStyle.Wrap = true; + userPermissionsGrid.Columns.Add(templateCol); + } + } + } + + #endregion + + #region Protected Methods + + protected virtual void AddPermission(PermissionInfo permission, int roleId, string roleName, int userId, string displayName, bool allowAccess) + { + } + + /// + /// Updates a Permission + /// + /// The permissions collection + /// The user to add + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual void AddPermission(ArrayList permissions, UserInfo user) + { + } + + /// + /// Builds the key used to store the "permission" information in the ViewState + /// + /// The type of permission ( grant / deny ) + /// The Id of the permission + /// The Id of the object permission + /// The role id + /// The role name + /// + /// + protected string BuildKey(bool allowAccess, int permissionId, int objectPermissionId, int roleId, string roleName) + { + return BuildKey(allowAccess, permissionId, objectPermissionId, roleId, roleName, Null.NullInteger, Null.NullString); + } + + /// + /// Builds the key used to store the "permission" information in the ViewState + /// + /// The type of permission ( grant / deny ) + /// The Id of the permission + /// The Id of the object permission + /// The role id + /// The role name + /// The user id + /// The user display name + /// + /// [cnurse] 01/09/2006 Created + /// + protected string BuildKey(bool allowAccess, int permissionId, int objectPermissionId, int roleId, string roleName, int userID, string displayName) + { + string key; + if (allowAccess) + { + key = "True"; + } + else + { + key = "False"; + } + key += "|" + Convert.ToString(permissionId); + key += "|"; + if (objectPermissionId > -1) + { + key += Convert.ToString(objectPermissionId); + } + key += "|" + roleName; + key += "|" + roleId; + key += "|" + userID; + key += "|" + displayName; + + return key; + } + + /// + /// Creates the Child Controls + /// + /// + /// [cnurse] 02/23/2006 Created + /// + protected override void CreateChildControls() + { + _permissions = GetPermissions(); + + pnlPermissions = new Panel { CssClass = "dnnGrid dnnPermissionsGrid" }; + + //Optionally Add Role Group Filter + var portalSettings = PortalController.GetCurrentPortalSettings(); + var arrGroups = RoleController.GetRoleGroups(portalSettings.PortalId); + if (arrGroups.Count > 0) + { + var divRoleGroups = new Panel { CssClass = "dnnFormItem" }; + + lblGroups = new Label { Text = Localization.GetString("RoleGroupFilter") }; + cboRoleGroups = new DropDownList { AutoPostBack = true, ID = "cboRoleGroups" }; + cboRoleGroups.SelectedIndexChanged += RoleGroupsSelectedIndexChanged; + lblGroups.AssociatedControlID = cboRoleGroups.ID; + + divRoleGroups.Controls.Add(lblGroups); + + cboRoleGroups.Items.Add(new ListItem(Localization.GetString("AllRoles"), "-2")); + var liItem = new ListItem(Localization.GetString("GlobalRoles"), "-1") { Selected = true }; + cboRoleGroups.Items.Add(liItem); + + foreach (RoleGroupInfo roleGroup in arrGroups) + { + cboRoleGroups.Items.Add(new ListItem(roleGroup.RoleGroupName, roleGroup.RoleGroupID.ToString())); + } + + divRoleGroups.Controls.Add(cboRoleGroups); + + pnlPermissions.Controls.Add(divRoleGroups); + } + + rolePermissionsGrid = new DataGrid { AutoGenerateColumns = false, CellSpacing = 0, CellPadding = 2, GridLines = GridLines.None }; + rolePermissionsGrid.CssClass = "dnnPermissionsGrid"; + rolePermissionsGrid.FooterStyle.CssClass = "dnnGridFooter"; + rolePermissionsGrid.HeaderStyle.CssClass = "dnnGridHeader"; + rolePermissionsGrid.ItemStyle.CssClass = "dnnGridItem"; + rolePermissionsGrid.AlternatingItemStyle.CssClass = "dnnGridAltItem"; + + SetUpRolesGrid(); + pnlPermissions.Controls.Add(rolePermissionsGrid); + + _users = GetUsers(); + if (_users != null) + { + userPermissionsGrid = new DataGrid { AutoGenerateColumns = false, CellSpacing = 0, GridLines = GridLines.None }; + userPermissionsGrid.CssClass = "dnnPermissionsGrid"; + userPermissionsGrid.FooterStyle.CssClass = "dnnGridFooter"; + userPermissionsGrid.HeaderStyle.CssClass = "dnnGridHeader"; + userPermissionsGrid.ItemStyle.CssClass = "dnnGridItem"; + userPermissionsGrid.AlternatingItemStyle.CssClass = "dnnGridAltItem"; + + SetUpUsersGrid(); + pnlPermissions.Controls.Add(userPermissionsGrid); + + var divAddUser = new Panel { CssClass = "dnnFormItem" }; + + lblUser = new Label { Text = Localization.GetString("User") }; + txtUser = new TextBox { ID = "txtUser" }; + lblUser.AssociatedControlID = txtUser.ID; + + divAddUser.Controls.Add(lblUser); + divAddUser.Controls.Add(txtUser); + + cmdUser = new LinkButton { Text = Localization.GetString("Add"), CssClass = "dnnSecondaryAction" }; + divAddUser.Controls.Add(cmdUser); + cmdUser.Click += AddUser; + + pnlPermissions.Controls.Add(divAddUser); + } + Controls.Add(pnlPermissions); + } + + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual bool GetEnabled(PermissionInfo objPerm, RoleInfo role, int column) + { + return true; + } + + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The user + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual bool GetEnabled(PermissionInfo objPerm, UserInfo user, int column) + { + return true; + } + + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual bool GetPermission(PermissionInfo objPerm, RoleInfo role, int column) + { + return Convert.ToBoolean(GetPermission(objPerm, role, column, PermissionTypeDeny)); + } + + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// Default State. + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual string GetPermission(PermissionInfo objPerm, RoleInfo role, int column, string defaultState) + { + string stateKey = defaultState; + if (PermissionsList != null) + { + foreach (PermissionInfoBase permission in PermissionsList) + { + if (permission.PermissionID == objPerm.PermissionID && permission.RoleID == role.RoleID) + { + if (permission.AllowAccess) + { + stateKey = PermissionTypeGrant; + } + else + { + stateKey = PermissionTypeDeny; + } + break; + } + } + } + return stateKey; + } + + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The user + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual bool GetPermission(PermissionInfo objPerm, UserInfo user, int column) + { + return Convert.ToBoolean(GetPermission(objPerm, user, column, PermissionTypeDeny)); + } + + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The user + /// The column of the Grid + /// Default State. + /// + /// [cnurse] 01/13/2006 Created + /// + protected virtual string GetPermission(PermissionInfo objPerm, UserInfo user, int column, string defaultState) + { + var stateKey = defaultState; + if (PermissionsList != null) + { + foreach (var permission in PermissionsList) + { + if (permission.PermissionID == objPerm.PermissionID && permission.UserID == user.UserID) + { + if (permission.AllowAccess) + { + stateKey = PermissionTypeGrant; + } + else + { + stateKey = PermissionTypeDeny; + } + break; + } + } + } + return stateKey; + } + + /// + /// Gets the permissions from the Database + /// + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual ArrayList GetPermissions() + { + return null; + } + + /// + /// Gets the users from the Database + /// + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual ArrayList GetUsers() + { + var arrUsers = new ArrayList(); + UserInfo objUser; + if (PermissionsList != null) + { + foreach (var permission in PermissionsList) + { + if (!Null.IsNull(permission.UserID)) + { + bool blnExists = false; + foreach (UserInfo user in arrUsers) + { + if (permission.UserID == user.UserID) + { + blnExists = true; + } + } + if (!blnExists) + { + objUser = new UserInfo(); + objUser.UserID = permission.UserID; + objUser.Username = permission.Username; + objUser.DisplayName = permission.DisplayName; + arrUsers.Add(objUser); + } + } + } + } + return arrUsers; + } + + /// + /// Overrides the base OnPreRender method to Bind the Grid to the Permissions + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + protected override void OnPreRender(EventArgs e) + { + BindData(); + } + + protected virtual void ParsePermissionKeys(PermissionInfoBase permission, string[] Settings) + { + permission.PermissionID = Convert.ToInt32(Settings[1]); + permission.RoleID = Convert.ToInt32(Settings[4]); + permission.RoleName = Settings[3]; + permission.AllowAccess = Convert.ToBoolean(Settings[0]); + permission.UserID = Convert.ToInt32(Settings[5]); + permission.DisplayName = Settings[6]; + } + + protected virtual void RemovePermission(int permissionID, int roleID, int userID) + { + } + + /// + /// Updates a Permission + /// + /// The permission being updated + /// Rold Id. + /// The name of the role + /// The value of the permission + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual void UpdatePermission(PermissionInfo permission, int roleId, string roleName, bool allowAccess) + { + if (allowAccess) + { + UpdatePermission(permission, roleId, roleName, PermissionTypeGrant); + } + else + { + UpdatePermission(permission, roleId, roleName, PermissionTypeNull); + } + } + + /// + /// Updates a Permission + /// + /// The permission being updated + /// Role Id. + /// The name of the role + /// The permission state + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual void UpdatePermission(PermissionInfo permission, int roleId, string roleName, string stateKey) + { + RemovePermission(permission.PermissionID, roleId, Null.NullInteger); + switch (stateKey) + { + case PermissionTypeGrant: + AddPermission(permission, roleId, roleName, Null.NullInteger, Null.NullString, true); + break; + case PermissionTypeDeny: + AddPermission(permission, roleId, roleName, Null.NullInteger, Null.NullString, false); + break; + } + } + + /// + /// Updates a Permission + /// + /// The permission being updated + /// The user's displayname + /// The user's id + /// The value of the permission + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual void UpdatePermission(PermissionInfo permission, string displayName, int userId, bool allowAccess) + { + UpdatePermission(permission, displayName, userId, allowAccess ? PermissionTypeGrant : PermissionTypeNull); + } + + /// + /// Updates a Permission + /// + /// The permission being updated + /// The user's displayname + /// The user's id + /// The permission state + /// + /// [cnurse] 01/12/2006 Created + /// + protected virtual void UpdatePermission(PermissionInfo permission, string displayName, int userId, string stateKey) + { + RemovePermission(permission.PermissionID, int.Parse(Globals.glbRoleNothing), userId); + switch (stateKey) + { + case PermissionTypeGrant: + AddPermission(permission, int.Parse(Globals.glbRoleNothing), Null.NullString, userId, displayName, true); + break; + case PermissionTypeDeny: + AddPermission(permission, int.Parse(Globals.glbRoleNothing), Null.NullString, userId, displayName, false); + break; + } + } + + /// + /// returns whether or not the derived grid supports Deny permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + [Obsolete("Deprecated in 6.2.0 use SupportsDenyPermissions(PermissionInfo) instead.")] //todo just guessing at the version that this will release in + protected virtual bool SupportsDenyPermissions() + { + return false; //to support Deny permissions a derived grid typically needs to implement the new GetPermission and UpdatePermission overload methods which support StateKey + } + + protected virtual bool SupportsDenyPermissions(PermissionInfo permissionInfo) + { + //to maintain backward compatibility the base implementation must always call the simple parameterless version of this method +#pragma warning disable 612,618 + return SupportsDenyPermissions(); +#pragma warning restore 612,618 + } + + /// + /// Updates the permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + protected void UpdatePermissions() + { + EnsureChildControls(); + UpdateRolePermissions(); + UpdateUserPermissions(); + } + + /// + /// Updates the permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + protected void UpdateRolePermissions() + { + if (rolePermissionsGrid != null && !RefreshGrid) + { + foreach (DataGridItem dgi in rolePermissionsGrid.Items) + { + int i; + for (i = 2; i <= dgi.Cells.Count - 1; i++) + { + //all except first two cells which is role names and role ids + if (dgi.Cells[i].Controls.Count > 0) + { + var permissionInfo = (PermissionInfo)_permissions[i - 2]; + var triState = (PermissionTriState)dgi.Cells[i].Controls[0]; + if (SupportsDenyPermissions(permissionInfo)) + { + UpdatePermission(permissionInfo, int.Parse(dgi.Cells[1].Text), dgi.Cells[0].Text, triState.Value); + } + else + { + UpdatePermission(permissionInfo, int.Parse(dgi.Cells[1].Text), dgi.Cells[0].Text, triState.Value == PermissionTypeGrant); + } + } + } + } + } + } + + /// + /// Updates the permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + protected void UpdateUserPermissions() + { + if (userPermissionsGrid != null && !RefreshGrid) + { + foreach (DataGridItem dgi in userPermissionsGrid.Items) + { + int i; + for (i = 2; i <= dgi.Cells.Count - 1; i++) + { + //all except first two cells which is displayname and userid + if (dgi.Cells[i].Controls.Count > 0) + { + var permissionInfo = (PermissionInfo)_permissions[i - 2]; + var triState = (PermissionTriState)dgi.Cells[i].Controls[0]; + if (SupportsDenyPermissions(permissionInfo)) + { + UpdatePermission(permissionInfo, dgi.Cells[0].Text, int.Parse(dgi.Cells[1].Text), triState.Value); + } + else + { + UpdatePermission(permissionInfo, dgi.Cells[0].Text, int.Parse(dgi.Cells[1].Text), triState.Value == PermissionTypeGrant); + } + } + } + } + } + } + + #endregion + + #region Event Handlers + + /// + /// RoleGroupsSelectedIndexChanged runs when the Role Group is changed + /// + /// + /// [cnurse] 01/06/2006 Documented + /// + protected virtual void RoleGroupsSelectedIndexChanged(object sender, EventArgs e) + { + UpdatePermissions(); + } + + /// + /// AddUser runs when the Add user linkbutton is clicked + /// + /// + /// + protected virtual void AddUser(object sender, EventArgs e) + { + UpdatePermissions(); + if (!String.IsNullOrEmpty(txtUser.Text)) + { + //verify username + UserInfo objUser = UserController.GetCachedUser(PortalId, txtUser.Text); + if (objUser != null) + { + AddPermission(_permissions, objUser); + BindData(); + } + else + { + //user does not exist + lblUser = new Label(); + lblUser.Text = "
    " + Localization.GetString("InvalidUserName"); + lblUser.CssClass = "NormalRed"; + pnlPermissions.Controls.Add(lblUser); + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/Controls/TabPermissionsGrid.cs b/DNN Platform/Library/Security/Permissions/Controls/TabPermissionsGrid.cs new file mode 100644 index 00000000000..3d3717412d9 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/Controls/TabPermissionsGrid.cs @@ -0,0 +1,383 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +#endregion + +namespace DotNetNuke.Security.Permissions.Controls +{ + public class TabPermissionsGrid : PermissionsGrid + { + #region "Private Members" + + private List _PermissionsList; + private int _TabID = -1; + private TabPermissionCollection _TabPermissions; + + #endregion + + #region "Protected Properties" + + protected override List PermissionsList + { + get + { + if (_PermissionsList == null && _TabPermissions != null) + { + _PermissionsList = _TabPermissions.ToList(); + } + return _PermissionsList; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Permissions Collection + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public TabPermissionCollection Permissions + { + get + { + //First Update Permissions in case they have been changed + UpdatePermissions(); + + //Return the TabPermissions + return _TabPermissions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Id of the Tab + /// + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public int TabID + { + get + { + return _TabID; + } + set + { + _TabID = value; + if (!Page.IsPostBack) + { + GetTabPermissions(); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the TabPermissions from the Data Store + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + private void GetTabPermissions() + { + _TabPermissions = new TabPermissionCollection(TabPermissionController.GetTabPermissions(TabID, PortalId)); + _PermissionsList = null; + } + + public override void DataBind() + { + GetTabPermissions(); + base.DataBind(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Parse the Permission Keys used to persist the Permissions in the ViewState + /// + /// A string array of settings + /// + /// [cnurse] 01/09/2006 Documented + /// + /// ----------------------------------------------------------------------------- + private TabPermissionInfo ParseKeys(string[] Settings) + { + var objTabPermission = new TabPermissionInfo(); + + //Call base class to load base properties + base.ParsePermissionKeys(objTabPermission, Settings); + if (String.IsNullOrEmpty(Settings[2])) + { + objTabPermission.TabPermissionID = -1; + } + else + { + objTabPermission.TabPermissionID = Convert.ToInt32(Settings[2]); + } + objTabPermission.TabID = TabID; + + return objTabPermission; + } + + protected override void AddPermission(PermissionInfo permission, int roleId, string roleName, int userId, string displayName, bool allowAccess) + { + var objPermission = new TabPermissionInfo(permission); + objPermission.TabID = TabID; + objPermission.RoleID = roleId; + objPermission.RoleName = roleName; + objPermission.AllowAccess = allowAccess; + objPermission.UserID = userId; + objPermission.DisplayName = displayName; + _TabPermissions.Add(objPermission, true); + + //Clear Permission List + _PermissionsList = null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Permission + /// + /// The permissions collection + /// The user to add + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void AddPermission(ArrayList permissions, UserInfo user) + { + //Search TabPermission Collection for the user + bool isMatch = false; + foreach (TabPermissionInfo objTabPermission in _TabPermissions) + { + if (objTabPermission.UserID == user.UserID) + { + isMatch = true; + break; + } + } + + //user not found so add new + if (!isMatch) + { + foreach (PermissionInfo objPermission in permissions) + { + if (objPermission.PermissionKey == "VIEW") + { + AddPermission(objPermission, int.Parse(Globals.glbRoleNothing), Null.NullString, user.UserID, user.DisplayName, true); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Enabled status of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// + /// [cnurse] 01/13/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool GetEnabled(PermissionInfo objPerm, RoleInfo role, int column) + { + return role.RoleID != AdministratorRoleId; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Value of the permission + /// + /// The permission being loaded + /// The role + /// The column of the Grid + /// Default State. + /// A Boolean (True or False) + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override string GetPermission(PermissionInfo objPerm, RoleInfo role, int column, string defaultState) + { + string permission; + + if (role.RoleID == AdministratorRoleId) + { + permission = PermissionTypeGrant; + } + else + { + //Call base class method to handle standard permissions + permission = base.GetPermission(objPerm, role, column, PermissionTypeNull); + } + return permission; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the permissions from the Database + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override ArrayList GetPermissions() + { + return PermissionController.GetPermissionsByTab(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Load the ViewState + /// + /// The saved state + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override void LoadViewState(object savedState) + { + if (savedState != null) + { + //Load State from the array of objects that was saved with SaveViewState. + var myState = (object[])savedState; + + //Load Base Controls ViewState + if (myState[0] != null) + { + base.LoadViewState(myState[0]); + } + + //Load TabId + if (myState[1] != null) + { + TabID = Convert.ToInt32(myState[1]); + } + + //Load TabPermissions + if (myState[2] != null) + { + _TabPermissions = new TabPermissionCollection(); + string state = Convert.ToString(myState[2]); + if (!String.IsNullOrEmpty(state)) + { + //First Break the String into individual Keys + string[] permissionKeys = state.Split(new[] { "##" }, StringSplitOptions.None); + foreach (string key in permissionKeys) + { + string[] Settings = key.Split('|'); + _TabPermissions.Add(ParseKeys(Settings)); + } + } + } + } + } + + protected override void RemovePermission(int permissionID, int roleID, int userID) + { + _TabPermissions.Remove(permissionID, roleID, userID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Saves the ViewState + /// + /// + /// [cnurse] 01/12/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override object SaveViewState() + { + var allStates = new object[3]; + + //Save the Base Controls ViewState + allStates[0] = base.SaveViewState(); + + //Save the Tab Id + allStates[1] = TabID; + + //Persist the TabPermisisons + var sb = new StringBuilder(); + if (_TabPermissions != null) + { + bool addDelimiter = false; + foreach (TabPermissionInfo objTabPermission in _TabPermissions) + { + if (addDelimiter) + { + sb.Append("##"); + } + else + { + addDelimiter = true; + } + sb.Append(BuildKey(objTabPermission.AllowAccess, + objTabPermission.PermissionID, + objTabPermission.TabPermissionID, + objTabPermission.RoleID, + objTabPermission.RoleName, + objTabPermission.UserID, + objTabPermission.DisplayName)); + } + } + allStates[2] = sb.ToString(); + return allStates; + } + + /// ----------------------------------------------------------------------------- + /// + /// returns whether or not the derived grid supports Deny permissions + /// + /// + /// [cnurse] 01/09/2006 Created + /// + /// ----------------------------------------------------------------------------- + protected override bool SupportsDenyPermissions(PermissionInfo permissionInfo) + { + return true; + } + + #endregion + + #region "Public Methods" + + public override void GenerateDataGrid() + { + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/CorePermissionProvider.cs b/DNN Platform/Library/Security/Permissions/CorePermissionProvider.cs new file mode 100644 index 00000000000..7179f75e820 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/CorePermissionProvider.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.Security.Permissions +{ + public class CorePermissionProvider : PermissionProvider + { + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Permissions/DesktopModulePermissionCollection.cs b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionCollection.cs new file mode 100644 index 00000000000..059c450c76e --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionCollection.cs @@ -0,0 +1,199 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : DesktopModulePermissionCollection + /// ----------------------------------------------------------------------------- + /// + /// DesktopModulePermissionCollection provides the a custom collection for DesktopModulePermissionInfo + /// objects + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class DesktopModulePermissionCollection : CollectionBase + { + public DesktopModulePermissionCollection() + { + } + + public DesktopModulePermissionCollection(ArrayList DesktopModulePermissions) + { + AddRange(DesktopModulePermissions); + } + + public DesktopModulePermissionCollection(DesktopModulePermissionCollection DesktopModulePermissions) + { + AddRange(DesktopModulePermissions); + } + + public DesktopModulePermissionCollection(ArrayList DesktopModulePermissions, int DesktopModulePermissionID) + { + foreach (DesktopModulePermissionInfo permission in DesktopModulePermissions) + { + if (permission.DesktopModulePermissionID == DesktopModulePermissionID) + { + Add(permission); + } + } + } + + public DesktopModulePermissionInfo this[int index] + { + get + { + return (DesktopModulePermissionInfo) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(DesktopModulePermissionInfo value) + { + return List.Add(value); + } + + public int Add(DesktopModulePermissionInfo value, bool checkForDuplicates) + { + int id = Null.NullInteger; + if (!checkForDuplicates) + { + id = Add(value); + } + else + { + bool isMatch = false; + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == value.PermissionID && permission.UserID == value.UserID && permission.RoleID == value.RoleID) + { + isMatch = true; + break; + } + } + if (!isMatch) + { + id = Add(value); + } + } + + return id; + } + + public void AddRange(ArrayList DesktopModulePermissions) + { + foreach (DesktopModulePermissionInfo permission in DesktopModulePermissions) + { + Add(permission); + } + } + + public void AddRange(DesktopModulePermissionCollection DesktopModulePermissions) + { + foreach (DesktopModulePermissionInfo permission in DesktopModulePermissions) + { + Add(permission); + } + } + + public bool CompareTo(DesktopModulePermissionCollection objDesktopModulePermissionCollection) + { + if (objDesktopModulePermissionCollection.Count != Count) + { + return false; + } + InnerList.Sort(new CompareDesktopModulePermissions()); + objDesktopModulePermissionCollection.InnerList.Sort(new CompareDesktopModulePermissions()); + for (int i = 0; i <= Count - 1; i++) + { + if (objDesktopModulePermissionCollection[i].DesktopModulePermissionID != this[i].DesktopModulePermissionID || objDesktopModulePermissionCollection[i].AllowAccess != this[i].AllowAccess) + { + return false; + } + } + return true; + } + + public bool Contains(DesktopModulePermissionInfo value) + { + return List.Contains(value); + } + + public int IndexOf(DesktopModulePermissionInfo value) + { + return List.IndexOf(value); + } + + public void Insert(int index, DesktopModulePermissionInfo value) + { + List.Insert(index, value); + } + + public void Remove(DesktopModulePermissionInfo value) + { + List.Remove(value); + } + + public void Remove(int permissionID, int roleID, int userID) + { + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == permissionID && permission.UserID == userID && permission.RoleID == roleID) + { + List.Remove(permission); + break; + } + } + } + + public List ToList() + { + var list = new List(); + foreach (PermissionInfoBase permission in List) + { + list.Add(permission); + } + return list; + } + + public string ToString(string key) + { + return PermissionController.BuildPermissions(List, key); + } + } +} diff --git a/DNN Platform/Library/Security/Permissions/DesktopModulePermissionController.cs b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionController.cs new file mode 100644 index 00000000000..71a3c7dd776 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionController.cs @@ -0,0 +1,332 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : DesktopModulePermissionController + /// ----------------------------------------------------------------------------- + /// + /// DesktopModulePermissionController provides the Business Layer for DesktopModule Permissions + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class DesktopModulePermissionController + { + #region Private Members + + private static readonly DataProvider provider = DataProvider.Instance(); + + #endregion + + #region Private Shared Methods + + /// ----------------------------------------------------------------------------- + /// + /// ClearPermissionCache clears the DesktopModule Permission Cache + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static void ClearPermissionCache() + { + DataCache.ClearDesktopModulePermissionsCache(); + } + + /// ----------------------------------------------------------------------------- + /// + /// FillDesktopModulePermissionDictionary fills a Dictionary of DesktopModulePermissions from a + /// dataReader + /// + /// The IDataReader + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static Dictionary FillDesktopModulePermissionDictionary(IDataReader dr) + { + var dic = new Dictionary(); + try + { + while (dr.Read()) + { + //fill business object + var desktopModulePermissionInfo = CBO.FillObject(dr, false); + + //add DesktopModule Permission to dictionary + if (dic.ContainsKey(desktopModulePermissionInfo.PortalDesktopModuleID)) + { + //Add DesktopModulePermission to DesktopModulePermission Collection already in dictionary for TabId + dic[desktopModulePermissionInfo.PortalDesktopModuleID].Add(desktopModulePermissionInfo); + } + else + { + //Create new DesktopModulePermission Collection for DesktopModulePermissionID + var collection = new DesktopModulePermissionCollection {desktopModulePermissionInfo}; + + //Add Collection to Dictionary + dic.Add(desktopModulePermissionInfo.PortalDesktopModuleID, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModulePermissions gets a Dictionary of DesktopModulePermissionCollections by + /// DesktopModule. + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static Dictionary GetDesktopModulePermissions() + { + return CBO.GetCachedObject>( + new CacheItemArgs(DataCache.DesktopModulePermissionCacheKey, DataCache.DesktopModulePermissionCachePriority), GetDesktopModulePermissionsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModulePermissionsCallBack gets a Dictionary of DesktopModulePermissionCollections by + /// DesktopModule from the the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + private static object GetDesktopModulePermissionsCallBack(CacheItemArgs cacheItemArgs) + { + return FillDesktopModulePermissionDictionary(provider.GetDesktopModulePermissions()); + } + + #endregion + + #region Public Shared Methods + + /// ----------------------------------------------------------------------------- + /// + /// AddDesktopModulePermission adds a DesktopModule Permission to the Database + /// + /// The DesktopModule Permission to add + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static int AddDesktopModulePermission(DesktopModulePermissionInfo objDesktopModulePermission) + { + int Id = provider.AddDesktopModulePermission(objDesktopModulePermission.PortalDesktopModuleID, + objDesktopModulePermission.PermissionID, + objDesktopModulePermission.RoleID, + objDesktopModulePermission.AllowAccess, + objDesktopModulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objDesktopModulePermission, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + "", + EventLogController.EventLogType.DESKTOPMODULEPERMISSION_CREATED); + ClearPermissionCache(); + return Id; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModulePermission deletes a DesktopModule Permission in the Database + /// + /// The ID of the DesktopModule Permission to delete + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteDesktopModulePermission(int DesktopModulePermissionID) + { + provider.DeleteDesktopModulePermission(DesktopModulePermissionID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("DesktopModulePermissionID", + DesktopModulePermissionID.ToString(CultureInfo.InvariantCulture), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.DESKTOPMODULEPERMISSION_DELETED); + ClearPermissionCache(); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModulePermissionsByPortalDesktopModuleID deletes a DesktopModule's + /// DesktopModule Permission in the Database + /// + /// The ID of the DesktopModule to delete + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteDesktopModulePermissionsByPortalDesktopModuleID(int portalDesktopModuleID) + { + provider.DeleteDesktopModulePermissionsByPortalDesktopModuleID(portalDesktopModuleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalDesktopModuleID", + portalDesktopModuleID.ToString(CultureInfo.InvariantCulture), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.DESKTOPMODULE_DELETED); + ClearPermissionCache(); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteDesktopModulePermissionsByUserID deletes a user's DesktopModule Permission in the Database + /// + /// The user + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteDesktopModulePermissionsByUserID(UserInfo objUser) + { + provider.DeleteDesktopModulePermissionsByUserID(objUser.UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("UserID", + objUser.UserID.ToString(CultureInfo.InvariantCulture), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.DESKTOPMODULE_DELETED); + ClearPermissionCache(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModulePermission gets a DesktopModule Permission from the Database + /// + /// The ID of the DesktopModule Permission + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static DesktopModulePermissionInfo GetDesktopModulePermission(int DesktopModulePermissionID) + { + return CBO.FillObject(provider.GetDesktopModulePermission(DesktopModulePermissionID), true); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetDesktopModulePermissions gets a DesktopModulePermissionCollection + /// + /// The ID of the DesktopModule + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static DesktopModulePermissionCollection GetDesktopModulePermissions(int portalDesktopModuleID) + { + //Get the Tab DesktopModulePermission Dictionary + Dictionary dicDesktopModulePermissions = GetDesktopModulePermissions(); + + //Get the Collection from the Dictionary + DesktopModulePermissionCollection DesktopModulePermissions; + bool bFound = dicDesktopModulePermissions.TryGetValue(portalDesktopModuleID, out DesktopModulePermissions); + if (!bFound) + { + //Return empty collection + DesktopModulePermissions = new DesktopModulePermissionCollection(); + } + return DesktopModulePermissions; + } + + /// ----------------------------------------------------------------------------- + /// + /// HasDesktopModulePermission checks whether the current user has a specific DesktopModule Permission + /// + /// The Permissions for the DesktopModule + /// The Permission to check + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static bool HasDesktopModulePermission(DesktopModulePermissionCollection objDesktopModulePermissions, string permissionKey) + { + return PortalSecurity.IsInRoles(objDesktopModulePermissions.ToString(permissionKey)); + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateDesktopModulePermission updates a DesktopModule Permission in the Database + /// + /// The DesktopModule Permission to update + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void UpdateDesktopModulePermission(DesktopModulePermissionInfo objDesktopModulePermission) + { + provider.UpdateDesktopModulePermission(objDesktopModulePermission.DesktopModulePermissionID, + objDesktopModulePermission.PortalDesktopModuleID, + objDesktopModulePermission.PermissionID, + objDesktopModulePermission.RoleID, + objDesktopModulePermission.AllowAccess, + objDesktopModulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objDesktopModulePermission, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + "", + EventLogController.EventLogType.DESKTOPMODULEPERMISSION_UPDATED); + ClearPermissionCache(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/DesktopModulePermissionInfo.cs b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionInfo.cs new file mode 100644 index 00000000000..6c1df03eb4e --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/DesktopModulePermissionInfo.cs @@ -0,0 +1,256 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : DesktopModulePermissionInfo + /// ----------------------------------------------------------------------------- + /// + /// DesktopModulePermissionInfo provides the Entity Layer for DesktopModulePermissionInfo + /// Permissions + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class DesktopModulePermissionInfo : PermissionInfoBase, IHydratable + { + #region "Private Members" + + //local property declarations + private int _desktopModulePermissionID; + private int _portalDesktopModuleID; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new DesktopModulePermissionInfo + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public DesktopModulePermissionInfo() + { + _desktopModulePermissionID = Null.NullInteger; + _portalDesktopModuleID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new DesktopModulePermissionInfo + /// + /// A PermissionInfo object + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public DesktopModulePermissionInfo(PermissionInfo permission) : this() + { + ModuleDefID = permission.ModuleDefID; + PermissionCode = permission.PermissionCode; + PermissionID = permission.PermissionID; + PermissionKey = permission.PermissionKey; + PermissionName = permission.PermissionName; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the DesktopModule Permission ID + /// + /// An Integer + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int DesktopModulePermissionID + { + get + { + return _desktopModulePermissionID; + } + set + { + _desktopModulePermissionID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the PortalDesktopModule ID + /// + /// An Integer + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int PortalDesktopModuleID + { + get + { + return _portalDesktopModuleID; + } + set + { + _portalDesktopModuleID = value; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a DesktopModulePermissionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + base.FillInternal(dr); + DesktopModulePermissionID = Null.SetNullInteger(dr["DesktopModulePermissionID"]); + PortalDesktopModuleID = Null.SetNullInteger(dr["PortalDesktopModuleID"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return DesktopModulePermissionID; + } + set + { + DesktopModulePermissionID = value; + } + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Compares if two DesktopModulePermissionInfo objects are equivalent/equal + /// + /// a DesktopModulePermissionObject + /// true if the permissions being passed represents the same permission + /// in the current object + /// + /// + /// This function is needed to prevent adding duplicates to the DesktopModulePermissionCollection. + /// DesktopModulePermissionCollection.Contains will use this method to check if a given permission + /// is already included in the collection. + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool Equals(DesktopModulePermissionInfo other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return (AllowAccess == other.AllowAccess) && (PortalDesktopModuleID == other.PortalDesktopModuleID) && (RoleID == other.RoleID) && (PermissionID == other.PermissionID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Compares if two DesktopModulePermissionInfo objects are equivalent/equal + /// + /// a DesktopModulePermissionObject + /// true if the permissions being passed represents the same permission + /// in the current object + /// + /// + /// This function is needed to prevent adding duplicates to the DesktopModulePermissionCollection. + /// DesktopModulePermissionCollection.Contains will use this method to check if a given permission + /// is already included in the collection. + /// + /// + /// [cnurse] 01/15/2008 Created + /// + /// ----------------------------------------------------------------------------- + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != typeof (DesktopModulePermissionInfo)) + { + return false; + } + return Equals((DesktopModulePermissionInfo) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (_desktopModulePermissionID*397) ^ _portalDesktopModuleID; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/FolderPermissionCollection.cs b/DNN Platform/Library/Security/Permissions/FolderPermissionCollection.cs new file mode 100644 index 00000000000..cf775efae87 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/FolderPermissionCollection.cs @@ -0,0 +1,201 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + [Serializable] + public class FolderPermissionCollection : CollectionBase + { + public FolderPermissionCollection() + { + } + + public FolderPermissionCollection(ArrayList folderPermissions) + { + AddRange(folderPermissions); + } + + public FolderPermissionCollection(FolderPermissionCollection folderPermissions) + { + AddRange(folderPermissions); + } + + public FolderPermissionCollection(ArrayList folderPermissions, string FolderPath) + { + foreach (FolderPermissionInfo permission in folderPermissions) + { + if (permission.FolderPath.Equals(FolderPath, StringComparison.InvariantCultureIgnoreCase)) + { + Add(permission); + } + } + } + + public FolderPermissionInfo this[int index] + { + get + { + return (FolderPermissionInfo) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(FolderPermissionInfo value) + { + return List.Add(value); + } + + public int Add(FolderPermissionInfo value, bool checkForDuplicates) + { + int id = Null.NullInteger; + if (!checkForDuplicates) + { + id = Add(value); + } + else + { + bool isMatch = false; + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == value.PermissionID && permission.UserID == value.UserID && permission.RoleID == value.RoleID) + { + isMatch = true; + break; + } + } + if (!isMatch) + { + id = Add(value); + } + } + + return id; + } + + public void AddRange(ArrayList folderPermissions) + { + foreach (FolderPermissionInfo permission in folderPermissions) + { + List.Add(permission); + } + } + + public void AddRange(FolderPermissionCollection folderPermissions) + { + foreach (FolderPermissionInfo permission in folderPermissions) + { + List.Add(permission); + } + } + + public int IndexOf(FolderPermissionInfo value) + { + return List.IndexOf(value); + } + + public void Insert(int index, FolderPermissionInfo value) + { + List.Insert(index, value); + } + + public void Remove(FolderPermissionInfo value) + { + List.Remove(value); + } + + public void Remove(int permissionID, int roleID, int userID) + { + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == permissionID && permission.UserID == userID && permission.RoleID == roleID) + { + List.Remove(permission); + break; + } + } + } + + public bool Contains(FolderPermissionInfo value) + { + return List.Contains(value); + } + + public bool Contains(string key, int folderId, int roleId, int userId) + { + bool result = Null.NullBoolean; + foreach (FolderPermissionInfo permission in List) + { + if (permission.PermissionKey == key && permission.FolderID == folderId && permission.RoleID == roleId && permission.UserID == userId) + { + result = true; + break; + } + } + return result; + } + + + public bool CompareTo(FolderPermissionCollection objFolderPermissionCollection) + { + if (objFolderPermissionCollection.Count != Count) + { + return false; + } + InnerList.Sort(new CompareFolderPermissions()); + objFolderPermissionCollection.InnerList.Sort(new CompareFolderPermissions()); + for (int i = 0; i <= Count - 1; i++) + { + if (objFolderPermissionCollection[i].FolderPermissionID != this[i].FolderPermissionID || objFolderPermissionCollection[i].AllowAccess != this[i].AllowAccess) + { + return false; + } + } + return true; + } + + public List ToList() + { + var list = new List(); + foreach (PermissionInfoBase permission in List) + { + list.Add(permission); + } + return list; + } + + public string ToString(string key) + { + return PermissionController.BuildPermissions(List, key); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Permissions/FolderPermissionController.cs b/DNN Platform/Library/Security/Permissions/FolderPermissionController.cs new file mode 100644 index 00000000000..06b27978349 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/FolderPermissionController.cs @@ -0,0 +1,230 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + public class FolderPermissionController + { + private static readonly PermissionProvider provider = PermissionProvider.Instance(); + + private static void ClearPermissionCache(int PortalID) + { + DataCache.ClearFolderPermissionsCache(PortalID); + DataCache.ClearCache(string.Format("Folders|{0}|", PortalID)); + DataCache.ClearFolderCache(PortalID); + } + + public static bool CanAddFolder(FolderInfo folder) + { + return provider.CanAddFolder(folder) || CanAdminFolder(folder); + } + + public static bool CanAdminFolder(FolderInfo folder) + { + return provider.CanAdminFolder(folder); + } + + public static bool CanCopyFolder(FolderInfo folder) + { + return provider.CanCopyFolder(folder) || CanAdminFolder(folder); + } + + public static bool CanDeleteFolder(FolderInfo folder) + { + return provider.CanDeleteFolder(folder) || CanAdminFolder(folder); + } + + public static bool CanManageFolder(FolderInfo folder) + { + return provider.CanManageFolder(folder) || CanAdminFolder(folder); + } + + public static bool CanViewFolder(FolderInfo folder) + { + return provider.CanViewFolder(folder) || CanAdminFolder(folder); + } + + public static void DeleteFolderPermissionsByUser(UserInfo objUser) + { + provider.DeleteFolderPermissionsByUser(objUser); + ClearPermissionCache(objUser.PortalID); + } + + public static FolderPermissionCollection GetFolderPermissionsCollectionByFolder(int PortalID, string Folder) + { + return provider.GetFolderPermissionsCollectionByFolder(PortalID, Folder); + } + + public static bool HasFolderPermission(int portalId, string folderPath, string permissionKey) + { + return HasFolderPermission(GetFolderPermissionsCollectionByFolder(portalId, folderPath), permissionKey); + } + + public static bool HasFolderPermission(FolderPermissionCollection objFolderPermissions, string PermissionKey) + { + bool hasPermission = provider.HasFolderPermission(objFolderPermissions, "WRITE"); + if (!hasPermission) + { + if (PermissionKey.Contains(",")) + { + foreach (string permission in PermissionKey.Split(',')) + { + if (provider.HasFolderPermission(objFolderPermissions, permission)) + { + hasPermission = true; + break; + } + } + } + else + { + hasPermission = provider.HasFolderPermission(objFolderPermissions, PermissionKey); + } + } + return hasPermission; + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveFolderPermissions updates a Folder's permissions + /// + /// The Folder to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static void SaveFolderPermissions(FolderInfo folder) + { + SaveFolderPermissions((IFolderInfo)folder); + } + + /// + /// SaveFolderPermissions updates a Folder's permissions + /// + /// The Folder to update + public static void SaveFolderPermissions(IFolderInfo folder) + { + provider.SaveFolderPermissions(folder); + ClearPermissionCache(folder.PortalID); + } + + #region "Obsolete Methods" + + [Obsolete("Deprecated in DNN 5.1.")] + public int AddFolderPermission(FolderPermissionInfo objFolderPermission) + { + ClearPermissionCache(objFolderPermission.PortalID); + return DataProvider.Instance().AddFolderPermission(objFolderPermission.FolderID, + objFolderPermission.PermissionID, + objFolderPermission.RoleID, + objFolderPermission.AllowAccess, + objFolderPermission.UserID, + UserController.GetCurrentUserInfo().UserID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteFolderPermission(int FolderPermissionID) + { + DataProvider.Instance().DeleteFolderPermission(FolderPermissionID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteFolderPermissionsByFolder(int PortalID, string FolderPath) + { + DataProvider.Instance().DeleteFolderPermissionsByFolderPath(PortalID, FolderPath); + ClearPermissionCache(PortalID); + } + + [Obsolete("Deprecated in DNN 5.0. Use DeleteFolderPermissionsByUser(UserInfo) ")] + public void DeleteFolderPermissionsByUserID(UserInfo objUser) + { + DataProvider.Instance().DeleteFolderPermissionsByUserID(objUser.PortalID, objUser.UserID); + ClearPermissionCache(objUser.PortalID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public FolderPermissionInfo GetFolderPermission(int FolderPermissionID) + { + return CBO.FillObject(DataProvider.Instance().GetFolderPermission(FolderPermissionID), true); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetFolderPermissionsCollectionByFolderPath(PortalId, Folder)")] + public ArrayList GetFolderPermissionsByFolder(int PortalID, string Folder) + { + return CBO.FillCollection(DataProvider.Instance().GetFolderPermissionsByFolderPath(PortalID, Folder, -1), typeof(FolderPermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetFolderPermissionsCollectionByFolderPath(PortalId, Folder)")] + public FolderPermissionCollection GetFolderPermissionsByFolder(ArrayList arrFolderPermissions, string FolderPath) + { + return new FolderPermissionCollection(arrFolderPermissions, FolderPath); + } + + [Obsolete("Deprecated in DNN 5.1. GetModulePermissions(ModulePermissionCollection, String) ")] + public string GetFolderPermissionsByFolderPath(ArrayList arrFolderPermissions, string FolderPath, string PermissionKey) + { + //Create a Folder Permission Collection from the ArrayList + var folderPermissions = new FolderPermissionCollection(arrFolderPermissions, FolderPath); + + //Return the permission string for permissions with specified FolderPath + return folderPermissions.ToString(PermissionKey); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetFolderPermissionsCollectionByFolder(PortalId, Folder)")] + public FolderPermissionCollection GetFolderPermissionsCollectionByFolderPath(int PortalID, string Folder) + { + return GetFolderPermissionsCollectionByFolder(PortalID, Folder); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetFolderPermissionsCollectionByFolder(PortalId, Folder)")] + public FolderPermissionCollection GetFolderPermissionsCollectionByFolderPath(ArrayList arrFolderPermissions, string FolderPath) + { + var objFolderPermissionCollection = new FolderPermissionCollection(arrFolderPermissions, FolderPath); + return objFolderPermissionCollection; + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void UpdateFolderPermission(FolderPermissionInfo objFolderPermission) + { + DataProvider.Instance().UpdateFolderPermission(objFolderPermission.FolderPermissionID, + objFolderPermission.FolderID, + objFolderPermission.PermissionID, + objFolderPermission.RoleID, + objFolderPermission.AllowAccess, + objFolderPermission.UserID, + UserController.GetCurrentUserInfo().UserID); + ClearPermissionCache(objFolderPermission.PortalID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/FolderPermissionInfo.cs b/DNN Platform/Library/Security/Permissions/FolderPermissionInfo.cs new file mode 100644 index 00000000000..820323af301 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/FolderPermissionInfo.cs @@ -0,0 +1,185 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + [Serializable] + public class FolderPermissionInfo : PermissionInfoBase, IHydratable + { + #region "Private Members" + + //local property declarations + private int _folderID; + private string _folderPath; + private int _folderPermissionID; + private int _portalID; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new FolderPermissionInfo + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public FolderPermissionInfo() + { + _folderPermissionID = Null.NullInteger; + _folderPath = Null.NullString; + _portalID = Null.NullInteger; + _folderID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new FolderPermissionInfo + /// + /// A PermissionInfo object + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public FolderPermissionInfo(PermissionInfo permission) : this() + { + ModuleDefID = permission.ModuleDefID; + PermissionCode = permission.PermissionCode; + PermissionID = permission.PermissionID; + PermissionKey = permission.PermissionKey; + PermissionName = permission.PermissionName; + } + + #endregion + + #region "Public Properties" + + [XmlIgnore] + public int FolderPermissionID + { + get + { + return _folderPermissionID; + } + set + { + _folderPermissionID = value; + } + } + + [XmlIgnore] + public int FolderID + { + get + { + return _folderID; + } + set + { + _folderID = value; + } + } + + [XmlIgnore] + public int PortalID + { + get + { + return _portalID; + } + set + { + _portalID = value; + } + } + + [XmlElement("folderpath")] + public string FolderPath + { + get + { + return _folderPath; + } + set + { + _folderPath = value; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a FolderPermissionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 05/23/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + base.FillInternal(dr); + FolderPermissionID = Null.SetNullInteger(dr["FolderPermissionID"]); + FolderID = Null.SetNullInteger(dr["FolderID"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + FolderPath = Null.SetNullString(dr["FolderPath"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 05/23/2008 Created + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int KeyID + { + get + { + return FolderPermissionID; + } + set + { + FolderPermissionID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/ModulePermissionCollection.cs b/DNN Platform/Library/Security/Permissions/ModulePermissionCollection.cs new file mode 100644 index 00000000000..7ce45e7847b --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/ModulePermissionCollection.cs @@ -0,0 +1,217 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : ModulePermissionCollection + /// ----------------------------------------------------------------------------- + /// + /// ModulePermissionCollection provides the a custom collection for ModulePermissionInfo + /// objects + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ModulePermissionCollection : CollectionBase + { + public ModulePermissionCollection() + { + } + + public ModulePermissionCollection(ArrayList modulePermissions) + { + AddRange(modulePermissions); + } + + public ModulePermissionCollection(ModulePermissionCollection modulePermissions) + { + AddRange(modulePermissions); + } + + public ModulePermissionCollection(ArrayList modulePermissions, int ModuleID) + { + foreach (ModulePermissionInfo permission in modulePermissions) + { + if (permission.ModuleID == ModuleID) + { + Add(permission); + } + } + } + + public ModulePermissionCollection(ModuleInfo objModule) + { + foreach (ModulePermissionInfo permission in objModule.ModulePermissions) + { + if (permission.ModuleID == objModule.ModuleID) + { + Add(permission); + } + } + } + + public ModulePermissionInfo this[int index] + { + get + { + return (ModulePermissionInfo) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(ModulePermissionInfo value) + { + return List.Add(value); + } + + public int Add(ModulePermissionInfo value, bool checkForDuplicates) + { + int id = Null.NullInteger; + if (!checkForDuplicates) + { + id = Add(value); + } + else + { + bool isMatch = false; + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == value.PermissionID && permission.UserID == value.UserID && permission.RoleID == value.RoleID) + { + isMatch = true; + break; + } + } + if (!isMatch) + { + id = Add(value); + } + } + + return id; + } + + public void AddRange(ArrayList modulePermissions) + { + foreach (ModulePermissionInfo permission in modulePermissions) + { + Add(permission); + } + } + + public void AddRange(ModulePermissionCollection modulePermissions) + { + foreach (ModulePermissionInfo permission in modulePermissions) + { + Add(permission); + } + } + + public bool CompareTo(ModulePermissionCollection objModulePermissionCollection) + { + if (objModulePermissionCollection.Count != Count) + { + return false; + } + InnerList.Sort(new CompareModulePermissions()); + objModulePermissionCollection.InnerList.Sort(new CompareModulePermissions()); + for (int i = 0; i <= Count - 1; i++) + { + if (objModulePermissionCollection[i].ModulePermissionID != this[i].ModulePermissionID || objModulePermissionCollection[i].AllowAccess != this[i].AllowAccess) + { + return false; + } + } + return true; + } + + public bool Contains(ModulePermissionInfo value) + { + return List.Contains(value); + } + + public int IndexOf(ModulePermissionInfo value) + { + return List.IndexOf(value); + } + + public void Insert(int index, ModulePermissionInfo value) + { + List.Insert(index, value); + } + + public void Remove(ModulePermissionInfo value) + { + List.Remove(value); + } + + public void Remove(int permissionID, int roleID, int userID) + { + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == permissionID && permission.UserID == userID && permission.RoleID == roleID) + { + List.Remove(permission); + break; + } + } + } + + public List ToList() + { + var list = new List(); + foreach (PermissionInfoBase permission in List) + { + list.Add(permission); + } + return list; + } + + public string ToString(string key) + { + return PermissionController.BuildPermissions(List, key); + } + + public IEnumerable Where(Func predicate) + { + return this.Cast().Where(predicate); + } + } +} diff --git a/DNN Platform/Library/Security/Permissions/ModulePermissionController.cs b/DNN Platform/Library/Security/Permissions/ModulePermissionController.cs new file mode 100644 index 00000000000..de0d2e5e8dd --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/ModulePermissionController.cs @@ -0,0 +1,444 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Text.RegularExpressions; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : ModulePermissionController + /// ----------------------------------------------------------------------------- + /// + /// ModulePermissionController provides the Business Layer for Module Permissions + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class ModulePermissionController + { + #region Private Members + + private static readonly PermissionProvider Provider = PermissionProvider.Instance(); + + #endregion + + #region Private Methods + + private static void ClearPermissionCache(int moduleId) + { + var objModules = new ModuleController(); + ModuleInfo objModule = objModules.GetModule(moduleId, Null.NullInteger, false); + DataCache.ClearModulePermissionsCache(objModule.TabID); + } + + private static bool CanAddContentToPage(ModuleInfo objModule) + { + TabInfo objTab = new TabController().GetTab(objModule.TabID, objModule.PortalID, false); + return TabPermissionController.CanAddContentToPage(objTab); + } + + #endregion + + #region Public Methods + + public static bool CanAdminModule(ModuleInfo module) + { + return Provider.CanAdminModule(module); + } + + public static bool CanDeleteModule(ModuleInfo module) + { + return CanAddContentToPage(module) || Provider.CanDeleteModule(module); + } + + public static bool CanEditModuleContent(ModuleInfo module) + { + return CanAddContentToPage(module) || Provider.CanEditModuleContent(module); + } + + public static bool CanExportModule(ModuleInfo module) + { + return Provider.CanExportModule(module); + } + + public static bool CanImportModule(ModuleInfo module) + { + return Provider.CanImportModule(module); + } + + public static bool CanManageModule(ModuleInfo module) + { + return CanAddContentToPage(module) || Provider.CanManageModule(module); + } + + public static bool CanViewModule(ModuleInfo module) + { + bool canView; + if (module.InheritViewPermissions) + { + TabInfo objTab = new TabController().GetTab(module.TabID, module.PortalID, false); + canView = TabPermissionController.CanViewPage(objTab); + } + else + { + canView = Provider.CanViewModule(module); + } + + return canView; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteModulePermissionsByUser deletes a user's Module Permission in the Database + /// + /// The user + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteModulePermissionsByUser(UserInfo user) + { + Provider.DeleteModulePermissionsByUser(user); + DataCache.ClearModulePermissionsCachesByPortal(user.PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModulePermissions gets a ModulePermissionCollection + /// + /// The ID of the module + /// The ID of the tab + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static ModulePermissionCollection GetModulePermissions(int moduleID, int tabID) + { + return Provider.GetModulePermissions(moduleID, tabID); + } + + /// ----------------------------------------------------------------------------- + /// + /// HasModulePermission checks whether the current user has a specific Module Permission + /// + /// If you pass in a comma delimited list of permissions (eg "ADD,DELETE", this will return + /// true if the user has any one of the permissions. + /// The Permissions for the Module + /// The Permission to check + /// + /// [cnurse] 01/15/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public static bool HasModulePermission(ModulePermissionCollection modulePermissions, string permissionKey) + { + bool hasPermission = Null.NullBoolean; + if (permissionKey.Contains(",")) + { + foreach (string permission in permissionKey.Split(',')) + { + if (Provider.HasModulePermission(modulePermissions, permission)) + { + hasPermission = true; + break; + } + } + } + else + { + hasPermission = Provider.HasModulePermission(modulePermissions, permissionKey); + } + return hasPermission; + } + + ///----------------------------------------------------------------------------- + /// + /// Determines if user has the necessary permissions to access an item with the + /// designated AccessLevel. + /// + /// The SecurityAccessLevel required to access a portal module or module action. + /// If Security Access is Edit the permissionKey is the actual "edit" permisison required. + /// The ModuleInfo object for the associated module. + /// A boolean value indicating if the user has the necessary permissions + /// Every module control and module action has an associated permission level. This + /// function determines whether the user represented by UserName has sufficient permissions, as + /// determined by the PortalSettings and ModuleSettings, to access a resource with the + /// designated AccessLevel. + ///----------------------------------------------------------------------------- + public static bool HasModuleAccess(SecurityAccessLevel accessLevel, string permissionKey, ModuleInfo moduleConfiguration) + { + bool isAuthorized = false; + UserInfo userInfo = UserController.GetCurrentUserInfo(); + if (userInfo != null && userInfo.IsSuperUser) + { + isAuthorized = true; + } + else + { + switch (accessLevel) + { + case SecurityAccessLevel.Anonymous: + isAuthorized = true; + break; + case SecurityAccessLevel.View: + if (CanViewModule(moduleConfiguration)) + { + isAuthorized = true; + } + break; + case SecurityAccessLevel.ViewPermissions: + isAuthorized = TabPermissionController.CanAddContentToPage(); + break; + case SecurityAccessLevel.Edit: + if (moduleConfiguration != null && !((moduleConfiguration.IsShared && moduleConfiguration.IsShareableViewOnly) + && TabPermissionController.CanAddContentToPage())) + { + if (TabPermissionController.CanAddContentToPage()) + { + isAuthorized = true; + } + else + { + if (string.IsNullOrEmpty(permissionKey)) + { + permissionKey = "CONTENT,DELETE,EDIT,EXPORT,IMPORT,MANAGE"; + } + if (CanViewModule(moduleConfiguration) && + (HasModulePermission(moduleConfiguration.ModulePermissions, permissionKey) + || HasModulePermission(moduleConfiguration.ModulePermissions, "EDIT"))) + { + isAuthorized = true; + } + } + } + break; + case SecurityAccessLevel.Admin: + if (moduleConfiguration != null && !((moduleConfiguration.IsShared && moduleConfiguration.IsShareableViewOnly) + && TabPermissionController.CanAddContentToPage())) + { + isAuthorized = TabPermissionController.CanAddContentToPage(); + } + break; + case SecurityAccessLevel.Host: + break; + } + } + return isAuthorized; + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveModulePermissions updates a Module's permissions + /// + /// The Module to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static void SaveModulePermissions(ModuleInfo module) + { + Provider.SaveModulePermissions(module); + DataCache.ClearModulePermissionsCache(module.TabID); + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DNN 5.1.")] + public int AddModulePermission(ModulePermissionInfo modulePermission, int tabId) + { + PortalSettings portal = PortalSettings.Current; + + int id = DataProvider.Instance().AddModulePermission(modulePermission.ModuleID, + portal.PortalId, + modulePermission.PermissionID, + modulePermission.RoleID, + modulePermission.AllowAccess, + modulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + DataCache.ClearModulePermissionsCache(tabId); + return id; + } + + [Obsolete("Deprecated in DNN 5.0.")] + public int AddModulePermission(ModulePermissionInfo modulePermission) + { + PortalSettings portal = PortalSettings.Current; + + int id = DataProvider.Instance().AddModulePermission(modulePermission.ModuleID, + portal.PortalId, + modulePermission.PermissionID, + modulePermission.RoleID, + modulePermission.AllowAccess, + modulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + ClearPermissionCache(modulePermission.ModuleID); + return id; + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteModulePermission(int modulePermissionID) + { + DataProvider.Instance().DeleteModulePermission(modulePermissionID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteModulePermissionsByModuleID(int moduleID) + { + PortalSettings portal = PortalSettings.Current; + + DataProvider.Instance().DeleteModulePermissionsByModuleID(moduleID, portal.PortalId); + ClearPermissionCache(moduleID); + } + + [Obsolete("Deprecated in DNN 5.0. Use DeleteModulePermissionsByUser(UserInfo) ")] + public void DeleteModulePermissionsByUserID(UserInfo objUser) + { + DataProvider.Instance().DeleteModulePermissionsByUserID(objUser.PortalID, objUser.UserID); + DataCache.ClearModulePermissionsCachesByPortal(objUser.PortalID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public ModulePermissionInfo GetModulePermission(int modulePermissionID) + { + return CBO.FillObject(DataProvider.Instance().GetModulePermission(modulePermissionID), true); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by ModulePermissionColelction.ToString(String)")] + public string GetModulePermissions(ModulePermissionCollection modulePermissions, string permissionKey) + { + return modulePermissions.ToString(permissionKey); + } + + [Obsolete("Deprecated in DNN 5.0. This should have been declared as Friend as it was never meant to be used outside of the core.")] + public ArrayList GetModulePermissionsByPortal(int portalID) + { + return CBO.FillCollection(DataProvider.Instance().GetModulePermissionsByPortal(portalID), typeof (ModulePermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0. This should have been declared as Friend as it was never meant to be used outside of the core.")] + public ArrayList GetModulePermissionsByTabID(int tabID) + { + return CBO.FillCollection(DataProvider.Instance().GetModulePermissionsByTabID(tabID), typeof (ModulePermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0. Use GetModulePermissions(ModulePermissionCollection, String) ")] + public string GetModulePermissionsByModuleID(ModuleInfo objModule, string permissionKey) + { + //Create a Module Permission Collection from the ArrayList + var modulePermissions = new ModulePermissionCollection(objModule); + + //Return the permission string for permissions with specified TabId + return modulePermissions.ToString(permissionKey); + } + + [Obsolete("Deprecated in DNN 5.1. GetModulePermissions(integer, integer) ")] + public ModulePermissionCollection GetModulePermissionsCollectionByModuleID(int moduleID, int tabID) + { + return GetModulePermissions(moduleID, tabID); + } + + [Obsolete("Deprecated in DNN 5.0. Use GetModulePermissions(integer, integer) ")] + public ModulePermissionCollection GetModulePermissionsCollectionByModuleID(int moduleID) + { + return new ModulePermissionCollection(CBO.FillCollection(DataProvider.Instance().GetModulePermissionsByModuleID(moduleID, -1), typeof (ModulePermissionInfo))); + } + + [Obsolete("Deprecated in DNN 5.0. Use GetModulePermissions(integer, integer) ")] + public ModulePermissionCollection GetModulePermissionsCollectionByModuleID(ArrayList arrModulePermissions, int moduleID) + { + return new ModulePermissionCollection(arrModulePermissions, moduleID); + } + + [Obsolete("Deprecated in DNN 5.0. It was used to replace lists of RoleIds by lists of RoleNames.")] + public string GetRoleNamesFromRoleIDs(string roles) + { + string strRoles = ""; + if (roles.IndexOf(";") > 0) + { + string[] arrRoles = roles.Split(';'); + for (int i = 0; i <= arrRoles.Length - 1; i++) + { + if (Regex.IsMatch(arrRoles[i], "^\\d+$")) + { + strRoles += Globals.GetRoleName(Convert.ToInt32(arrRoles[i])) + ";"; + } + } + } + else if (roles.Trim().Length > 0) + { + strRoles = Globals.GetRoleName(Convert.ToInt32(roles.Trim())); + } + if (!strRoles.StartsWith(";")) + { + strRoles += ";"; + } + return strRoles; + } + + [Obsolete("Deprecated in DNN 5.0. Use HasModulePermission(ModulePermissionCollection, string)")] + public static bool HasModulePermission(int moduleID, string permissionKey) + { + var objModulePermissions = new ModulePermissionCollection(CBO.FillCollection(DataProvider.Instance().GetModulePermissionsByModuleID(moduleID, -1), typeof (ModulePermissionInfo))); + return HasModulePermission(objModulePermissions, permissionKey); + } + + [Obsolete("Deprecated in DNN 5.1. Use HasModulePermission(ModulePermissionCollection, string)")] + public static bool HasModulePermission(int moduleID, int tabID, string permissionKey) + { + return HasModulePermission(GetModulePermissions(moduleID, tabID), permissionKey); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void UpdateModulePermission(ModulePermissionInfo modulePermission) + { + PortalSettings portal = PortalSettings.Current; + + DataProvider.Instance().UpdateModulePermission(modulePermission.ModulePermissionID, + portal.PortalId, + modulePermission.ModuleID, + modulePermission.PermissionID, + modulePermission.RoleID, + modulePermission.AllowAccess, + modulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + ClearPermissionCache(modulePermission.ModuleID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/ModulePermissionInfo.cs b/DNN Platform/Library/Security/Permissions/ModulePermissionInfo.cs new file mode 100644 index 00000000000..d5d7863f599 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/ModulePermissionInfo.cs @@ -0,0 +1,260 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : ModulePermissionInfo + /// ----------------------------------------------------------------------------- + /// + /// ModulePermissionInfo provides the Entity Layer for Module Permissions + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class ModulePermissionInfo : PermissionInfoBase, IHydratable + { + #region "Private Members" + + private int _moduleID; + + //local property declarations + private int _modulePermissionID; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new ModulePermissionInfo + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public ModulePermissionInfo() + { + _modulePermissionID = Null.NullInteger; + _moduleID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new ModulePermissionInfo + /// + /// A PermissionInfo object + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public ModulePermissionInfo(PermissionInfo permission) : this() + { + ModuleDefID = permission.ModuleDefID; + PermissionCode = permission.PermissionCode; + PermissionID = permission.PermissionID; + PermissionKey = permission.PermissionKey; + PermissionName = permission.PermissionName; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module Permission ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("modulepermissionid")] + public int ModulePermissionID + { + get + { + return _modulePermissionID; + } + set + { + _modulePermissionID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("moduleid")] + public int ModuleID + { + get + { + return _moduleID; + } + set + { + _moduleID = value; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a ModulePermissionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + base.FillInternal(dr); + ModulePermissionID = Null.SetNullInteger(dr["ModulePermissionID"]); + ModuleID = Null.SetNullInteger(dr["ModuleID"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int KeyID + { + get + { + return ModulePermissionID; + } + set + { + ModulePermissionID = value; + } + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Compares if two ModulePermissionInfo objects are equivalent/equal + /// + /// a ModulePermissionObject + /// true if the permissions being passed represents the same permission + /// in the current object + /// + /// + /// This function is needed to prevent adding duplicates to the ModulePermissionCollection. + /// ModulePermissionCollection.Contains will use this method to check if a given permission + /// is already included in the collection. + /// + /// + /// [Vicen] 09/01/2005 Created + /// + /// ----------------------------------------------------------------------------- + public bool Equals(ModulePermissionInfo other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return (AllowAccess == other.AllowAccess) && (ModuleID == other.ModuleID) && (RoleID == other.RoleID) && (PermissionID == other.PermissionID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Compares if two ModulePermissionInfo objects are equivalent/equal + /// + /// a ModulePermissionObject + /// true if the permissions being passed represents the same permission + /// in the current object + /// + /// + /// This function is needed to prevent adding duplicates to the ModulePermissionCollection. + /// ModulePermissionCollection.Contains will use this method to check if a given permission + /// is already included in the collection. + /// + /// + /// [Vicen] 09/01/2005 Created + /// + /// ----------------------------------------------------------------------------- + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + if (obj.GetType() != typeof (ModulePermissionInfo)) + { + return false; + } + return Equals((ModulePermissionInfo) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (_moduleID*397) ^ _modulePermissionID; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/PermissionController.cs b/DNN Platform/Library/Security/Permissions/PermissionController.cs new file mode 100644 index 00000000000..eed6d55d659 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/PermissionController.cs @@ -0,0 +1,242 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + public class PermissionController + { + #region Public Methods + + private static readonly DataProvider provider = DataProvider.Instance(); + + public int AddPermission(PermissionInfo objPermission) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(objPermission, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PERMISSION_CREATED); + return + Convert.ToInt32(provider.AddPermission(objPermission.PermissionCode, + objPermission.ModuleDefID, + objPermission.PermissionKey, + objPermission.PermissionName, + UserController.GetCurrentUserInfo().UserID)); + } + + public void DeletePermission(int permissionID) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("PermissionID", + permissionID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PERMISSION_DELETED); + provider.DeletePermission(permissionID); + } + + public PermissionInfo GetPermission(int permissionID) + { + return CBO.FillObject(provider.GetPermission(permissionID)); + } + + public ArrayList GetPermissionByCodeAndKey(string permissionCode, string permissionKey) + { + return CBO.FillCollection(provider.GetPermissionByCodeAndKey(permissionCode, permissionKey), typeof (PermissionInfo)); + } + + public ArrayList GetPermissionsByModuleDefID(int moduleDefID) + { + return CBO.FillCollection(provider.GetPermissionsByModuleDefID(moduleDefID), typeof (PermissionInfo)); + } + + public ArrayList GetPermissionsByModuleID(int moduleID) + { + return CBO.FillCollection(provider.GetPermissionsByModuleID(moduleID), typeof (PermissionInfo)); + } + + public void UpdatePermission(PermissionInfo objPermission) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(objPermission, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PERMISSION_UPDATED); + provider.UpdatePermission(objPermission.PermissionID, + objPermission.PermissionCode, + objPermission.ModuleDefID, + objPermission.PermissionKey, + objPermission.PermissionName, + UserController.GetCurrentUserInfo().UserID); + } + + #endregion + + #region Shared Methods + + public static string BuildPermissions(IList Permissions, string PermissionKey) + { + var permissionsBuilder = new StringBuilder(); + foreach (PermissionInfoBase permission in Permissions) + { + if (permission.PermissionKey.ToLowerInvariant() == PermissionKey.ToLowerInvariant()) + { + //Deny permissions are prefixed with a "!" + string prefix = !permission.AllowAccess ? "!" : ""; + + //encode permission + string permissionString; + if (Null.IsNull(permission.UserID)) + { + permissionString = prefix + permission.RoleName + ";"; + } + else + { + permissionString = prefix + "[" + permission.UserID + "];"; + } + + //build permissions string ensuring that Deny permissions are inserted at the beginning and Grant permissions at the end + if (prefix == "!") + { + permissionsBuilder.Insert(0, permissionString); + } + else + { + permissionsBuilder.Append(permissionString); + } + } + } + + //get string + string permissionsString = permissionsBuilder.ToString(); + + //ensure leading delimiter + if (!permissionsString.StartsWith(";")) + { + permissionsString.Insert(0, ";"); + } + return permissionsString; + } + + public static ArrayList GetPermissionsByFolder() + { + return CBO.FillCollection(provider.GetPermissionsByFolder(), typeof (PermissionInfo)); + } + + public static ArrayList GetPermissionsByPortalDesktopModule() + { + return CBO.FillCollection(provider.GetPermissionsByPortalDesktopModule(), typeof (PermissionInfo)); + } + + public static ArrayList GetPermissionsByTab() + { + return CBO.FillCollection(provider.GetPermissionsByTab(), typeof (PermissionInfo)); + } + + public T RemapPermission(T permission, int portalId) where T : PermissionInfoBase + { + PermissionInfo permissionInfo = GetPermissionByCodeAndKey(permission.PermissionCode, permission.PermissionKey).ToArray().Cast().FirstOrDefault(); + T result = null; + + if ((permissionInfo != null)) + { + int RoleID = int.MinValue; + int UserID = int.MinValue; + + if ((string.IsNullOrEmpty(permission.RoleName))) + { + UserInfo _user = UserController.GetUserByName(portalId, permission.Username); + if ((_user != null)) + { + UserID = _user.UserID; + } + } + else + { + switch (permission.RoleName) + { + case Globals.glbRoleAllUsersName: + RoleID = Convert.ToInt32(Globals.glbRoleAllUsers); + break; + case Globals.glbRoleUnauthUserName: + RoleID = Convert.ToInt32(Globals.glbRoleUnauthUser); + break; + default: + RoleInfo _role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleName == permission.RoleName); + if ((_role != null)) + { + RoleID = _role.RoleID; + } + break; + } + } + + // if role was found add, otherwise ignore + if (RoleID != int.MinValue || UserID != int.MinValue) + { + permission.PermissionID = permissionInfo.PermissionID; + if ((RoleID != int.MinValue)) + { + permission.RoleID = RoleID; + } + if ((UserID != int.MinValue)) + { + permission.UserID = UserID; + } + result = permission; + } + } + + return result; + } + + #endregion + + [Obsolete("Deprecated in DNN 5.0.1. Replaced by GetPermissionsByFolder()")] + public ArrayList GetPermissionsByFolder(int portalID, string folder) + { + return CBO.FillCollection(provider.GetPermissionsByFolder(), typeof (PermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0.1. Replaced by GetPermissionsByTab()")] + public ArrayList GetPermissionsByTabID(int tabID) + { + return CBO.FillCollection(provider.GetPermissionsByTab(), typeof (PermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0.1. Replaced by GetPermissionsByPortalDesktopModule()")] + public ArrayList GetPermissionsByPortalDesktopModuleID() + { + return CBO.FillCollection(provider.GetPermissionsByPortalDesktopModule(), typeof (PermissionInfo)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Permissions/PermissionInfo.cs b/DNN Platform/Library/Security/Permissions/PermissionInfo.cs new file mode 100644 index 00000000000..5c3dcc5677b --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/PermissionInfo.cs @@ -0,0 +1,196 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : PermissionInfo + /// ----------------------------------------------------------------------------- + /// + /// PermissionInfo provides the Entity Layer for Permissions + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class PermissionInfo : BaseEntityInfo + { + #region "Private Members" + + private int _ModuleDefID; + private string _PermissionCode; + private int _PermissionID; + private string _PermissionKey; + private string _PermissionName; + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Mdoule Definition ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int ModuleDefID + { + get + { + return _ModuleDefID; + } + set + { + _ModuleDefID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Permission Code + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("permissioncode")] + public string PermissionCode + { + get + { + return _PermissionCode; + } + set + { + _PermissionCode = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Permission ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("permissionid")] + public int PermissionID + { + get + { + return _PermissionID; + } + set + { + _PermissionID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Permission Key + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("permissionkey")] + public string PermissionKey + { + get + { + return _PermissionKey; + } + set + { + _PermissionKey = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Permission Name + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public string PermissionName + { + get + { + return _PermissionName; + } + set + { + _PermissionName = value; + } + } + + #endregion + + #region "Protected methods" + + /// ----------------------------------------------------------------------------- + /// + /// FillInternal fills a PermissionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + protected override void FillInternal(IDataReader dr) + { + base.FillInternal(dr); + PermissionID = Null.SetNullInteger(dr["PermissionID"]); + ModuleDefID = Null.SetNullInteger(dr["ModuleDefID"]); + PermissionCode = Null.SetNullString(dr["PermissionCode"]); + PermissionKey = Null.SetNullString(dr["PermissionKey"]); + PermissionName = Null.SetNullString(dr["PermissionName"]); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs b/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs new file mode 100644 index 00000000000..b8c89cd7ec0 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/PermissionInfoBase.cs @@ -0,0 +1,254 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : PermissionInfoBase + /// ----------------------------------------------------------------------------- + /// + /// PermissionInfoBase provides a base class for PermissionInfo classes + /// + /// All Permission calsses have a common set of properties + /// - AllowAccess + /// - RoleID + /// - RoleName + /// - UserID + /// - Username + /// - DisplayName + /// + /// and these are implemented in this base class + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public abstract class PermissionInfoBase : PermissionInfo + { + #region "Private Members" + + private bool _AllowAccess; + private string _DisplayName; + private int _RoleID; + private string _RoleName; + private int _UserID; + private string _Username; + + #endregion + + #region "Constructors" + + public PermissionInfoBase() + { + _RoleID = int.Parse(Globals.glbRoleNothing); + _AllowAccess = false; + _RoleName = Null.NullString; + _UserID = Null.NullInteger; + _Username = Null.NullString; + _DisplayName = Null.NullString; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets aflag that indicates whether the user or role has permission + /// + /// A Boolean + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("allowaccess")] + public bool AllowAccess + { + get + { + return _AllowAccess; + } + set + { + _AllowAccess = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User's DisplayName + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("displayname")] + public string DisplayName + { + get + { + return _DisplayName; + } + set + { + _DisplayName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Role ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("roleid")] + public int RoleID + { + get + { + return _RoleID; + } + set + { + _RoleID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Role Name + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("rolename")] + public string RoleName + { + get + { + return _RoleName; + } + set + { + _RoleName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("userid")] + public int UserID + { + get + { + return _UserID; + } + set + { + _UserID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User Name + /// + /// A String + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("username")] + public string Username + { + get + { + return _Username; + } + set + { + _Username = value; + } + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// FillInternal fills the PermissionInfoBase from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + protected override void FillInternal(IDataReader dr) + { + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + + UserID = Null.SetNullInteger(dr["UserID"]); + Username = Null.SetNullString(dr["Username"]); + DisplayName = Null.SetNullString(dr["DisplayName"]); + if (UserID == Null.NullInteger) + { + RoleID = Null.SetNullInteger(dr["RoleID"]); + RoleName = Null.SetNullString(dr["RoleName"]); + } + else + { + RoleID = int.Parse(Globals.glbRoleNothing); + RoleName = ""; + } + AllowAccess = Null.SetNullBoolean(dr["AllowAccess"]); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/PermissionProvider.cs b/DNN Platform/Library/Security/Permissions/PermissionProvider.cs new file mode 100644 index 00000000000..9048e62c7c7 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/PermissionProvider.cs @@ -0,0 +1,736 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + public class PermissionProvider + { + #region Private Members + + //Folder Permission Codes + private const string AdminFolderPermissionCode = "WRITE"; + private const string AddFolderPermissionCode = "WRITE"; + private const string CopyFolderPermissionCode = "WRITE"; + private const string DeleteFolderPermissionCode = "WRITE"; + private const string ManageFolderPermissionCode = "WRITE"; + private const string ViewFolderPermissionCode = "READ"; + + //Module Permission Codes + private const string AdminModulePermissionCode = "EDIT"; + private const string ContentModulePermissionCode = "EDIT"; + private const string DeleteModulePermissionCode = "EDIT"; + private const string ExportModulePermissionCode = "EDIT"; + private const string ImportModulePermissionCode = "EDIT"; + private const string ManageModulePermissionCode = "EDIT"; + private const string ViewModulePermissionCode = "VIEW"; + + //Page Permission Codes + private const string AddPagePermissionCode = "EDIT"; + private const string AdminPagePermissionCode = "EDIT"; + private const string ContentPagePermissionCode = "EDIT"; + private const string CopyPagePermissionCode = "EDIT"; + private const string DeletePagePermissionCode = "EDIT"; + private const string ExportPagePermissionCode = "EDIT"; + private const string ImportPagePermissionCode = "EDIT"; + private const string ManagePagePermissionCode = "EDIT"; + private const string NavigatePagePermissionCode = "VIEW"; + private const string ViewPagePermissionCode = "VIEW"; + private readonly DataProvider dataProvider = DataProvider.Instance(); + + #endregion + + #region Shared/Static Methods + + //return the provider + public virtual string LocalResourceFile + { + get + { + return Localization.GlobalResourceFile; + } + } + + public static PermissionProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region Private Methods + + private object GetFolderPermissionsCallBack(CacheItemArgs cacheItemArgs) + { + var PortalID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = dataProvider.GetFolderPermissionsByPortal(PortalID); + var dic = new Dictionary(); + try + { + while (dr.Read()) + { + //fill business object + var folderPermissionInfo = CBO.FillObject(dr, false); + string dictionaryKey = folderPermissionInfo.FolderPath; + if (string.IsNullOrEmpty(dictionaryKey)) + { + dictionaryKey = "[PortalRoot]"; + } + + //add Folder Permission to dictionary + if (dic.ContainsKey(dictionaryKey)) + { + //Add FolderPermission to FolderPermission Collection already in dictionary for FolderPath + dic[dictionaryKey].Add(folderPermissionInfo); + } + else + { + //Create new FolderPermission Collection for TabId + var collection = new FolderPermissionCollection {folderPermissionInfo}; + + //Add Permission to Collection + + //Add Collection to Dictionary + dic.Add(dictionaryKey, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return dic; + } + + private Dictionary GetFolderPermissions(int PortalID) + { + string cacheKey = string.Format(DataCache.FolderPermissionCacheKey, PortalID); + return + CBO.GetCachedObject>( + new CacheItemArgs(cacheKey, DataCache.FolderPermissionCacheTimeOut, DataCache.FolderPermissionCachePriority, PortalID), GetFolderPermissionsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModulePermissions gets a Dictionary of ModulePermissionCollections by + /// Module. + /// + /// The ID of the tab + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + private Dictionary GetModulePermissions(int tabID) + { + string cacheKey = string.Format(DataCache.ModulePermissionCacheKey, tabID); + return CBO.GetCachedObject>( + new CacheItemArgs(cacheKey, DataCache.ModulePermissionCacheTimeOut, DataCache.ModulePermissionCachePriority, tabID), GetModulePermissionsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModulePermissionsCallBack gets a Dictionary of ModulePermissionCollections by + /// Module from the the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + private object GetModulePermissionsCallBack(CacheItemArgs cacheItemArgs) + { + var tabID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = dataProvider.GetModulePermissionsByTabID(tabID); + var dic = new Dictionary(); + try + { + while (dr.Read()) + { + //fill business object + var modulePermissionInfo = CBO.FillObject(dr, false); + + //add Module Permission to dictionary + if (dic.ContainsKey(modulePermissionInfo.ModuleID)) + { + dic[modulePermissionInfo.ModuleID].Add(modulePermissionInfo); + } + else + { + //Create new ModulePermission Collection for ModuleId + var collection = new ModulePermissionCollection {modulePermissionInfo}; + + //Add Permission to Collection + + //Add Collection to Dictionary + dic.Add(modulePermissionInfo.ModuleID, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetTabPermissions gets a Dictionary of TabPermissionCollections by + /// Tab. + /// + /// The ID of the portal + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + private Dictionary GetTabPermissions(int portalID) + { + string cacheKey = string.Format(DataCache.TabPermissionCacheKey, portalID); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.TabPermissionCacheTimeOut, DataCache.TabPermissionCachePriority, portalID), + GetTabPermissionsCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetTabPermissionsCallBack gets a Dictionary of TabPermissionCollections by + /// Tab from the the Database. + /// + /// The CacheItemArgs object that contains the parameters + /// needed for the database call + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + private object GetTabPermissionsCallBack(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + IDataReader dr = dataProvider.GetTabPermissionsByPortal(portalID); + var dic = new Dictionary(); + try + { + while (dr.Read()) + { + //fill business object + var tabPermissionInfo = CBO.FillObject(dr, false); + + //add Tab Permission to dictionary + if (dic.ContainsKey(tabPermissionInfo.TabID)) + { + //Add TabPermission to TabPermission Collection already in dictionary for TabId + dic[tabPermissionInfo.TabID].Add(tabPermissionInfo); + } + else + { + //Create new TabPermission Collection for TabId + var collection = new TabPermissionCollection {tabPermissionInfo}; + + //Add Collection to Dictionary + dic.Add(tabPermissionInfo.TabID, collection); + } + } + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return dic; + } + + #endregion + + #region Public Methods + + #region FolderPermission Methods + + public virtual bool CanAdminFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(AdminFolderPermissionCode)); + } + + public virtual bool CanAddFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(AddFolderPermissionCode)); + } + + public virtual bool CanCopyFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(CopyFolderPermissionCode)); + } + + public virtual bool CanDeleteFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(DeleteFolderPermissionCode)); + } + + public virtual bool CanManageFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(ManageFolderPermissionCode)); + } + + public virtual bool CanViewFolder(FolderInfo folder) + { + if (folder == null) return false; + return PortalSecurity.IsInRoles(folder.FolderPermissions.ToString(ViewFolderPermissionCode)); + } + + public virtual void DeleteFolderPermissionsByUser(UserInfo objUser) + { + dataProvider.DeleteFolderPermissionsByUserID(objUser.PortalID, objUser.UserID); + } + + public virtual FolderPermissionCollection GetFolderPermissionsCollectionByFolder(int PortalID, string Folder) + { + string dictionaryKey = Folder; + if (string.IsNullOrEmpty(dictionaryKey)) + { + dictionaryKey = "[PortalRoot]"; + } + //Get the Portal FolderPermission Dictionary + Dictionary dicFolderPermissions = GetFolderPermissions(PortalID); + + //Get the Collection from the Dictionary + FolderPermissionCollection folderPermissions; + bool bFound = dicFolderPermissions.TryGetValue(dictionaryKey, out folderPermissions); + if (!bFound) + { + //Return empty collection + folderPermissions = new FolderPermissionCollection(); + } + return folderPermissions; + } + + public virtual bool HasFolderPermission(FolderPermissionCollection objFolderPermissions, string PermissionKey) + { + return PortalSecurity.IsInRoles(objFolderPermissions.ToString(PermissionKey)); + } + + /// + /// SaveFolderPermissions updates a Folder's permissions + /// + /// The Folder to update + public virtual void SaveFolderPermissions(FolderInfo folder) + { + SaveFolderPermissions((IFolderInfo)folder); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveFolderPermissions updates a Folder's permissions + /// + /// The Folder to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void SaveFolderPermissions(IFolderInfo folder) + { + if ((folder.FolderPermissions != null)) + { + FolderPermissionCollection folderPermissions = GetFolderPermissionsCollectionByFolder(folder.PortalID, folder.FolderPath); + + //Ensure that if role/user has been given a permission that is not Read/Browse then they also need Read/Browse + var permController = new PermissionController(); + ArrayList permArray = permController.GetPermissionByCodeAndKey("SYSTEM_FOLDER", "READ"); + PermissionInfo readPerm = null; + if (permArray.Count == 1) + { + readPerm = permArray[0] as PermissionInfo; + } + + PermissionInfo browsePerm = null; + permArray = permController.GetPermissionByCodeAndKey("SYSTEM_FOLDER", "BROWSE"); + if (permArray.Count == 1) + { + browsePerm = permArray[0] as PermissionInfo; + } + + var additionalPermissions = new FolderPermissionCollection(); + foreach (FolderPermissionInfo folderPermission in folder.FolderPermissions) + { + if (folderPermission.PermissionKey != "BROWSE" && folderPermission.PermissionKey != "READ") + { + //Try to add Read permission + var newFolderPerm = new FolderPermissionInfo(readPerm) + { + FolderID = folderPermission.FolderID, + RoleID = folderPermission.RoleID, + UserID = folderPermission.UserID, + AllowAccess = folderPermission.AllowAccess + }; + + additionalPermissions.Add(newFolderPerm); + + //Try to add Browse permission + newFolderPerm = new FolderPermissionInfo(browsePerm) + { + FolderID = folderPermission.FolderID, + RoleID = folderPermission.RoleID, + UserID = folderPermission.UserID, + AllowAccess = folderPermission.AllowAccess + }; + + additionalPermissions.Add(newFolderPerm); + } + } + + foreach (FolderPermissionInfo folderPermission in additionalPermissions) + { + folder.FolderPermissions.Add(folderPermission, true); + } + + if (!folderPermissions.CompareTo(folder.FolderPermissions)) + { + dataProvider.DeleteFolderPermissionsByFolderPath(folder.PortalID, folder.FolderPath); + + foreach (FolderPermissionInfo folderPermission in folder.FolderPermissions) + { + dataProvider.AddFolderPermission(folder.FolderID, + folderPermission.PermissionID, + folderPermission.RoleID, + folderPermission.AllowAccess, + folderPermission.UserID, + UserController.GetCurrentUserInfo().UserID); + } + } + } + } + + #endregion + + #region ModulePermission Methods + + public virtual bool CanAdminModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(AdminModulePermissionCode)); + } + + public virtual bool CanDeleteModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(DeleteModulePermissionCode)); + } + + public virtual bool CanEditModuleContent(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(ContentModulePermissionCode)); + } + + public virtual bool CanExportModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(ExportModulePermissionCode)); + } + + public virtual bool CanImportModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(ImportModulePermissionCode)); + } + + public virtual bool CanManageModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(ManageModulePermissionCode)); + } + + public virtual bool CanViewModule(ModuleInfo module) + { + return PortalSecurity.IsInRoles(module.ModulePermissions.ToString(ViewModulePermissionCode)); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteModulePermissionsByUser deletes a user's Module Permission in the Database + /// + /// The user + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void DeleteModulePermissionsByUser(UserInfo user) + { + dataProvider.DeleteModulePermissionsByUserID(user.PortalID, user.UserID); + DataCache.ClearModulePermissionsCachesByPortal(user.PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModulePermissions gets a ModulePermissionCollection + /// + /// The ID of the module + /// The ID of the tab + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual ModulePermissionCollection GetModulePermissions(int moduleID, int tabID) + { + //Get the Tab ModulePermission Dictionary + Dictionary dictionary = GetModulePermissions(tabID); + + //Get the Collection from the Dictionary + ModulePermissionCollection modulePermissions; + bool found = dictionary.TryGetValue(moduleID, out modulePermissions); + if (!found) + { + //Return empty collection + modulePermissions = new ModulePermissionCollection(); + } + return modulePermissions; + } + + /// ----------------------------------------------------------------------------- + /// + /// HasModulePermission checks whether the current user has a specific Module Permission + /// + /// The Permissions for the Module + /// The Permission to check + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual bool HasModulePermission(ModulePermissionCollection modulePermissions, string permissionKey) + { + return PortalSecurity.IsInRoles(modulePermissions.ToString(permissionKey)); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveModulePermissions updates a Module's permissions + /// + /// The Module to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void SaveModulePermissions(ModuleInfo module) + { + if (module.ModulePermissions != null) + { + ModulePermissionCollection modulePermissions = ModulePermissionController.GetModulePermissions(module.ModuleID, module.TabID); + if (!modulePermissions.CompareTo(module.ModulePermissions)) + { + dataProvider.DeleteModulePermissionsByModuleID(module.ModuleID, module.PortalID); + + foreach (ModulePermissionInfo modulePermission in module.ModulePermissions) + { + if (!module.IsShared && module.InheritViewPermissions && modulePermission.PermissionKey == "VIEW") + { + dataProvider.DeleteModulePermission(modulePermission.ModulePermissionID); + } + else + { + dataProvider.AddModulePermission(module.ModuleID, + module.PortalID, + modulePermission.PermissionID, + modulePermission.RoleID, + modulePermission.AllowAccess, + modulePermission.UserID, + UserController.GetCurrentUserInfo().UserID); + } + } + } + } + } + + #endregion + + #region TabPermission Methods + + public virtual bool CanAddContentToPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(ContentPagePermissionCode)); + } + + public virtual bool CanAddPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(AddPagePermissionCode)); + } + + public virtual bool CanAdminPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(AdminPagePermissionCode)); + } + + public virtual bool CanCopyPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(CopyPagePermissionCode)); + } + + public virtual bool CanDeletePage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(DeletePagePermissionCode)); + } + + public virtual bool CanExportPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(ExportPagePermissionCode)); + } + + public virtual bool CanImportPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(ImportPagePermissionCode)); + } + + public virtual bool CanManagePage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(ManagePagePermissionCode)); + } + + public virtual bool CanNavigateToPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(NavigatePagePermissionCode)); + } + + public virtual bool CanViewPage(TabInfo tab) + { + return PortalSecurity.IsInRoles(tab.TabPermissions.ToString(ViewPagePermissionCode)); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteTabPermissionsByUser deletes a user's Tab Permissions in the Database + /// + /// The user + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void DeleteTabPermissionsByUser(UserInfo user) + { + dataProvider.DeleteTabPermissionsByUserID(user.PortalID, user.UserID); + DataCache.ClearTabPermissionsCache(user.PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetTabPermissions gets a TabPermissionCollection + /// + /// The ID of the tab + /// The ID of the portal + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual TabPermissionCollection GetTabPermissions(int tabID, int portalID) + { + //Get the Portal TabPermission Dictionary + Dictionary dicTabPermissions = GetTabPermissions(portalID); + + //Get the Collection from the Dictionary + TabPermissionCollection tabPermissions; + bool bFound = dicTabPermissions.TryGetValue(tabID, out tabPermissions); + if (!bFound) + { + //Return empty collection + tabPermissions = new TabPermissionCollection(); + } + return tabPermissions; + } + + /// ----------------------------------------------------------------------------- + /// + /// HasTabPermission checks whether the current user has a specific Tab Permission + /// + /// The Permissions for the Tab + /// The Permission to check + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual bool HasTabPermission(TabPermissionCollection tabPermissions, string permissionKey) + { + return PortalSecurity.IsInRoles(tabPermissions.ToString(permissionKey)); + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveTabPermissions saves a Tab's permissions + /// + /// The Tab to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void SaveTabPermissions(TabInfo tab) + { + TabPermissionCollection objCurrentTabPermissions = GetTabPermissions(tab.TabID, tab.PortalID); + var objEventLog = new EventLogController(); + if (!objCurrentTabPermissions.CompareTo(tab.TabPermissions)) + { + dataProvider.DeleteTabPermissionsByTabID(tab.TabID); + objEventLog.AddLog(tab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.TABPERMISSION_DELETED); + if (tab.TabPermissions != null) + { + foreach (TabPermissionInfo objTabPermission in tab.TabPermissions) + { + dataProvider.AddTabPermission(tab.TabID, + objTabPermission.PermissionID, + objTabPermission.RoleID, + objTabPermission.AllowAccess, + objTabPermission.UserID, + UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(tab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.TABPERMISSION_CREATED); + } + } + } + } + + #endregion + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/TabPermissionCollection.cs b/DNN Platform/Library/Security/Permissions/TabPermissionCollection.cs new file mode 100644 index 00000000000..0df08e2f70c --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/TabPermissionCollection.cs @@ -0,0 +1,216 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : TabPermissionCollection + /// ----------------------------------------------------------------------------- + /// + /// TabPermissionCollection provides the a custom collection for TabPermissionInfo + /// objects + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + [XmlRoot("tabpermissions")] + public class TabPermissionCollection : CollectionBase + { + public TabPermissionCollection() + { + } + + public TabPermissionCollection(ArrayList tabPermissions) + { + AddRange(tabPermissions); + } + + public TabPermissionCollection(TabPermissionCollection tabPermissions) + { + AddRange(tabPermissions); + } + + public TabPermissionCollection(ArrayList tabPermissions, int TabId) + { + foreach (TabPermissionInfo permission in tabPermissions) + { + if (permission.TabID == TabId) + { + Add(permission); + } + } + } + + public TabPermissionInfo this[int index] + { + get + { + return (TabPermissionInfo) List[index]; + } + set + { + List[index] = value; + } + } + + public int Add(TabPermissionInfo value) + { + return List.Add(value); + } + + public int Add(TabPermissionInfo value, bool checkForDuplicates) + { + int id = Null.NullInteger; + + if (!checkForDuplicates) + { + id = Add(value); + } + else + { + bool isMatch = false; + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == value.PermissionID && permission.UserID == value.UserID && permission.RoleID == value.RoleID) + { + isMatch = true; + break; + } + } + if (!isMatch) + { + id = Add(value); + } + } + + return id; + } + + public void AddRange(ArrayList tabPermissions) + { + foreach (TabPermissionInfo permission in tabPermissions) + { + Add(permission); + } + } + + public void AddRange(IEnumerable tabPermissions) + { + foreach (TabPermissionInfo permission in tabPermissions) + { + Add(permission); + } + } + + public void AddRange(TabPermissionCollection tabPermissions) + { + foreach (TabPermissionInfo permission in tabPermissions) + { + Add(permission); + } + } + + public bool CompareTo(TabPermissionCollection objTabPermissionCollection) + { + if (objTabPermissionCollection.Count != Count) + { + return false; + } + InnerList.Sort(new CompareTabPermissions()); + objTabPermissionCollection.InnerList.Sort(new CompareTabPermissions()); + for (int i = 0; i <= Count - 1; i++) + { + if (objTabPermissionCollection[i].TabPermissionID != this[i].TabPermissionID || objTabPermissionCollection[i].AllowAccess != this[i].AllowAccess) + { + return false; + } + } + return true; + } + + public bool Contains(TabPermissionInfo value) + { + return List.Contains(value); + } + + public int IndexOf(TabPermissionInfo value) + { + return List.IndexOf(value); + } + + public void Insert(int index, TabPermissionInfo value) + { + List.Insert(index, value); + } + + public void Remove(TabPermissionInfo value) + { + List.Remove(value); + } + + public void Remove(int permissionID, int roleID, int userID) + { + foreach (PermissionInfoBase permission in List) + { + if (permission.PermissionID == permissionID && permission.UserID == userID && permission.RoleID == roleID) + { + List.Remove(permission); + break; + } + } + } + + public List ToList() + { + var list = new List(); + foreach (PermissionInfoBase permission in List) + { + list.Add(permission); + } + return list; + } + + public string ToString(string key) + { + return PermissionController.BuildPermissions(List, key); + } + + public IEnumerable Where(Func predicate) + { + return this.Cast().Where(predicate); + } + } +} diff --git a/DNN Platform/Library/Security/Permissions/TabPermissionController.cs b/DNN Platform/Library/Security/Permissions/TabPermissionController.cs new file mode 100644 index 00000000000..c56ce7ee804 --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/TabPermissionController.cs @@ -0,0 +1,374 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : TabPermissionController + /// ----------------------------------------------------------------------------- + /// + /// TabPermissionController provides the Business Layer for Tab Permissions + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public class TabPermissionController + { + #region "Private Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// ClearPermissionCache clears the Tab Permission Cache + /// + /// The ID of the Tab + /// + /// [cnurse] 01/15/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private static void ClearPermissionCache(int tabId) + { + TabController objTabs = new TabController(); + TabInfo objTab = objTabs.GetTab(tabId, Null.NullInteger, false); + DataCache.ClearTabPermissionsCache(objTab.PortalID); + } + + #endregion + + #region Private Members + + private static readonly PermissionProvider provider = PermissionProvider.Instance(); + + #endregion + + #region Public Shared Methods + + public static bool CanAddContentToPage() + { + return CanAddContentToPage(TabController.CurrentPage); + } + + public static bool CanAddContentToPage(TabInfo objTab) + { + return provider.CanAddContentToPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanAddPage() + { + return CanAddPage(TabController.CurrentPage); + } + + public static bool CanAddPage(TabInfo objTab) + { + return provider.CanAddPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanAdminPage() + { + return CanAdminPage(TabController.CurrentPage); + } + + public static bool CanAdminPage(TabInfo objTab) + { + return provider.CanAdminPage(objTab); + } + + public static bool CanCopyPage() + { + return CanCopyPage(TabController.CurrentPage); + } + + public static bool CanCopyPage(TabInfo objTab) + { + return provider.CanCopyPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanDeletePage() + { + return CanDeletePage(TabController.CurrentPage); + } + + public static bool CanDeletePage(TabInfo objTab) + { + return provider.CanDeletePage(objTab) || CanAdminPage(objTab); + } + + public static bool CanExportPage() + { + return CanExportPage(TabController.CurrentPage); + } + + public static bool CanExportPage(TabInfo objTab) + { + return provider.CanExportPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanImportPage() + { + return CanImportPage(TabController.CurrentPage); + } + + public static bool CanImportPage(TabInfo objTab) + { + return provider.CanImportPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanManagePage() + { + return CanManagePage(TabController.CurrentPage); + } + + public static bool CanManagePage(TabInfo objTab) + { + return provider.CanManagePage(objTab) || CanAdminPage(objTab); + } + + public static bool CanNavigateToPage() + { + return CanNavigateToPage(TabController.CurrentPage); + } + + public static bool CanNavigateToPage(TabInfo objTab) + { + return provider.CanNavigateToPage(objTab) || CanAdminPage(objTab); + } + + public static bool CanViewPage() + { + return CanViewPage(TabController.CurrentPage); + } + + public static bool CanViewPage(TabInfo objTab) + { + return provider.CanViewPage(objTab) || CanAdminPage(objTab); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteTabPermissionsByUser deletes a user's Tab Permissions in the Database + /// + /// The user + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteTabPermissionsByUser(UserInfo objUser) + { + provider.DeleteTabPermissionsByUser(objUser); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objUser, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.TABPERMISSION_DELETED); + DataCache.ClearTabPermissionsCache(objUser.PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetTabPermissions gets a TabPermissionCollection + /// + /// The ID of the tab + /// The ID of the portal + /// + /// [cnurse] 01/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static TabPermissionCollection GetTabPermissions(int tabID, int portalID) + { + return provider.GetTabPermissions(tabID, portalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// HasTabPermission checks whether the current user has a specific Tab Permission + /// + /// If you pass in a comma delimited list of permissions (eg "ADD,DELETE", this will return + /// true if the user has any one of the permissions. + /// The Permission to check + /// + /// [cnurse] 01/15/2008 Documented + /// [cnurse] 04/22/2009 Added multi-permisison support + /// + /// ----------------------------------------------------------------------------- + public static bool HasTabPermission(string permissionKey) + { + return HasTabPermission(PortalController.GetCurrentPortalSettings().ActiveTab.TabPermissions, permissionKey); + } + + /// ----------------------------------------------------------------------------- + /// + /// HasTabPermission checks whether the current user has a specific Tab Permission + /// + /// If you pass in a comma delimited list of permissions (eg "ADD,DELETE", this will return + /// true if the user has any one of the permissions. + /// The Permissions for the Tab + /// The Permission(s) to check + /// + /// [cnurse] 01/15/2008 Documented + /// [cnurse] 04/22/2009 Added multi-permisison support + /// + /// ----------------------------------------------------------------------------- + public static bool HasTabPermission(TabPermissionCollection objTabPermissions, string permissionKey) + { + bool hasPermission = provider.HasTabPermission(objTabPermissions, "EDIT"); + if (!hasPermission) + { + if (permissionKey.Contains(",")) + { + foreach (string permission in permissionKey.Split(',')) + { + if (provider.HasTabPermission(objTabPermissions, permission)) + { + hasPermission = true; + break; + } + } + } + else + { + hasPermission = provider.HasTabPermission(objTabPermissions, permissionKey); + } + } + return hasPermission; + } + + /// ----------------------------------------------------------------------------- + /// + /// SaveTabPermissions saves a Tab's permissions + /// + /// The Tab to update + /// + /// [cnurse] 04/15/2009 Created + /// + /// ----------------------------------------------------------------------------- + public static void SaveTabPermissions(TabInfo tabInfo) + { + provider.SaveTabPermissions(tabInfo); + new EventLogController().AddLog(tabInfo, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.TABPERMISSION_UPDATED); + DataCache.ClearTabPermissionsCache(tabInfo.PortalID); + } + + #endregion + + #region "Obsolete Methods" + + [Obsolete("Deprecated in DNN 5.1.")] + public int AddTabPermission(TabPermissionInfo objTabPermission) + { + int id = Convert.ToInt32(DataProvider.Instance().AddTabPermission(objTabPermission.TabID, objTabPermission.PermissionID, objTabPermission.RoleID, objTabPermission.AllowAccess, objTabPermission.UserID, UserController.GetCurrentUserInfo().UserID)); + ClearPermissionCache(objTabPermission.TabID); + return id; + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteTabPermission(int tabPermissionID) + { + DataProvider.Instance().DeleteTabPermission(tabPermissionID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void DeleteTabPermissionsByTabID(int tabID) + { + DataProvider.Instance().DeleteTabPermissionsByTabID(tabID); + ClearPermissionCache(tabID); + } + + [Obsolete("Deprecated in DNN 5.0. Use DeleteTabPermissionsByUser(UserInfo) ")] + public void DeleteTabPermissionsByUserID(UserInfo objUser) + { + DataProvider.Instance().DeleteTabPermissionsByUserID(objUser.PortalID, objUser.UserID); + DataCache.ClearTabPermissionsCache(objUser.PortalID); + } + + [Obsolete("Deprecated in DNN 5.0. Please use TabPermissionCollection.ToString(String)")] + public string GetTabPermissions(TabPermissionCollection tabPermissions, string permissionKey) + { + return tabPermissions.ToString(permissionKey); + } + + [Obsolete("Deprecated in DNN 5.0. This should have been declared as Friend as it was never meant to be used outside of the core.")] + public ArrayList GetTabPermissionsByPortal(int PortalID) + { + return CBO.FillCollection(DataProvider.Instance().GetTabPermissionsByPortal(PortalID), typeof(TabPermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetTabPermissions(TabId, PortalId)")] + public ArrayList GetTabPermissionsByTabID(int TabID) + { + return CBO.FillCollection(DataProvider.Instance().GetTabPermissionsByTabID(TabID, -1), typeof(TabPermissionInfo)); + } + + [Obsolete("Deprecated in DNN 5.0. Please use TabPermissionCollection.ToString(String)")] + public string GetTabPermissionsByTabID(ArrayList arrTabPermissions, int TabID, string PermissionKey) + { + //Create a Tab Permission Collection from the ArrayList + TabPermissionCollection tabPermissions = new TabPermissionCollection(arrTabPermissions, TabID); + + //Return the permission string for permissions with specified TabId + return tabPermissions.ToString(PermissionKey); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetTabPermissions(TabId, PortalId)")] + public TabPermissionCollection GetTabPermissionsByTabID(ArrayList arrTabPermissions, int TabID) + { + return new TabPermissionCollection(arrTabPermissions, TabID); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetTabPermissions(TabId, PortalId)")] + public Security.Permissions.TabPermissionCollection GetTabPermissionsCollectionByTabID(int TabID) + { + return new TabPermissionCollection(CBO.FillCollection(DataProvider.Instance().GetTabPermissionsByTabID(TabID, -1), typeof(TabPermissionInfo))); + } + + [Obsolete("Deprecated in DNN 5.0. Please use GetTabPermissions(TabId, PortalId)")] + public TabPermissionCollection GetTabPermissionsCollectionByTabID(ArrayList arrTabPermissions, int TabID) + { + return new TabPermissionCollection(arrTabPermissions, TabID); + } + + [Obsolete("Deprecated in DNN 5.1. Please use GetTabPermissions(TabId, PortalId)")] + public TabPermissionCollection GetTabPermissionsCollectionByTabID(int tabID, int portalID) + { + return GetTabPermissions(tabID, portalID); + } + + [Obsolete("Deprecated in DNN 5.1.")] + public void UpdateTabPermission(TabPermissionInfo objTabPermission) + { + DataProvider.Instance().UpdateTabPermission(objTabPermission.TabPermissionID, objTabPermission.TabID, objTabPermission.PermissionID, objTabPermission.RoleID, objTabPermission.AllowAccess, objTabPermission.UserID, UserController.GetCurrentUserInfo().UserID); + ClearPermissionCache(objTabPermission.TabID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Permissions/TabPermissionInfo.cs b/DNN Platform/Library/Security/Permissions/TabPermissionInfo.cs new file mode 100644 index 00000000000..50dbba0e3af --- /dev/null +++ b/DNN Platform/Library/Security/Permissions/TabPermissionInfo.cs @@ -0,0 +1,185 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Security.Permissions +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.Security.Permissions + /// Class : TabPermissionInfo + /// ----------------------------------------------------------------------------- + /// + /// TabPermissionInfo provides the Entity Layer for Tab Permissions + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [Serializable] + [XmlRoot("permission")] + public class TabPermissionInfo : PermissionInfoBase, IHydratable + { + #region "Private Members" + + private int _TabID; + //local property declarations + private int _TabPermissionID; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new TabPermissionInfo + /// + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public TabPermissionInfo() + { + _TabPermissionID = Null.NullInteger; + _TabID = Null.NullInteger; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new TabPermissionInfo + /// + /// A PermissionInfo object + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public TabPermissionInfo(PermissionInfo permission) : this() + { + ModuleDefID = permission.ModuleDefID; + PermissionCode = permission.PermissionCode; + PermissionID = permission.PermissionID; + PermissionKey = permission.PermissionKey; + PermissionName = permission.PermissionName; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Tab Permission ID + /// + /// An Integer + /// + /// [cnurse] 01/15/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("tabpermissionid")] + public int TabPermissionID + { + get + { + return _TabPermissionID; + } + set + { + _TabPermissionID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Tab ID + /// + /// An Integer + /// + /// [cnurse] 01/15/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlElement("tabid")] + public int TabID + { + get + { + return _TabID; + } + set + { + _TabID = value; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a TabPermissionInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + //Call the base classes fill method to ppoulate base class proeprties + base.FillInternal(dr); + TabPermissionID = Null.SetNullInteger(dr["TabPermissionID"]); + TabID = Null.SetNullInteger(dr["TabID"]); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 01/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int KeyID + { + get + { + return TabPermissionID; + } + set + { + TabPermissionID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/PortalSecurity.cs b/DNN Platform/Library/Security/PortalSecurity.cs new file mode 100644 index 00000000000..f6a1ab2bd54 --- /dev/null +++ b/DNN Platform/Library/Security/PortalSecurity.cs @@ -0,0 +1,947 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.Security; + +using DotNetNuke.Common; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Membership; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Security +{ + public class PortalSecurity + { + #region FilterFlag enum + + ///----------------------------------------------------------------------------- + /// + /// The FilterFlag enum determines which filters are applied by the InputFilter + /// function. The Flags attribute allows the user to include multiple + /// enumerated values in a single variable by OR'ing the individual values + /// together. + /// + ///----------------------------------------------------------------------------- + [Flags] + public enum FilterFlag + { + MultiLine = 1, + NoMarkup = 2, + NoScripting = 4, + NoSQL = 8, + NoAngleBrackets = 16, + NoProfanity =32 + } + + /// + /// Determines the configuration source for the remove and replace functions + /// + public enum ConfigType + { + ListController, + ExternalFile + } + + /// + /// determines whether to use system (host) list, portal specific list, or combine both + /// At present only supported by ConfigType.ListController + /// + public enum FilterScope + { + SystemList, + PortalList, + SystemAndPortalList + } + + #endregion + + #region Private Methods + + private string BytesToHexString(byte[] bytes) + { + var hexString = new StringBuilder(64); + int counter; + for (counter = 0; counter <= bytes.Length - 1; counter++) + { + hexString.Append(String.Format("{0:X2}", bytes[counter])); + } + return hexString.ToString(); + } + + ///----------------------------------------------------------------------------- + /// + /// This function uses Regex search strings to remove HTML tags which are + /// targeted in Cross-site scripting (XSS) attacks. This function will evolve + /// to provide more robust checking as additional holes are found. + /// + /// This is the string to be filtered + /// Filtered UserInput + /// + /// This is a private function that is used internally by the FormatDisableScripting function + /// + /// + /// [cathal] 3/06/2007 Created + /// + ///----------------------------------------------------------------------------- + private string FilterStrings(string strInput) + { + //setup up list of search terms as items may be used twice + string TempInput = strInput; + var listStrings = new List + { + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>.*?<]*>", + "]*>", + "<]*>", + "onerror", + "onmouseover", + "javascript:", + "vbscript:", + "unescape", + "alert[\\s( )]*\\([\\s( )]*'?[\\s( )]*[\"(")]?" + }; + + const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Singleline; + const string replacement = " "; + + //check if text contains encoded angle brackets, if it does it we decode it to check the plain text + if (TempInput.Contains(">") && TempInput.Contains("<")) + { + //text is encoded, so decode and try again + TempInput = HttpContext.Current.Server.HtmlDecode(TempInput); + TempInput = listStrings.Aggregate(TempInput, (current, s) => Regex.Replace(current, s, replacement, options)); + + //Re-encode + TempInput = HttpContext.Current.Server.HtmlEncode(TempInput); + } + else + { + TempInput = listStrings.Aggregate(TempInput, (current, s) => Regex.Replace(current, s, replacement, options)); + } + return TempInput; + } + + ///----------------------------------------------------------------------------- + /// + /// This function uses Regex search strings to remove HTML tags which are + /// targeted in Cross-site scripting (XSS) attacks. This function will evolve + /// to provide more robust checking as additional holes are found. + /// + /// This is the string to be filtered + /// Filtered UserInput + /// + /// This is a private function that is used internally by the InputFilter function + /// + ///----------------------------------------------------------------------------- + private string FormatDisableScripting(string strInput) + { + string TempInput = strInput; + TempInput = FilterStrings(TempInput); + return TempInput; + } + + ///----------------------------------------------------------------------------- + /// + /// This filter removes angle brackets i.e. + /// + /// This is the string to be filtered + /// Filtered UserInput + /// + /// This is a private function that is used internally by the InputFilter function + /// + /// + /// [Cathal] 6/1/2006 Created to fufill client request + /// + ///----------------------------------------------------------------------------- + private string FormatAngleBrackets(string strInput) + { + string TempInput = strInput.Replace("<", ""); + TempInput = TempInput.Replace(">", ""); + return TempInput; + } + + ///----------------------------------------------------------------------------- + /// + /// This filter removes CrLf characters and inserts br + /// + /// This is the string to be filtered + /// Filtered UserInput + /// + /// This is a private function that is used internally by the InputFilter function + /// + ///----------------------------------------------------------------------------- + private string FormatMultiLine(string strInput) + { + string tempInput = strInput.Replace(Environment.NewLine, "
    ").Replace("\r\n", "
    ").Replace("\n", "
    ").Replace("\r", "
    "); + return (tempInput); + } + + ///----------------------------------------------------------------------------- + /// + /// This function verifies raw SQL statements to prevent SQL injection attacks + /// and replaces a similar function (PreventSQLInjection) from the Common.Globals.vb module + /// + /// This is the string to be filtered + /// Filtered UserInput + /// + /// This is a private function that is used internally by the InputFilter function + /// + ///----------------------------------------------------------------------------- + private string FormatRemoveSQL(string strSQL) + { + const string BadStatementExpression = ";|--|create|drop|select|insert|delete|update|union|sp_|xp_|exec|/\\*.*\\*/|declare|waitfor|%|&"; + return Regex.Replace(strSQL, BadStatementExpression, " ", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace("'", "''"); + } + + ///----------------------------------------------------------------------------- + /// + /// This function determines if the Input string contains any markup. + /// + /// This is the string to be checked + /// True if string contains Markup tag(s) + /// + /// This is a private function that is used internally by the InputFilter function + /// + ///----------------------------------------------------------------------------- + private bool IncludesMarkup(string strInput) + { + const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Singleline; + const string pattern = "<[^<>]*>"; + return Regex.IsMatch(strInput, pattern, options); + } + + #endregion + + #region Public Methods + + ///----------------------------------------------------------------------------- + /// + /// This function creates a random key + /// + /// This is the number of bytes for the key + /// A random string + /// + /// This is a public function used for generating SHA1 keys + /// + /// + /// + ///----------------------------------------------------------------------------- + public string CreateKey(int numBytes) + { + var rng = new RNGCryptoServiceProvider(); + var buff = new byte[numBytes]; + rng.GetBytes(buff); + return BytesToHexString(buff); + } + + public string Decrypt(string strKey, string strData) + { + if (String.IsNullOrEmpty(strData)) + { + return ""; + } + string strValue = ""; + if (!String.IsNullOrEmpty(strKey)) + { + //convert key to 16 characters for simplicity + if (strKey.Length < 16) + { + strKey = strKey + "XXXXXXXXXXXXXXXX".Substring(0, 16 - strKey.Length); + } + else + { + strKey = strKey.Substring(0, 16); + } + + //create encryption keys + byte[] byteKey = Encoding.UTF8.GetBytes(strKey.Substring(0, 8)); + byte[] byteVector = Encoding.UTF8.GetBytes(strKey.Substring(strKey.Length - 8, 8)); + + //convert data to byte array and Base64 decode + var byteData = new byte[strData.Length]; + try + { + byteData = Convert.FromBase64String(strData); + } + catch //invalid length + { + strValue = strData; + } + if (String.IsNullOrEmpty(strValue)) + { + try + { + //decrypt + var objDES = new DESCryptoServiceProvider(); + var objMemoryStream = new MemoryStream(); + var objCryptoStream = new CryptoStream(objMemoryStream, objDES.CreateDecryptor(byteKey, byteVector), CryptoStreamMode.Write); + objCryptoStream.Write(byteData, 0, byteData.Length); + objCryptoStream.FlushFinalBlock(); + + //convert to string + Encoding objEncoding = Encoding.UTF8; + strValue = objEncoding.GetString(objMemoryStream.ToArray()); + } + catch //decryption error + { + strValue = ""; + } + } + } + else + { + strValue = strData; + } + return strValue; + } + + public string DecryptString(string message, string passphrase) + { + byte[] results; + var utf8 = new UTF8Encoding(); + + //hash the passphrase using MD5 to create 128bit byte array + var hashProvider = new MD5CryptoServiceProvider(); + byte[] tdesKey = hashProvider.ComputeHash(utf8.GetBytes(passphrase)); + + var tdesAlgorithm = new TripleDESCryptoServiceProvider {Key = tdesKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7}; + + + byte[] dataToDecrypt = Convert.FromBase64String(message); + try + { + ICryptoTransform decryptor = tdesAlgorithm.CreateDecryptor(); + results = decryptor.TransformFinalBlock(dataToDecrypt, 0, dataToDecrypt.Length); + } + finally + { + // Clear the TripleDes and Hashprovider services of any sensitive information + tdesAlgorithm.Clear(); + hashProvider.Clear(); + } + + return utf8.GetString(results); + } + + public string Encrypt(string key, string data) + { + string value; + if (!String.IsNullOrEmpty(key)) + { + //convert key to 16 characters for simplicity + if (key.Length < 16) + { + key = key + "XXXXXXXXXXXXXXXX".Substring(0, 16 - key.Length); + } + else + { + key = key.Substring(0, 16); + } + + //create encryption keys + byte[] byteKey = Encoding.UTF8.GetBytes(key.Substring(0, 8)); + byte[] byteVector = Encoding.UTF8.GetBytes(key.Substring(key.Length - 8, 8)); + + //convert data to byte array + byte[] byteData = Encoding.UTF8.GetBytes(data); + + //encrypt + var objDES = new DESCryptoServiceProvider(); + var objMemoryStream = new MemoryStream(); + var objCryptoStream = new CryptoStream(objMemoryStream, objDES.CreateEncryptor(byteKey, byteVector), CryptoStreamMode.Write); + objCryptoStream.Write(byteData, 0, byteData.Length); + objCryptoStream.FlushFinalBlock(); + + //convert to string and Base64 encode + value = Convert.ToBase64String(objMemoryStream.ToArray()); + } + else + { + value = data; + } + return value; + } + + public string EncryptString(string message, string passphrase) + { + byte[] results; + var utf8 = new UTF8Encoding(); + + //hash the passphrase using MD5 to create 128bit byte array + var hashProvider = new MD5CryptoServiceProvider(); + byte[] tdesKey = hashProvider.ComputeHash(utf8.GetBytes(passphrase)); + + var tdesAlgorithm = new TripleDESCryptoServiceProvider {Key = tdesKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7}; + + + byte[] dataToEncrypt = utf8.GetBytes(message); + + try + { + ICryptoTransform encryptor = tdesAlgorithm.CreateEncryptor(); + results = encryptor.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length); + } + finally + { + // Clear the TripleDes and Hashprovider services of any sensitive information + tdesAlgorithm.Clear(); + hashProvider.Clear(); + } + + //Return the encrypted string as a base64 encoded string + return Convert.ToBase64String(results); + } + + ///----------------------------------------------------------------------------- + /// + /// This function applies security filtering to the UserInput string. + /// + /// This is the string to be filtered + /// Flags which designate the filters to be applied + /// Filtered UserInput + ///----------------------------------------------------------------------------- + public string InputFilter(string userInput, FilterFlag filterType) + { + if (userInput == null) + { + return ""; + } + var tempInput = userInput; + if ((filterType & FilterFlag.NoAngleBrackets) == FilterFlag.NoAngleBrackets) + { + var removeAngleBrackets = Config.GetSetting("RemoveAngleBrackets") != null && Boolean.Parse(Config.GetSetting("RemoveAngleBrackets")); + if (removeAngleBrackets) + { + tempInput = FormatAngleBrackets(tempInput); + } + } + if ((filterType & FilterFlag.NoSQL) == FilterFlag.NoSQL) + { + tempInput = FormatRemoveSQL(tempInput); + } + else + { + if ((filterType & FilterFlag.NoMarkup) == FilterFlag.NoMarkup && IncludesMarkup(tempInput)) + { + tempInput = HttpUtility.HtmlEncode(tempInput); + } + if ((filterType & FilterFlag.NoScripting) == FilterFlag.NoScripting) + { + tempInput = FormatDisableScripting(tempInput); + } + if ((filterType & FilterFlag.MultiLine) == FilterFlag.MultiLine) + { + tempInput = FormatMultiLine(tempInput); + } + } + if ((filterType & FilterFlag.NoProfanity) == FilterFlag.NoProfanity) + { + tempInput = Replace(tempInput, ConfigType.ListController, "ProfanityFilter", FilterScope.SystemAndPortalList); + } + return tempInput; + } + + ///----------------------------------------------------------------------------- + /// + /// Replaces profanity words with other words in the provided input string. + /// + /// + /// The correspondence between the words to search and the words to replace could be specified in two different places: + /// 1) In an external file. (NOT IMPLEMENTED) + /// 2) In System/Site lists. + /// The name of the System List is "ProfanityFilter". The name of the list in each portal is composed using the following rule: + /// "ProfanityFilter-" + PortalID. + /// + /// The string to search the words in. + /// The type of configuration. + /// The external file to search the words. Ignored when configType is ListController. + /// When using ListController configType, this parameter indicates which list(s) to use. + /// The original text with the profanity words replaced. + ///----------------------------------------------------------------------------- + public string Replace(string inputString, ConfigType configType, string configSource, FilterScope filterScope) + { + switch (configType) + { + case ConfigType.ListController: + const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Singleline; + const string listName = "ProfanityFilter"; + + var listController = new ListController(); + + PortalSettings settings; + + IEnumerable listEntryHostInfos; + IEnumerable listEntryPortalInfos; + + switch (filterScope) + { + case FilterScope.SystemList: + listEntryHostInfos = listController.GetListEntryInfoItems(listName, "", Null.NullInteger); + inputString = listEntryHostInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", removeItem.Value, options)); + break; + case FilterScope.SystemAndPortalList: + settings = PortalController.GetCurrentPortalSettings(); + listEntryHostInfos = listController.GetListEntryInfoItems(listName, "", Null.NullInteger); + listEntryPortalInfos = listController.GetListEntryInfoItems(listName + "-" + settings.PortalId, "", settings.PortalId); + inputString = listEntryHostInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", removeItem.Value, options)); + inputString = listEntryPortalInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", removeItem.Value, options)); + break; + case FilterScope.PortalList: + settings = PortalController.GetCurrentPortalSettings(); + listEntryPortalInfos = listController.GetListEntryInfoItems(listName + "-" + settings.PortalId, "", settings.PortalId); + inputString = listEntryPortalInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", removeItem.Value, options)); + break; + } + break; + case ConfigType.ExternalFile: + throw new NotImplementedException(); + default: + throw new ArgumentOutOfRangeException("configType"); + } + + return inputString; + } + + ///----------------------------------------------------------------------------- + /// + /// Removes profanity words in the provided input string. + /// + /// + /// The words to search could be defined in two different places: + /// 1) In an external file. (NOT IMPLEMENTED) + /// 2) In System/Site lists. + /// The name of the System List is "ProfanityFilter". The name of the list in each portal is composed using the following rule: + /// "ProfanityFilter-" + PortalID. + /// + /// The string to search the words in. + /// The type of configuration. + /// The external file to search the words. Ignored when configType is ListController. + /// When using ListController configType, this parameter indicates which list(s) to use. + /// The original text with the profanity words removed. + ///----------------------------------------------------------------------------- + public string Remove(string inputString, ConfigType configType, string configSource, FilterScope filterScope) + { + switch (configType) + { + case ConfigType.ListController: + const RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Singleline; + const string listName = "ProfanityFilter"; + + var listController = new ListController(); + + PortalSettings settings; + + IEnumerable listEntryHostInfos; + IEnumerable listEntryPortalInfos; + + switch (filterScope) + { + case FilterScope.SystemList: + listEntryHostInfos = listController.GetListEntryInfoItems(listName, "", Null.NullInteger); + inputString = listEntryHostInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", string.Empty, options)); + break; + case FilterScope.SystemAndPortalList: + settings = PortalController.GetCurrentPortalSettings(); + listEntryHostInfos = listController.GetListEntryInfoItems(listName, "", Null.NullInteger); + listEntryPortalInfos = listController.GetListEntryInfoItems(listName + "-" + settings.PortalId, "", settings.PortalId); + inputString = listEntryHostInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", string.Empty, options)); + inputString = listEntryPortalInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", string.Empty, options)); + break; + case FilterScope.PortalList: + settings = PortalController.GetCurrentPortalSettings(); + listEntryPortalInfos = listController.GetListEntryInfoItems(listName + "-" + settings.PortalId, "", settings.PortalId); + inputString = listEntryPortalInfos.Aggregate(inputString, (current, removeItem) => Regex.Replace(current, @"\b" + removeItem.Text + @"\b", string.Empty, options)); + break; + } + + break; + case ConfigType.ExternalFile: + throw new NotImplementedException(); + default: + throw new ArgumentOutOfRangeException("configType"); + } + + return inputString; + } + + public void SignIn(UserInfo user, bool createPersistentCookie) + { + if (PortalController.IsMemberOfPortalGroup(user.PortalID) || createPersistentCookie) + { + //Create a custom auth cookie + + //first, create the authentication ticket + FormsAuthenticationTicket authenticationTicket = createPersistentCookie + ? new FormsAuthenticationTicket(user.Username, true, Config.GetPersistentCookieTimeout()) + : new FormsAuthenticationTicket(user.Username, false, Config.GetAuthCookieTimeout()); + + //encrypt it + var encryptedAuthTicket = FormsAuthentication.Encrypt(authenticationTicket); + + //Create a new Cookie + var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedAuthTicket) + { + Expires = authenticationTicket.Expiration, + Domain = GetCookieDomain(user.PortalID), + Path = FormsAuthentication.FormsCookiePath, + Secure = FormsAuthentication.RequireSSL + }; + + HttpContext.Current.Response.Cookies.Set(authCookie); + + + if (PortalController.IsMemberOfPortalGroup(user.PortalID)) + { + var domain = GetCookieDomain(user.PortalID); + var siteGroupCookie = new HttpCookie("SiteGroup", domain) + { + Expires = authenticationTicket.Expiration, + Domain = domain, + Path = FormsAuthentication.FormsCookiePath, + Secure = FormsAuthentication.RequireSSL + }; + + HttpContext.Current.Response.Cookies.Set(siteGroupCookie); + } + } + else + { + FormsAuthentication.SetAuthCookie(user.Username, false); + } + } + + public void SignOut() + { + //Log User Off from Cookie Authentication System + var domainCookie = HttpContext.Current.Request.Cookies["SiteGroup"]; + if (domainCookie == null) + { + //Forms Authentication's Logout + FormsAuthentication.SignOut(); + } + else + { + //clear custom domain cookie + var domain = domainCookie.Value; + + //Create a new Cookie + string str = String.Empty; + if (HttpContext.Current.Request.Browser["supportsEmptyStringInCookieValue"] == "false") + { + str = "NoCookie"; + } + + var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, str) + { + Expires = new DateTime(1999, 1, 1), + Domain = domain, + Path = FormsAuthentication.FormsCookiePath, + Secure = FormsAuthentication.RequireSSL + + }; + + HttpContext.Current.Response.Cookies.Set(authCookie); + + var siteGroupCookie = new HttpCookie("SiteGroup", str) + { + Expires = new DateTime(1999, 1, 1), + Domain = domain, + Path = FormsAuthentication.FormsCookiePath, + Secure = FormsAuthentication.RequireSSL + }; + + HttpContext.Current.Response.Cookies.Set(siteGroupCookie); + } + + //Remove current userinfo from context items + HttpContext.Current.Items.Remove("UserInfo"); + + //remove language cookie + var httpCookie = HttpContext.Current.Response.Cookies["language"]; + if (httpCookie != null) + { + httpCookie.Value = ""; + } + + //remove authentication type cookie + var cookie = HttpContext.Current.Response.Cookies["authentication"]; + if (cookie != null) + { + cookie.Value = ""; + } + + //expire cookies + var httpCookie1 = HttpContext.Current.Response.Cookies["portalaliasid"]; + if (httpCookie1 != null) + { + httpCookie1.Value = null; + httpCookie1.Path = "/"; + httpCookie1.Expires = DateTime.Now.AddYears(-30); + } + + var cookie1 = HttpContext.Current.Response.Cookies["portalroles"]; + if (cookie1 != null) + { + cookie1.Value = null; + cookie1.Path = "/"; + cookie1.Expires = DateTime.Now.AddYears(-30); + } + } + + ///----------------------------------------------------------------------------- + /// + /// This function applies security filtering to the UserInput string, and reports + /// whether the input string is valid. + /// + /// This is the string to be filtered + /// Flags which designate the filters to be applied + /// + ///----------------------------------------------------------------------------- + public bool ValidateInput(string userInput, FilterFlag filterType) + { + string filteredInput = InputFilter(userInput, filterType); + + return (userInput == filteredInput); + } + + #endregion + + #region Public Shared/Static Methods + + public static void ForceSecureConnection() + { + //get current url + string URL = HttpContext.Current.Request.Url.ToString(); + //if unsecure connection + if (URL.StartsWith("http://")) + { + //switch to secure connection + URL = URL.Replace("http://", "https://"); + //append ssl parameter to querystring to indicate secure connection processing has already occurred + if (URL.IndexOf("?", StringComparison.Ordinal) == -1) + { + URL = URL + "?ssl=1"; + } + else + { + URL = URL + "&ssl=1"; + } + //redirect to secure connection + HttpContext.Current.Response.Redirect(URL, true); + } + } + + public static string GetCookieDomain(int portalId) + { + string cookieDomain = String.Empty; + if (PortalController.IsMemberOfPortalGroup(portalId)) + { + //set cookie domain for portal group + var groupController = new PortalGroupController(); + var group = groupController.GetPortalGroups().SingleOrDefault(p => p.MasterPortalId == PortalController.GetEffectivePortalId(portalId)); + + if (@group != null + && !string.IsNullOrEmpty(@group.AuthenticationDomain) + && PortalSettings.Current.PortalAlias.HTTPAlias.Contains(@group.AuthenticationDomain)) + { + cookieDomain = @group.AuthenticationDomain; + } + + if (String.IsNullOrEmpty(cookieDomain)) + { + cookieDomain = FormsAuthentication.CookieDomain; + } + } + else + { + //set cookie domain to be consistent with domain specification in web.config + cookieDomain = FormsAuthentication.CookieDomain; + } + + + return cookieDomain; + } + + public static bool IsInRole(string role) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + HttpContext context = HttpContext.Current; + if (!String.IsNullOrEmpty(role) && ((context.Request.IsAuthenticated == false && role == Globals.glbRoleUnauthUserName))) + { + return true; + } + return objUserInfo.IsInRole(role); + } + + public static bool IsInRoles(string roles) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + //Portal Admin cannot be denied from his/her portal (so ignore deny permissions if user is portal admin) + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + return IsInRoles(objUserInfo, settings, roles); + } + + public static bool IsInRoles(UserInfo objUserInfo, PortalSettings settings, string roles) + { + //super user always has full access + bool blnIsInRoles = objUserInfo.IsSuperUser; + + if (!blnIsInRoles) + { + if (roles != null) + { + //permissions strings are encoded with Deny permissions at the beginning and Grant permissions at the end for optimal performance + foreach (string role in roles.Split(new[] { ';' })) + { + if (!String.IsNullOrEmpty(role)) + { + //Deny permission + if (role.StartsWith("!")) + { + //Portal Admin cannot be denied from his/her portal (so ignore deny permissions if user is portal admin) + if (!(settings.PortalId == objUserInfo.PortalID && settings.AdministratorId == objUserInfo.UserID)) + { + string denyRole = role.Replace("!", ""); + if (denyRole == Globals.glbRoleAllUsersName || objUserInfo.IsInRole(denyRole)) + { + break; + } + } + } + else //Grant permission + { + if (role == Globals.glbRoleAllUsersName || objUserInfo.IsInRole(role)) + { + blnIsInRoles = true; + break; + } + } + } + } + } + } + return blnIsInRoles; + } + + #endregion + + #region Obsoleted Methods, retained for Binary Compatability + + [Obsolete("Deprecated in DNN 6.2 - roles cookie is no longer used)")] + public static void ClearRoles() + { + var httpCookie = HttpContext.Current.Response.Cookies["portalroles"]; + if (httpCookie != null) + { + httpCookie.Value = null; + httpCookie.Path = "/"; + httpCookie.Expires = DateTime.Now.AddYears(-30); + } + } + + [Obsolete("Deprecated in DNN 5.0. Please use HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo, Username)")] + public static bool HasEditPermissions(int ModuleId) + { + return + ModulePermissionController.HasModulePermission( + new ModulePermissionCollection(CBO.FillCollection(DataProvider.Instance().GetModulePermissionsByModuleID(ModuleId, -1), typeof (ModulePermissionInfo))), "EDIT"); + } + + [Obsolete("Deprecated in DNN 5.0. Please use HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo)")] + public static bool HasEditPermissions(ModulePermissionCollection objModulePermissions) + { + return ModulePermissionController.HasModulePermission(objModulePermissions, "EDIT"); + } + + [Obsolete("Deprecated in DNN 5.0. Please use HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo)")] + public static bool HasEditPermissions(int ModuleId, int Tabid) + { + return ModulePermissionController.HasModulePermission(ModulePermissionController.GetModulePermissions(ModuleId, Tabid), "EDIT"); + } + + [Obsolete("Deprecated in DNN 5.1. Please use ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo)")] + public static bool HasNecessaryPermission(SecurityAccessLevel AccessLevel, PortalSettings PortalSettings, ModuleInfo ModuleConfiguration, string UserName) + { + return ModulePermissionController.HasModuleAccess(AccessLevel, "EDIT", ModuleConfiguration); + } + + [Obsolete("Deprecated in DNN 5.1. Please use ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo)")] + public static bool HasNecessaryPermission(SecurityAccessLevel AccessLevel, PortalSettings PortalSettings, ModuleInfo ModuleConfiguration, UserInfo User) + { + return ModulePermissionController.HasModuleAccess(AccessLevel, "EDIT", ModuleConfiguration); + } + + [Obsolete("Deprecated in DNN 5.1. Please use ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, PortalSettings, ModuleInfo)")] + public static bool HasNecessaryPermission(SecurityAccessLevel AccessLevel, PortalSettings PortalSettings, ModuleInfo ModuleConfiguration) + { + return ModulePermissionController.HasModuleAccess(AccessLevel, "EDIT", ModuleConfiguration); + } + + [Obsolete("Deprecated in DNN 5.1. Please use TabPermissionController.CanAdminPage")] + public static bool IsPageAdmin() + { + return TabPermissionController.CanAdminPage(); + } + + [Obsolete("Deprecated in DNN 4.3. This function has been replaced by UserController.UserLogin")] + public int UserLogin(string Username, string Password, int PortalID, string PortalName, string IP, bool CreatePersistentCookie) + { + UserLoginStatus loginStatus = UserLoginStatus.LOGIN_FAILURE; + int UserId = -1; + UserInfo objUser = UserController.UserLogin(PortalID, Username, Password, "", PortalName, IP, ref loginStatus, CreatePersistentCookie); + if (loginStatus == UserLoginStatus.LOGIN_SUCCESS || loginStatus == UserLoginStatus.LOGIN_SUPERUSER) + { + UserId = objUser.UserID; + } + return UserId; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Profile/DNNProfileProvider.cs b/DNN Platform/Library/Security/Profile/DNNProfileProvider.cs new file mode 100644 index 00000000000..f5f1695595a --- /dev/null +++ b/DNN Platform/Library/Security/Profile/DNNProfileProvider.cs @@ -0,0 +1,230 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Globalization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Security.Profile +// ReSharper restore CheckNamespace +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Profile + /// Class: DNNProfileProvider + /// ----------------------------------------------------------------------------- + /// + /// The DNNProfileProvider overrides the default ProfileProvider to provide + /// a purely DotNetNuke implementation + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class DNNProfileProvider : ProfileProvider + { + #region Private Members + + private readonly DataProvider _dataProvider = DataProvider.Instance(); + + #endregion + + #region Private Methods + + private void UpdateTimeZoneInfo(UserInfo user, ProfilePropertyDefinitionCollection properties) + { + ProfilePropertyDefinition newTimeZone = properties["PreferredTimeZone"]; + ProfilePropertyDefinition oldTimeZone = properties["TimeZone"]; + if (newTimeZone != null && oldTimeZone != null) + { + //Old timezone is present but new is not...we will set that up. + if (!string.IsNullOrEmpty(oldTimeZone.PropertyValue) && string.IsNullOrEmpty(newTimeZone.PropertyValue)) + { + int oldOffset; + int.TryParse(oldTimeZone.PropertyValue, out oldOffset); + TimeZoneInfo timeZoneInfo = Localization.ConvertLegacyTimeZoneOffsetToTimeZoneInfo(oldOffset); + newTimeZone.PropertyValue = timeZoneInfo.Id; + UpdateUserProfile(user); + } + //It's also possible that the new value is set but not the old value. We need to make them backwards compatible + else if (!string.IsNullOrEmpty(newTimeZone.PropertyValue) && string.IsNullOrEmpty(oldTimeZone.PropertyValue)) + { + TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(newTimeZone.PropertyValue); + if (timeZoneInfo != null) + { + oldTimeZone.PropertyValue = timeZoneInfo.BaseUtcOffset.TotalMinutes.ToString(CultureInfo.InvariantCulture); + } + } + } + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Provider Properties can be edited + /// + /// A Boolean + /// ----------------------------------------------------------------------------- + public override bool CanEditProviderProperties + { + get + { + return true; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserProfile retrieves the UserProfile information from the Data Store + /// + /// + /// + /// The user whose Profile information we are retrieving. + /// ----------------------------------------------------------------------------- + public override void GetUserProfile(ref UserInfo user) + { + ProfilePropertyDefinition profProperty; + + int portalId = user.IsSuperUser ? Globals.glbSuperUserAppName : user.PortalID; + var properties = ProfileController.GetPropertyDefinitionsByPortal(portalId, true, false); + + //Load the Profile properties + if (user.UserID > Null.NullInteger) + { + IDataReader dr = _dataProvider.GetUserProfile(user.UserID); + try + { + while (dr.Read()) + { + //Ensure the data reader returned is valid + if (!string.Equals(dr.GetName(0), "ProfileID", StringComparison.InvariantCultureIgnoreCase)) + { + break; + } + int definitionId = Convert.ToInt32(dr["PropertyDefinitionId"]); + profProperty = properties.GetById(definitionId); + if (profProperty != null) + { + profProperty.PropertyValue = Convert.ToString(dr["PropertyValue"]); + var extendedVisibility = string.Empty; + if (dr.GetSchemaTable().Select("ColumnName = 'ExtendedVisibility'").Length > 0) + { + extendedVisibility = Convert.ToString(dr["ExtendedVisibility"]); + } + profProperty.ProfileVisibility = new ProfileVisibility(portalId, extendedVisibility) + { + VisibilityMode = (UserVisibilityMode)dr["Visibility"] + }; + } + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + + //Clear the profile + user.Profile.ProfileProperties.Clear(); + + //Add the properties to the profile + foreach (ProfilePropertyDefinition property in properties) + { + profProperty = property; + if (string.IsNullOrEmpty(profProperty.PropertyValue) && !string.IsNullOrEmpty(profProperty.DefaultValue)) + { + profProperty.PropertyValue = profProperty.DefaultValue; + } + user.Profile.ProfileProperties.Add(profProperty); + } + + //Clear IsDirty Flag + user.Profile.ClearIsDirty(); + + //Ensure old and new TimeZone properties are in synch + UpdateTimeZoneInfo(user, properties); + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateUserProfile persists a user's Profile to the Data Store + /// + /// + /// + /// The user to persist to the Data Store. + /// ----------------------------------------------------------------------------- + public override void UpdateUserProfile(UserInfo user) + { + ProfilePropertyDefinitionCollection properties = user.Profile.ProfileProperties; + + //Ensure old and new TimeZone properties are in synch + var newTimeZone = properties["PreferredTimeZone"]; + var oldTimeZone = properties["TimeZone"]; + if (oldTimeZone != null && newTimeZone != null) + { //preference given to new property, if new is changed then old should be updated as well. + if (newTimeZone.IsDirty && !string.IsNullOrEmpty(newTimeZone.PropertyValue)) + { + var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(newTimeZone.PropertyValue); + if (timeZoneInfo != null) + oldTimeZone.PropertyValue = timeZoneInfo.BaseUtcOffset.TotalMinutes.ToString(CultureInfo.InvariantCulture); + } + //however if old is changed, we need to update new as well + else if (oldTimeZone.IsDirty) + { + int oldOffset; + int.TryParse(oldTimeZone.PropertyValue, out oldOffset); + newTimeZone.PropertyValue = Localization.ConvertLegacyTimeZoneOffsetToTimeZoneInfo(oldOffset).Id; + } + } + + foreach (ProfilePropertyDefinition profProperty in properties) + { + if ((profProperty.PropertyValue != null) && (profProperty.IsDirty)) + { + var objSecurity = new PortalSecurity(); + string propertyValue = objSecurity.InputFilter(profProperty.PropertyValue, PortalSecurity.FilterFlag.NoScripting); + _dataProvider.UpdateProfileProperty(Null.NullInteger, user.UserID, profProperty.PropertyDefinitionId, + propertyValue, (int) profProperty.ProfileVisibility.VisibilityMode, + profProperty.ProfileVisibility.ExtendedVisibilityString(), DateTime.Now); + var objEventLog = new EventLogController(); + objEventLog.AddLog(user, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", "USERPROFILE_UPDATED"); + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Profile/ProfileProvider.cs b/DNN Platform/Library/Security/Profile/ProfileProvider.cs new file mode 100644 index 00000000000..af100009925 --- /dev/null +++ b/DNN Platform/Library/Security/Profile/ProfileProvider.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Security.Profile +{ + public abstract class ProfileProvider + { + #region "Abstract Properties" + + public abstract bool CanEditProviderProperties { get; } + + #endregion + + #region "Shared/Static Methods" + + //return the provider + public static ProfileProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region "Abstract Methods" + + public abstract void GetUserProfile(ref UserInfo user); + + public abstract void UpdateUserProfile(UserInfo user); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Profile/ProfileProviderConfig.cs b/DNN Platform/Library/Security/Profile/ProfileProviderConfig.cs new file mode 100644 index 00000000000..0c32dca1f05 --- /dev/null +++ b/DNN Platform/Library/Security/Profile/ProfileProviderConfig.cs @@ -0,0 +1,66 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; + +#endregion + +namespace DotNetNuke.Security.Profile +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Profile + /// Class: ProfileProviderConfig + /// ----------------------------------------------------------------------------- + /// + /// The ProfileProviderConfig class provides a wrapper to the Profile providers + /// configuration + /// + /// + /// + /// + /// [cnurse] 03/09/2006 created + /// + /// ----------------------------------------------------------------------------- + public class ProfileProviderConfig + { + private static readonly ProfileProvider profileProvider = ProfileProvider.Instance(); + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Provider Properties can be edited + /// + /// A Boolean + /// + /// [cnurse] 03/02/2006 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public static bool CanEditProviderProperties + { + get + { + return profileProvider.CanEditProviderProperties; + } + } + } +} diff --git a/DNN Platform/Library/Security/Roles/DNNRoleProvider.cs b/DNN Platform/Library/Security/Roles/DNNRoleProvider.cs new file mode 100644 index 00000000000..f4d3bc26ec7 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/DNNRoleProvider.cs @@ -0,0 +1,440 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Globalization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Membership; + +#endregion + +namespace DotNetNuke.Security.Roles +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Membership + /// Class: DNNRoleProvider + /// ----------------------------------------------------------------------------- + /// + /// The DNNRoleProvider overrides the default MembershipProvider to provide + /// a purely DNN Membership Component implementation + /// + /// + /// + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public class DNNRoleProvider : RoleProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (DNNRoleProvider)); + private readonly DataProvider dataProvider = DataProvider.Instance(); + + #region Private Methods + + private void AddDNNUserRole(UserRoleInfo userRole) + { + //Add UserRole to DNN + userRole.UserRoleID = Convert.ToInt32(dataProvider.AddUserRole(userRole.PortalID, userRole.UserID, userRole.RoleID, + (int)userRole.Status, userRole.IsOwner, + userRole.EffectiveDate, userRole.ExpiryDate, + UserController.GetCurrentUserInfo().UserID)); + } + + #endregion + + #region Role Methods + + /// ----------------------------------------------------------------------------- + /// + /// CreateRole persists a Role to the Data Store + /// + /// + /// + /// The role to persist to the Data Store. + /// A Boolean indicating success or failure. + /// ----------------------------------------------------------------------------- + public override bool CreateRole(RoleInfo role) + { + try + { + role.RoleID = + Convert.ToInt32(dataProvider.AddRole(role.PortalID, + role.RoleGroupID, + role.RoleName, + role.Description, + role.ServiceFee, + role.BillingPeriod.ToString(CultureInfo.InvariantCulture), + role.BillingFrequency, + role.TrialFee, + role.TrialPeriod, + role.TrialFrequency, + role.IsPublic, + role.AutoAssignment, + role.RSVPCode, + role.IconFile, + UserController.GetCurrentUserInfo().UserID, + (int)role.Status, + (int)role.SecurityMode, + role.IsSystemRole)); + } + catch (SqlException e) + { + throw new ArgumentException(e.ToString()); + } + + return true; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteRole deletes a Role from the Data Store + /// + /// The role to delete from the Data Store. + /// ----------------------------------------------------------------------------- + public override void DeleteRole(RoleInfo role) + { + dataProvider.DeleteRole(role.RoleID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get the roles for a portal + /// + /// Id of the portal (If -1 all roles for all portals are + /// retrieved. + /// An ArrayList of RoleInfo objects + /// ----------------------------------------------------------------------------- + public override ArrayList GetRoles(int portalId) + { + var arrRoles = CBO.FillCollection(portalId == Null.NullInteger + ? dataProvider.GetRoles() + : dataProvider.GetPortalRoles(portalId), typeof (RoleInfo)); + return arrRoles; + } + + public override IList GetRolesBasicSearch(int portalID, int pageSize, string filterBy) + { + return CBO.FillCollection(dataProvider.GetRolesBasicSearch(portalID, pageSize, filterBy)); + } + + public override IDictionary GetRoleSettings(int roleId) + { + var settings = new Dictionary { }; + using (IDataReader dr = dataProvider.GetRoleSettings(roleId)) { + while (dr.Read()) { + settings.Add(dr["SettingName"].ToString(), dr["SettingValue"].ToString()); + } + dr.Close(); + } + return settings; + } + + /// ----------------------------------------------------------------------------- + /// + /// Update a role + /// + /// The role to update + /// ----------------------------------------------------------------------------- + public override void UpdateRole(RoleInfo role) + { + dataProvider.UpdateRole(role.RoleID, + role.RoleGroupID, + role.RoleName, + role.Description, + role.ServiceFee, + role.BillingPeriod.ToString(CultureInfo.InvariantCulture), + role.BillingFrequency, + role.TrialFee, + role.TrialPeriod, + role.TrialFrequency, + role.IsPublic, + role.AutoAssignment, + role.RSVPCode, + role.IconFile, + UserController.GetCurrentUserInfo().UserID, + (int)role.Status, + (int)role.SecurityMode, + role.IsSystemRole); + } + + /// ----------------------------------------------------------------------------- + /// + /// Update the role settings for a role + /// + /// The role to update + /// ----------------------------------------------------------------------------- + public override void UpdateRoleSettings(RoleInfo role) + { + var currentSettings = GetRoleSettings(role.RoleID); + + foreach (var setting in role.Settings) + { + if (!currentSettings.ContainsKey(setting.Key) || currentSettings[setting.Key] != setting.Value) + { + dataProvider.UpdateRoleSetting(role.RoleID, setting.Key, setting.Value, UserController.GetCurrentUserInfo().UserID); + } + } + } + + #endregion + + #region User Role Methods + + /// ----------------------------------------------------------------------------- + /// + /// AddUserToRole adds a User to a Role + /// + /// + /// + /// Id of the portal + /// The user to add. + /// The role to add the user to. + /// A Boolean indicating success or failure. + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override bool AddUserToRole(int portalId, UserInfo user, UserRoleInfo userRole) + { + bool createStatus = true; + try + { + //Add UserRole to DNN + AddDNNUserRole(userRole); + } + catch (Exception exc) + { + //Clear User (duplicate User information) + Logger.Error(exc); + + createStatus = false; + } + return createStatus; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserRole gets a User/Role object from the Data Store + /// + /// + /// + /// Id of the portal + /// The Id of the User + /// The Id of the Role. + /// The UserRoleInfo object + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override UserRoleInfo GetUserRole(int portalId, int userId, int roleId) + { + return CBO.FillObject(dataProvider.GetUserRole(portalId, userId, roleId)); + } + + /// + /// Gets a list of UserRoles for the user + /// + /// A UserInfo object representaing the user + /// Include private roles. + /// A list of UserRoleInfo objects + public override IList GetUserRoles(UserInfo user, bool includePrivate) + { + Requires.NotNull("user", user); + + return CBO.FillCollection(includePrivate + ? dataProvider.GetUserRoles(user.PortalID, user.UserID) + : dataProvider.GetServices(user.PortalID, user.UserID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetUserRoles gets a collection of User/Role objects from the Data Store + /// + /// + /// + /// Id of the portal + /// The user to fetch roles for + /// The role to fetch users for + /// An ArrayList of UserRoleInfo objects + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override ArrayList GetUserRoles(int portalId, string userName, string roleName) + { + return CBO.FillCollection(dataProvider.GetUserRolesByUsername(portalId, userName, roleName), typeof (UserRoleInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get the users in a role (as User objects) + /// + /// Id of the portal (If -1 all roles for all portals are + /// retrieved. + /// The role to fetch users for + /// An ArrayList of UserInfo objects + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override ArrayList GetUsersByRoleName(int portalId, string roleName) + { + return AspNetMembershipProvider.FillUserCollection(portalId, dataProvider.GetUsersByRolename(portalId, roleName)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Remove a User from a Role + /// + /// + /// + /// Id of the portal + /// The user to remove. + /// The role to remove the user from. + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override void RemoveUserFromRole(int portalId, UserInfo user, UserRoleInfo userRole) + { + dataProvider.DeleteUserRole(userRole.UserID, userRole.RoleID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a User/Role + /// + /// The User/Role to update + /// + /// [cnurse] 12/15/2005 created + /// + /// ----------------------------------------------------------------------------- + public override void UpdateUserRole(UserRoleInfo userRole) + { + dataProvider.UpdateUserRole(userRole.UserRoleID, + (int)userRole.Status, userRole.IsOwner, + userRole.EffectiveDate, userRole.ExpiryDate, + UserController.GetCurrentUserInfo().UserID); + } + + #endregion + + #region RoleGroup Methods + + /// ----------------------------------------------------------------------------- + /// + /// CreateRoleGroup persists a RoleGroup to the Data Store + /// + /// + /// + /// The RoleGroup to persist to the Data Store. + /// The Id of the new role. + /// + /// [cnurse] 03/28/2006 created + /// [jlucarino] 02/26/2009 added CreatedByUserID parameter + /// + /// ----------------------------------------------------------------------------- + public override int CreateRoleGroup(RoleGroupInfo roleGroup) + { + return Convert.ToInt32(dataProvider.AddRoleGroup(roleGroup.PortalID, roleGroup.RoleGroupName, roleGroup.Description, UserController.GetCurrentUserInfo().UserID)); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteRoleGroup deletes a RoleGroup from the Data Store + /// + /// The RoleGroup to delete from the Data Store. + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override void DeleteRoleGroup(RoleGroupInfo roleGroup) + { + dataProvider.DeleteRoleGroup(roleGroup.RoleGroupID); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetRoleGroup gets a RoleGroup from the Data Store + /// + /// Id of the portal + /// The Id of the RoleGroup to retrieve. + /// A RoleGroupInfo object + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override RoleGroupInfo GetRoleGroup(int portalId, int roleGroupId) + { + return CBO.FillObject(dataProvider.GetRoleGroup(portalId, roleGroupId)); + } + + public override RoleGroupInfo GetRoleGroupByName(int PortalID, string RoleGroupName) + { + return CBO.FillObject(dataProvider.GetRoleGroupByName(PortalID, RoleGroupName)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get the RoleGroups for a portal + /// + /// Id of the portal. + /// An ArrayList of RoleGroupInfo objects + /// + /// [cnurse] 03/28/2006 created + /// + /// ----------------------------------------------------------------------------- + public override ArrayList GetRoleGroups(int portalId) + { + return CBO.FillCollection(dataProvider.GetRoleGroups(portalId), typeof(RoleGroupInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Update a RoleGroup + /// + /// The RoleGroup to update + /// + /// [cnurse] 03/28/2006 created + /// [jlucarino] 02/26/2009 added LastModifiedByUserID parameter + /// + /// ----------------------------------------------------------------------------- + public override void UpdateRoleGroup(RoleGroupInfo roleGroup) + { + dataProvider.UpdateRoleGroup(roleGroup.RoleGroupID, roleGroup.RoleGroupName, roleGroup.Description, UserController.GetCurrentUserInfo().UserID); + } + + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Roles/Internal/IRoleController.cs b/DNN Platform/Library/Security/Roles/Internal/IRoleController.cs new file mode 100644 index 00000000000..12fc5e853ac --- /dev/null +++ b/DNN Platform/Library/Security/Roles/Internal/IRoleController.cs @@ -0,0 +1,131 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Security.Roles.Internal +{ + public interface IRoleController + { + /// ----------------------------------------------------------------------------- + /// + /// Adds a role + /// + /// The Role to Add + /// The Id of the new role + /// ----------------------------------------------------------------------------- + int AddRole(RoleInfo role); + + /// + /// Adds a role + /// + /// The Role to Add + /// Add this role on all exist users if auto assignment is true. + /// The Id of the new role + int AddRole(RoleInfo role, bool addToExistUsers); + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a role + /// + /// The Role to delete + /// ----------------------------------------------------------------------------- + void DeleteRole(RoleInfo role); + + /// ----------------------------------------------------------------------------- + /// + /// Fetch a single role based on a predicate + /// + /// Id of the portal + /// The predicate (criteria) required + /// A RoleInfo object + /// ----------------------------------------------------------------------------- + RoleInfo GetRole(int portalId, Func predicate); + + /// ----------------------------------------------------------------------------- + /// + /// Obtains a list of roles from the cache (or for the database if the cache has expired) + /// + /// The id of the portal + /// The list of roles + /// ----------------------------------------------------------------------------- + IList GetRoles(int portalId); + + /// + /// get a list of roles based on progressive search + /// + /// the id of the portal + /// the number of items to return + /// the text used to trim data + /// + IList GetRolesBasicSearch(int portalID, int pageSize, string filterBy); + + /// ----------------------------------------------------------------------------- + /// + /// Get the roles based on a predicate + /// + /// Id of the portal + /// The predicate (criteria) required + /// A List of RoleInfo objects + /// ----------------------------------------------------------------------------- + IList GetRoles(int portalId, Func predicate); + + /// ----------------------------------------------------------------------------- + /// + /// Gets the settings for a role + /// + /// Id of the role + /// A Dictionary of settings + /// ----------------------------------------------------------------------------- + IDictionary GetRoleSettings(int roleId); + + /// ----------------------------------------------------------------------------- + /// + /// Persists a role to the Data Store + /// + /// The role to persist + /// ----------------------------------------------------------------------------- + void UpdateRole(RoleInfo role); + + /// + /// Persists a role to the Data Store + /// + /// The role to persist + /// Add this role on all exist users if auto assignment is true. + void UpdateRole(RoleInfo role, bool addToExistUsers); + + /// ----------------------------------------------------------------------------- + /// + /// Update the role settings + /// + /// The Role + /// A flag that indicates whether the cache should be cleared + /// ----------------------------------------------------------------------------- + void UpdateRoleSettings(RoleInfo role, bool clearCache); + + /// + /// Clears Roles cache for the passed portal ID and for the default ID (-1) as well. + /// + /// Id of the portal + void ClearRoleCache(int portalId); + } +} diff --git a/DNN Platform/Library/Security/Roles/Internal/RoleControllerImpl.cs b/DNN Platform/Library/Security/Roles/Internal/RoleControllerImpl.cs new file mode 100644 index 00000000000..ea01ed2d051 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/Internal/RoleControllerImpl.cs @@ -0,0 +1,208 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Journal; + +namespace DotNetNuke.Security.Roles.Internal +{ + internal class RoleControllerImpl : IRoleController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (RoleControllerImpl)); + #region Private Members + + private static readonly RoleProvider provider = RoleProvider.Instance(); + + #endregion + + #region Private Methods + + private void AddMessage(RoleInfo roleInfo, EventLogController.EventLogType logType) + { + var eventLogController = new EventLogController(); + eventLogController.AddLog(roleInfo, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + "", + logType); + + } + + private void AutoAssignUsers(RoleInfo role) + { + if (role.AutoAssignment) + { + //loop through users for portal and add to role + var arrUsers = UserController.GetUsers(role.PortalID); + foreach (UserInfo objUser in arrUsers) + { + try + { + var legacyRoleController = new RoleController(); + legacyRoleController.AddUserRole(role.PortalID, objUser.UserID, role.RoleID, Null.NullDate, Null.NullDate); + } + catch (Exception exc) + { + //user already belongs to role + Logger.Error(exc); + } + } + } + } + + public void ClearRoleCache(int portalId) + { + DataCache.RemoveCache(String.Format(DataCache.RolesCacheKey, portalId)); + if (portalId != Null.NullInteger) + { + DataCache.RemoveCache(String.Format(DataCache.RolesCacheKey, Null.NullInteger)); + } + } + + #endregion + + #region IRoleController Implementation + + public int AddRole(RoleInfo role) + { + return AddRole(role, true); + } + + public int AddRole(RoleInfo role, bool addToExistUsers) + { + Requires.NotNull("role", role); + + var roleId = -1; + if (provider.CreateRole(role)) + { + AddMessage(role, EventLogController.EventLogType.ROLE_CREATED); + if (addToExistUsers) + { + AutoAssignUsers(role); + } + roleId = role.RoleID; + + ClearRoleCache(role.PortalID); + } + + return roleId; + } + + public void DeleteRole(RoleInfo role) + { + Requires.NotNull("role", role); + + AddMessage(role, EventLogController.EventLogType.ROLE_DELETED); + + if(role.SecurityMode != SecurityMode.SecurityRole) + { + //remove group artifacts + var portalSettings = PortalController.GetCurrentPortalSettings(); + + IFileManager _fileManager = FileManager.Instance; + IFolderManager _folderManager = FolderManager.Instance; + + IFolderInfo groupFolder = _folderManager.GetFolder(portalSettings.PortalId, "Groups/" + role.RoleID); + if (groupFolder != null) + { + _fileManager.DeleteFiles(_folderManager.GetFiles(groupFolder)); + _folderManager.DeleteFolder(groupFolder); + } + JournalController.Instance.SoftDeleteJournalItemByGroupId(portalSettings.PortalId, role.RoleID); + } + + provider.DeleteRole(role); + + ClearRoleCache(role.PortalID); + } + + public RoleInfo GetRole(int portalId, Func predicate) + { + return GetRoles(portalId).Where(predicate).FirstOrDefault(); + } + + public IList GetRoles(int portalId) + { + var cacheKey = String.Format(DataCache.RolesCacheKey, portalId); + return CBO.GetCachedObject>( + new CacheItemArgs(cacheKey, DataCache.RolesCacheTimeOut, DataCache.RolesCachePriority), + c => provider.GetRoles(portalId).Cast().ToList()); + } + + public IList GetRoles(int portalId, Func predicate) + { + return GetRoles(portalId).Where(predicate).ToList(); + } + + public IList GetRolesBasicSearch(int portalID, int pageSize, string filterBy) + { + return provider.GetRolesBasicSearch(portalID, pageSize, filterBy); + } + + public IDictionary GetRoleSettings(int roleId) + { + return provider.GetRoleSettings(roleId); + } + + public void UpdateRole(RoleInfo role) + { + UpdateRole(role, true); + } + + public void UpdateRole(RoleInfo role, bool addToExistUsers) + { + Requires.NotNull("role", role); + + provider.UpdateRole(role); + AddMessage(role, EventLogController.EventLogType.ROLE_UPDATED); + + if (addToExistUsers) + { + AutoAssignUsers(role); + } + + ClearRoleCache(role.PortalID); + } + + public void UpdateRoleSettings(RoleInfo role, bool clearCache) + { + provider.UpdateRoleSettings(role); + + if (clearCache) + { + ClearRoleCache(role.PortalID); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Roles/Internal/TestableRoleController.cs b/DNN Platform/Library/Security/Roles/Internal/TestableRoleController.cs new file mode 100644 index 00000000000..5903a99d8d4 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/Internal/TestableRoleController.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Security.Roles.Internal +{ + public class TestableRoleController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new RoleControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Security/Roles/RoleComparer.cs b/DNN Platform/Library/Security/Roles/RoleComparer.cs new file mode 100644 index 00000000000..5360f0276db --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleComparer.cs @@ -0,0 +1,64 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Security.Roles +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Roles + /// Class: RoleComparer + /// ----------------------------------------------------------------------------- + /// + /// The RoleComparer class provides an Implementation of IComparer for + /// RoleInfo objects + /// + /// + /// [cnurse] 05/24/2005 Split into separate file and documented + /// + /// ----------------------------------------------------------------------------- + public class RoleComparer : IComparer + { + #region IComparer Members + + /// ----------------------------------------------------------------------------- + /// + /// Compares two RoleInfo objects by performing a comparison of their rolenames + /// + /// One of the items to compare + /// One of the items to compare + /// An Integer that determines whether x is greater, smaller or equal to y + /// + /// [cnurse] 05/24/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public int Compare(object x, object y) + { + return new CaseInsensitiveComparer().Compare(((RoleInfo) x).RoleName, ((RoleInfo) y).RoleName); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Security/Roles/RoleController.cs b/DNN Platform/Library/Security/Roles/RoleController.cs new file mode 100644 index 00000000000..266893ff817 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleController.cs @@ -0,0 +1,883 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Messaging.Data; + +namespace DotNetNuke.Security.Roles +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Roles + /// Class: RoleController + /// ----------------------------------------------------------------------------- + /// + /// The RoleController class provides Business Layer methods for Roles + /// + /// + /// [cnurse] 05/23/2005 made compatible with .NET 2.0 + /// + /// ----------------------------------------------------------------------------- + public class RoleController + { + #region Private Nested Type: UserRoleActions + + private enum UserRoleActions + { + add = 0, + update = 1, + delete = 2 + } + + #endregion + + #region Private Shared Members + + private static readonly string[] UserRoleActionsCaption = {"ASSIGNMENT", "UPDATE", "UNASSIGNMENT"}; + + private static readonly RoleProvider provider = RoleProvider.Instance(); + + #endregion + + #region Private Methods + + private static bool DeleteUserRoleInternal(int portalId, int userId, int roleId) + { + var roleController = new RoleController(); + var user = UserController.GetUserById(portalId, userId); + var userRole = roleController.GetUserRole(portalId, userId, roleId); + var portalController = new PortalController(); + bool delete = true; + var portal = portalController.GetPortal(portalId); + if (portal != null && userRole != null) + { + if (CanRemoveUserFromRole(portal, userId, roleId)) + { + provider.RemoveUserFromRole(portalId, user, userRole); + var objEventLog = new EventLogController(); + objEventLog.AddLog(userRole, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.ROLE_UPDATED); + + //Remove the UserInfo from the Cache, as it has been modified + DataCache.ClearUserCache(portalId, user.Username); + TestableRoleController.Instance.ClearRoleCache(portalId); + } + else + { + delete = false; + } + } + return delete; + } + + private static void SendNotification(UserInfo objUser, RoleInfo objRole, PortalSettings PortalSettings, UserRoleActions Action) + { + var objRoles = new RoleController(); + var Custom = new ArrayList {objRole.RoleName, objRole.Description}; + switch (Action) + { + case UserRoleActions.add: + case UserRoleActions.update: + string preferredLocale = objUser.Profile.PreferredLocale; + if (string.IsNullOrEmpty(preferredLocale)) + { + preferredLocale = PortalSettings.DefaultLanguage; + } + var ci = new CultureInfo(preferredLocale); + UserRoleInfo objUserRole = objRoles.GetUserRole(PortalSettings.PortalId, objUser.UserID, objRole.RoleID); + Custom.Add(Null.IsNull(objUserRole.EffectiveDate) + ? DateTime.Today.ToString("g", ci) + : objUserRole.EffectiveDate.ToString("g", ci)); + Custom.Add(Null.IsNull(objUserRole.ExpiryDate) ? "-" : objUserRole.ExpiryDate.ToString("g", ci)); + break; + case UserRoleActions.delete: + Custom.Add(""); + break; + } + var _message = new Message + { + FromUserID = PortalSettings.AdministratorId, + ToUserID = objUser.UserID, + Subject = + Localization.GetSystemMessage(objUser.Profile.PreferredLocale, PortalSettings, + "EMAIL_ROLE_" + + UserRoleActionsCaption[(int) Action] + + "_SUBJECT", objUser), + Body = Localization.GetSystemMessage(objUser.Profile.PreferredLocale, + PortalSettings, + "EMAIL_ROLE_" + + UserRoleActionsCaption[(int) Action] + "_BODY", + objUser, + Localization.GlobalResourceFile, + Custom), + Status = MessageStatusType.Unread + }; + + //_messagingController.SaveMessage(_message); + Mail.SendEmail(PortalSettings.Email, objUser.Email, _message.Subject, _message.Body); + } + + #endregion + + #region Role Methods + + public int AddRole(RoleInfo role) + { + return TestableRoleController.Instance.AddRole(role); + } + + public void DeleteRole(int roleId, int portalId) + { + RoleInfo role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleID == roleId); + if (role != null) + { + TestableRoleController.Instance.DeleteRole(role); + } + } + + public ArrayList GetPortalRoles(int portalId) + { + return new ArrayList(TestableRoleController.Instance.GetRoles(portalId, r => r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).ToArray()); + } + + public RoleInfo GetRole(int roleId, int portalId) + { + return TestableRoleController.Instance.GetRole(portalId, r => r.RoleID == roleId); + } + + public RoleInfo GetRoleByName(int portalId, string roleName) + { + return TestableRoleController.Instance.GetRoles(portalId).SingleOrDefault(r => r.RoleName == roleName); + } + + public ArrayList GetRoles() + { + return new ArrayList(TestableRoleController.Instance.GetRoles(Null.NullInteger, r => r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).ToArray()); + } + + public ArrayList GetRolesByGroup(int portalId, int roleGroupId) + { + return new ArrayList(TestableRoleController.Instance.GetRoles(portalId, r => r.RoleGroupID == roleGroupId && r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved).ToArray()); + } + + public void UpdateRole(RoleInfo role) + { + TestableRoleController.Instance.UpdateRole(role); + } + + #endregion + + #region UserRoleInfo Methods + + /// ----------------------------------------------------------------------------- + /// + /// Adds a User to a Role + /// + /// The Id of the Portal + /// The Id of the User + /// The Id of the Role + /// The expiry Date of the Role membership + /// ----------------------------------------------------------------------------- + public void AddUserRole(int portalId, int userId, int roleId, DateTime expiryDate) + { + AddUserRole(portalId, userId, roleId, RoleStatus.Approved, false, Null.NullDate, expiryDate); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a User to a Role + /// + /// Overload adds Effective Date + /// The Id of the Portal + /// The Id of the User + /// The Id of the Role + /// The expiry Date of the Role membership + /// The expiry Date of the Role membership + /// ----------------------------------------------------------------------------- + public void AddUserRole(int portalId, int userId, int roleId, DateTime effectiveDate, DateTime expiryDate) + { + AddUserRole(portalId, userId, roleId, RoleStatus.Approved, false, effectiveDate, expiryDate); + } + + public void AddUserRole(int portalId, int userId, int roleId, RoleStatus status, bool isOwner, DateTime effectiveDate, DateTime expiryDate) + { + UserInfo user = UserController.GetUserById(portalId, userId); + UserRoleInfo userRole = GetUserRole(portalId, userId, roleId); + var eventLogController = new EventLogController(); + if (userRole == null) + { + //Create new UserRole + userRole = new UserRoleInfo + { + UserID = userId, + RoleID = roleId, + PortalID = portalId, + Status = status, + IsOwner = isOwner, + EffectiveDate = effectiveDate, + ExpiryDate = expiryDate + }; + provider.AddUserToRole(portalId, user, userRole); + eventLogController.AddLog(userRole, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_CREATED); + } + else + { + userRole.Status = status; + userRole.IsOwner = isOwner; + userRole.EffectiveDate = effectiveDate; + userRole.ExpiryDate = expiryDate; + provider.UpdateUserRole(userRole); + eventLogController.AddLog(userRole, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_UPDATED); + } + + //Remove the UserInfo and Roles from the Cache, as they have been modified + DataCache.ClearUserCache(portalId, user.Username); + TestableRoleController.Instance.ClearRoleCache(portalId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a User to a Role + /// + /// The user to assign + /// The role to add + /// The PortalSettings of the Portal + /// RoleStatus + /// The expiry Date of the Role membership + /// The expiry Date of the Role membership + /// A flag that indicates whether the user should be notified + /// A flag that indicates whether this user should be one of the group owners + /// ----------------------------------------------------------------------------- + public static void AddUserRole(UserInfo user, RoleInfo role, PortalSettings portalSettings, RoleStatus status, DateTime effectiveDate, DateTime expiryDate, bool notifyUser, bool isOwner) + { + var roleController = new RoleController(); + var userRole = roleController.GetUserRole(portalSettings.PortalId, user.UserID, role.RoleID); + var eventLogController = new EventLogController(); + + //update assignment + roleController.AddUserRole(portalSettings.PortalId, user.UserID, role.RoleID, status, isOwner, effectiveDate, expiryDate); + + UserController.UpdateUser(portalSettings.PortalId, user); + if (userRole == null) + { + eventLogController.AddLog("Role", role.RoleName, portalSettings, user.UserID, EventLogController.EventLogType.USER_ROLE_CREATED); + + //send notification + if (notifyUser) + { + SendNotification(user, role, portalSettings, UserRoleActions.@add); + } + } + else + { + eventLogController.AddLog("Role", role.RoleName, portalSettings, user.UserID, EventLogController.EventLogType.USER_ROLE_UPDATED); + if (notifyUser) + { + roleController.GetUserRole(portalSettings.PortalId, user.UserID, role.RoleID); + SendNotification(user, role, portalSettings, UserRoleActions.update); + } + } + + //Remove the UserInfo from the Cache, as it has been modified + DataCache.ClearUserCache(portalSettings.PortalId, user.Username); + } + + + /// ----------------------------------------------------------------------------- + /// + /// Determines if the specified user can be removed from a role + /// + /// + /// Roles such as "Registered Users" and "Administrators" can only + /// be removed in certain circumstances + /// + /// A PortalSettings structure representing the current portal settings + /// The Id of the User that should be checked for role removability + /// The Id of the Role that should be checked for removability + /// + /// + /// [anurse] 01/12/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CanRemoveUserFromRole(PortalSettings PortalSettings, int UserId, int RoleId) + { + //[DNN-4285] Refactored this check into a method for use in SecurityRoles.ascx.vb + //HACK: Duplicated in CanRemoveUserFromRole(PortalInfo, Integer, Integer) method below + //changes to this method should be reflected in the other method as well + return !((PortalSettings.AdministratorId == UserId && PortalSettings.AdministratorRoleId == RoleId) || PortalSettings.RegisteredRoleId == RoleId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Determines if the specified user can be removed from a role + /// + /// + /// Roles such as "Registered Users" and "Administrators" can only + /// be removed in certain circumstances + /// + /// A PortalInfo structure representing the current portal + /// The Id of the User + /// The Id of the Role that should be checked for removability + /// + /// + /// [anurse] 01/12/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static bool CanRemoveUserFromRole(PortalInfo PortalInfo, int UserId, int RoleId) + { + //[DNN-4285] Refactored this check into a method for use in SecurityRoles.ascx.vb + //HACK: Duplicated in CanRemoveUserFromRole(PortalSettings, Integer, Integer) method above + //changes to this method should be reflected in the other method as well + + return !((PortalInfo.AdministratorId == UserId && PortalInfo.AdministratorRoleId == RoleId) || PortalInfo.RegisteredRoleId == RoleId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Removes a User from a Role + /// + /// The user to remove + /// The role to remove the use from + /// The PortalSettings of the Portal + /// A flag that indicates whether the user should be notified + /// + /// [cnurse] 10/17/2007 Created (Refactored code from Security Roles user control) + /// + /// ----------------------------------------------------------------------------- + public static bool DeleteUserRole(UserInfo objUser, RoleInfo role, PortalSettings portalSettings, bool notifyUser) + { + bool canDelete = DeleteUserRoleInternal(portalSettings.PortalId, objUser.UserID, role.RoleID); + if (canDelete) + { + if (notifyUser) + { + SendNotification(objUser, role, portalSettings, UserRoleActions.delete); + } + } + return canDelete; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a User/Role + /// + /// The Id of the Portal + /// The Id of the user + /// The Id of the Role + /// A UserRoleInfo object + /// + /// [cnurse] 05/24/2005 Documented + /// [cnurse] 12/15/2005 Abstracted to MembershipProvider + /// + /// ----------------------------------------------------------------------------- + public UserRoleInfo GetUserRole(int PortalID, int UserId, int RoleId) + { + return provider.GetUserRole(PortalID, UserId, RoleId); + } + + /// + /// Gets a list of UserRoles for the user + /// + /// A UserInfo object representaing the user + /// Include private roles. + /// A list of UserRoleInfo objects + public IList GetUserRoles(UserInfo user, bool includePrivate) + { + return provider.GetUserRoles(user, includePrivate); + } + + public IList GetUserRoles(int portalID, string userName, string roleName) + { + return provider.GetUserRoles(portalID, userName, roleName).Cast().ToList(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Get the users in a role (as User objects) + /// + /// Id of the portal (If -1 all roles for all portals are + /// retrieved. + /// The role to fetch users for + /// An ArrayList of UserInfo objects + /// + /// [cnurse] 01/27/2006 created + /// + /// ----------------------------------------------------------------------------- + public ArrayList GetUsersByRoleName(int portalId, string roleName) + { + return provider.GetUsersByRoleName(portalId, roleName); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Service (UserRole) + /// + /// The Id of the Portal + /// The Id of the User + /// The Id of the Role + /// ----------------------------------------------------------------------------- + public void UpdateUserRole(int portalId, int userId, int roleId) + { + UpdateUserRole(portalId, userId, roleId, RoleStatus.Approved, false, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Service (UserRole) + /// + /// The Id of the Portal + /// The Id of the User + /// The Id of the Role + /// A flag that indicates whether to cancel (delete) the userrole + /// ----------------------------------------------------------------------------- + public void UpdateUserRole(int portalId, int userId, int roleId, bool cancel) + { + UpdateUserRole(portalId, userId, roleId, RoleStatus.Approved, false, cancel); + } + + public void UpdateUserRole(int portalId, int userId, int roleId, RoleStatus status, bool isOwner, bool cancel) + { + UserInfo user = UserController.GetUserById(portalId, userId); + UserRoleInfo userRole = GetUserRole(portalId, userId, roleId); + var eventLogController = new EventLogController(); + if (cancel) + { + if (userRole != null && userRole.ServiceFee > 0.0 && userRole.IsTrialUsed) + { + //Expire Role so we retain trial used data + userRole.ExpiryDate = DateTime.Now.AddDays(-1); + userRole.Status = status; + userRole.IsOwner = isOwner; + provider.UpdateUserRole(userRole); + eventLogController.AddLog(userRole, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_UPDATED); + } + else + { + //Delete Role + DeleteUserRoleInternal(portalId, userId, roleId); + eventLogController.AddLog("UserId", + userId.ToString(CultureInfo.InvariantCulture), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.USER_ROLE_DELETED); + } + } + else + { + int UserRoleId = -1; + DateTime ExpiryDate = DateTime.Now; + DateTime EffectiveDate = Null.NullDate; + bool IsTrialUsed = false; + int Period = 0; + string Frequency = ""; + if (userRole != null) + { + UserRoleId = userRole.UserRoleID; + EffectiveDate = userRole.EffectiveDate; + ExpiryDate = userRole.ExpiryDate; + IsTrialUsed = userRole.IsTrialUsed; + } + RoleInfo role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleID == roleId); + if (role != null) + { + if (IsTrialUsed == false && role.TrialFrequency != "N") + { + Period = role.TrialPeriod; + Frequency = role.TrialFrequency; + } + else + { + Period = role.BillingPeriod; + Frequency = role.BillingFrequency; + } + } + if (EffectiveDate < DateTime.Now) + { + EffectiveDate = Null.NullDate; + } + if (ExpiryDate < DateTime.Now) + { + ExpiryDate = DateTime.Now; + } + if (Period == Null.NullInteger) + { + ExpiryDate = Null.NullDate; + } + else + { + switch (Frequency) + { + case "N": + ExpiryDate = Null.NullDate; + break; + case "O": + ExpiryDate = new DateTime(9999, 12, 31); + break; + case "D": + ExpiryDate = ExpiryDate.AddDays(Period); + break; + case "W": + ExpiryDate = ExpiryDate.AddDays(Period * 7); + break; + case "M": + ExpiryDate = ExpiryDate.AddMonths(Period); + break; + case "Y": + ExpiryDate = ExpiryDate.AddYears(Period); + break; + } + } + if (UserRoleId != -1 && userRole != null) + { + userRole.ExpiryDate = ExpiryDate; + userRole.Status = status; + userRole.IsOwner = isOwner; + provider.UpdateUserRole(userRole); + eventLogController.AddLog(userRole, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_UPDATED); + } + else + { + AddUserRole(portalId, userId, roleId, status, isOwner, EffectiveDate, ExpiryDate); + } + } + + //Remove the UserInfo from the Cache, as it has been modified + DataCache.ClearUserCache(portalId, user.Username); + TestableRoleController.Instance.ClearRoleCache(portalId); + } + + #endregion + + #region RoleGroupInfo Methods + + /// ----------------------------------------------------------------------------- + /// + /// Adds a Role Group + /// + /// The RoleGroup to Add + /// The Id of the new role + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static int AddRoleGroup(RoleGroupInfo objRoleGroupInfo) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(objRoleGroupInfo, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_CREATED); + return provider.CreateRoleGroup(objRoleGroupInfo); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a Role Group + /// + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteRoleGroup(int PortalID, int RoleGroupId) + { + DeleteRoleGroup(GetRoleGroup(PortalID, RoleGroupId)); + } + + /// ----------------------------------------------------------------------------- + /// + /// Deletes a Role Group + /// + /// The RoleGroup to Delete + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteRoleGroup(RoleGroupInfo objRoleGroupInfo) + { + provider.DeleteRoleGroup(objRoleGroupInfo); + var objEventLog = new EventLogController(); + objEventLog.AddLog(objRoleGroupInfo, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_DELETED); + } + + /// ----------------------------------------------------------------------------- + /// + /// Fetch a single RoleGroup + /// + /// The Id of the Portal + /// Role Group ID + /// + /// + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static RoleGroupInfo GetRoleGroup(int portalId, int roleGroupId) + { + return provider.GetRoleGroup(portalId, roleGroupId); + } + + /// ----------------------------------------------------------------------------- + /// + /// Fetch a single RoleGroup by Name + /// + /// The Id of the Portal + /// Role Group Name + /// + /// + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static RoleGroupInfo GetRoleGroupByName(int portalId, string roleGroupName) + { + return provider.GetRoleGroupByName(portalId, roleGroupName); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an ArrayList of RoleGroups + /// + /// The Id of the Portal + /// An ArrayList of RoleGroups + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static ArrayList GetRoleGroups(int PortalID) + { + return provider.GetRoleGroups(PortalID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Serializes the role groups + /// + /// An XmlWriter + /// The Id of the Portal + /// + /// [cnurse] 03/18/2008 Created + /// + /// ----------------------------------------------------------------------------- + public static void SerializeRoleGroups(XmlWriter writer, int portalID) + { + //Serialize Role Groups + writer.WriteStartElement("rolegroups"); + foreach (RoleGroupInfo objRoleGroup in GetRoleGroups(portalID)) + { + CBO.SerializeObject(objRoleGroup, writer); + } + + //Serialize Global Roles + var globalRoleGroup = new RoleGroupInfo(Null.NullInteger, portalID, true) + { + RoleGroupName = "GlobalRoles", + Description = "A dummy role group that represents the Global roles" + }; + CBO.SerializeObject(globalRoleGroup, writer); + writer.WriteEndElement(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Updates a Role Group + /// + /// The RoleGroup to Update + /// + /// [cnurse] 01/03/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static void UpdateRoleGroup(RoleGroupInfo roleGroup) + { + UpdateRoleGroup(roleGroup, false); + } + + public static void UpdateRoleGroup(RoleGroupInfo roleGroup, bool includeRoles) + { + provider.UpdateRoleGroup(roleGroup); + var objEventLog = new EventLogController(); + objEventLog.AddLog(roleGroup, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.USER_ROLE_UPDATED); + if (includeRoles) + { + foreach (RoleInfo role in roleGroup.Roles.Values) + { + TestableRoleController.Instance.UpdateRole(role); + objEventLog.AddLog(role, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.ROLE_UPDATED); + } + } + } + + #endregion + + #region Obsoleted Methods, retained for Binary Compatability + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by AddRole(objRoleInfo)")] + public int AddRole(RoleInfo role, bool synchronizationMode) + { + role.SecurityMode = SecurityMode.SecurityRole; + role.Status = RoleStatus.Approved; + return TestableRoleController.Instance.AddRole(role); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public static bool DeleteUserRole(int userId, RoleInfo role, PortalSettings portalSettings, bool notifyUser) + { + UserInfo objUser = UserController.GetUserById(portalSettings.PortalId, userId); + return DeleteUserRole(objUser, role, portalSettings, notifyUser); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public static bool DeleteUserRole(int roleId, UserInfo user, PortalSettings portalSettings, bool notifyUser) + { + RoleInfo role = TestableRoleController.Instance.GetRole(portalSettings.PortalId, r => r.RoleID == roleId); + return DeleteUserRole(user, role, portalSettings, notifyUser); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public bool DeleteUserRole(int portalId, int userId, int roleId) + { + return DeleteUserRoleInternal(portalId, userId, roleId); + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetPortalRoles(PortalId)")] + public ArrayList GetPortalRoles(int portalId, bool synchronizeRoles) + { + return GetPortalRoles(portalId); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public string[] GetRoleNames(int portalId) + { + string[] roles = { }; + var roleList = TestableRoleController.Instance.GetRoles(portalId, role => role.SecurityMode != SecurityMode.SocialGroup && role.Status == RoleStatus.Approved); + var strRoles = roleList.Aggregate("", (current, role) => current + (role.RoleName + "|")); + if (strRoles.IndexOf("|", StringComparison.Ordinal) > 0) + { + roles = strRoles.Substring(0, strRoles.Length - 1).Split('|'); + } + return roles; + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetRolesByUser")] + public string[] GetPortalRolesByUser(int UserId, int PortalId) + { + return GetRolesByUser(UserId, PortalId); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public string[] GetRolesByUser(int UserId, int PortalId) + { + if(UserId == -1) + { + return new string[0]; + } + return UserController.GetUserById(PortalId, UserId).Roles; + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetUserRoles")] + public ArrayList GetServices(int PortalId) + { + return GetServices(PortalId, -1); + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetUserRoles")] + public ArrayList GetServices(int PortalId, int UserId) + { + return provider.GetUserRoles(PortalId, UserId, false); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public ArrayList GetUserRoles(int PortalId) + { + return GetUserRoles(PortalId, -1); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload that returns IList")] + public ArrayList GetUserRoles(int PortalId, int UserId) + { + return provider.GetUserRoles(PortalId, UserId, true); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload that returns IList")] + public ArrayList GetUserRoles(int PortalId, int UserId, bool includePrivate) + { + return provider.GetUserRoles(PortalId, UserId, includePrivate); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload of GetUserRoles that returns IList")] + public ArrayList GetUserRolesByUsername(int PortalID, string Username, string Rolename) + { + return provider.GetUserRoles(PortalID, Username, Rolename); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public ArrayList GetUserRolesByRoleName(int portalId, string roleName) + { + return provider.GetUserRoles(portalId, null, roleName); + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by GetUserRolesByRoleName")] + public ArrayList GetUsersInRole(int PortalID, string RoleName) + { + return provider.GetUserRolesByRoleName(PortalID, RoleName); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public static void SerializeRoles(XmlWriter writer, int portalId) + { + //Serialize Global Roles + writer.WriteStartElement("roles"); + foreach (RoleInfo role in TestableRoleController.Instance.GetRoles(portalId, r => r.RoleGroupID == Null.NullInteger)) + { + CBO.SerializeObject(role, writer); + } + writer.WriteEndElement(); + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by UpdateUserRole")] + public void UpdateService(int PortalId, int UserId, int RoleId) + { + UpdateUserRole(PortalId, UserId, RoleId, false); + } + + [Obsolete("Deprecated in DotNetNuke 5.0. This function has been replaced by UpdateUserRole")] + public void UpdateService(int PortalId, int UserId, int RoleId, bool Cancel) + { + UpdateUserRole(PortalId, UserId, RoleId, Cancel); + } + + [Obsolete("Deprecated in DotNetNuke 7.0. This function has been replaced by AddUserRole with additional params")] + public static void AddUserRole(UserInfo user, RoleInfo role, PortalSettings portalSettings, DateTime effectiveDate, DateTime expiryDate, int userId, bool notifyUser) + { + AddUserRole(user, role, portalSettings, RoleStatus.Approved, effectiveDate, expiryDate, notifyUser, false); + } + #endregion + + } +} diff --git a/DNN Platform/Library/Security/Roles/RoleGroupInfo.cs b/DNN Platform/Library/Security/Roles/RoleGroupInfo.cs new file mode 100644 index 00000000000..b7e7a758039 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleGroupInfo.cs @@ -0,0 +1,351 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Security.Roles +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Roles + /// Class: RoleGroupInfo + /// ----------------------------------------------------------------------------- + /// + /// The RoleGroupInfo class provides the Entity Layer RoleGroup object + /// + /// + /// [cnurse] 01/03/2006 made compatible with .NET 2.0 + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class RoleGroupInfo : BaseEntityInfo, IHydratable, IXmlSerializable + { + #region "Private Members" + + private string _Description; + private int _PortalID = Null.NullInteger; + private int _RoleGroupID = Null.NullInteger; + private string _RoleGroupName; + private Dictionary _Roles; + + #endregion + + #region "Constructors" + + public RoleGroupInfo() + { + } + + public RoleGroupInfo(int roleGroupID, int portalID, bool loadRoles) + { + _PortalID = portalID; + _RoleGroupID = roleGroupID; + if (loadRoles) + { + GetRoles(); + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the RoleGroup Id + /// + /// An Integer representing the Id of the RoleGroup + /// ----------------------------------------------------------------------------- + public int RoleGroupID + { + get + { + return _RoleGroupID; + } + set + { + _RoleGroupID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Portal Id for the RoleGroup + /// + /// An Integer representing the Id of the Portal + /// ----------------------------------------------------------------------------- + public int PortalID + { + get + { + return _PortalID; + } + set + { + _PortalID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the RoleGroup Name + /// + /// A string representing the Name of the RoleGroup + /// ----------------------------------------------------------------------------- + public string RoleGroupName + { + get + { + return _RoleGroupName; + } + set + { + _RoleGroupName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an sets the Description of the RoleGroup + /// + /// A string representing the description of the RoleGroup + /// ----------------------------------------------------------------------------- + public string Description + { + get + { + return _Description; + } + set + { + _Description = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Roles for this Role Group + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public Dictionary Roles + { + get + { + if (_Roles == null && RoleGroupID > Null.NullInteger) + { + GetRoles(); + } + return _Roles; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a RoleGroupInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 03/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + RoleGroupID = Null.SetNullInteger(dr["RoleGroupId"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + RoleGroupName = Null.SetNullString(dr["RoleGroupName"]); + Description = Null.SetNullString(dr["Description"]); + + //Fill base class fields + FillInternal(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 03/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int KeyID + { + get + { + return RoleGroupID; + } + set + { + RoleGroupID = value; + } + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the RoleGroupInfo + /// + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a RoleGroupInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name.ToLowerInvariant()) + { + case "roles": + if (!reader.IsEmptyElement) + { + ReadRoles(reader); + } + break; + case "rolegroupname": + RoleGroupName = reader.ReadElementContentAsString(); + break; + case "description": + Description = reader.ReadElementContentAsString(); + break; + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a RoleGroupInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("rolegroup"); + + //write out properties + writer.WriteElementString("rolegroupname", RoleGroupName); + writer.WriteElementString("description", Description); + + //Write start of roles + writer.WriteStartElement("roles"); + + //Iterate through roles + if (Roles != null) + { + foreach (RoleInfo role in Roles.Values) + { + role.WriteXml(writer); + } + } + + //Write end of Roles + writer.WriteEndElement(); + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + + private void GetRoles() + { + _Roles = new Dictionary(); + foreach (var role in TestableRoleController.Instance.GetRoles(PortalID, r => r.RoleGroupID == RoleGroupID)) + { + _Roles[role.RoleName] = role; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a Roles from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void ReadRoles(XmlReader reader) + { + reader.ReadStartElement("roles"); + _Roles = new Dictionary(); + do + { + reader.ReadStartElement("role"); + var role = new RoleInfo(); + role.ReadXml(reader); + _Roles.Add(role.RoleName, role); + } while (reader.ReadToNextSibling("role")); + } + } +} diff --git a/DNN Platform/Library/Security/Roles/RoleInfo.cs b/DNN Platform/Library/Security/Roles/RoleInfo.cs new file mode 100644 index 00000000000..3739e2c13a8 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleInfo.cs @@ -0,0 +1,750 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Security.Roles +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Security.Roles + /// Class: RoleInfo + /// ----------------------------------------------------------------------------- + /// + /// The RoleInfo class provides the Entity Layer Role object + /// + /// + /// [cnurse] 05/23/2005 made compatible with .NET 2.0 + /// [cnurse] 01/03/2006 added RoleGroupId property + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class RoleInfo : BaseEntityInfo, IHydratable, IXmlSerializable, IPropertyAccess + { + private RoleType _RoleType = RoleType.None; + private bool _RoleTypeSet = Null.NullBoolean; + private Dictionary _settings; + + public RoleInfo() + { + TrialFrequency = "N"; + BillingFrequency = "N"; + RoleID = Null.NullInteger; + IsSystemRole = false; + } + + #region Public Properties + /// + /// Gets whether this role is a system role + /// + /// A boolean representing whether this is a system role such as Administrators, Registered Users etc. + public bool IsSystemRole { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether users are automatically assigned to the role + /// + /// A boolean (True/False) + /// ----------------------------------------------------------------------------- + public bool AutoAssignment { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Billing Frequency for the role + /// + /// A String representing the Billing Frequency of the Role
    + ///
      + /// N - None + /// O - One time fee + /// D - Daily + /// W - Weekly + /// M - Monthly + /// Y - Yearly + ///
    + ///
    + /// ----------------------------------------------------------------------------- + public string BillingFrequency { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the length of the billing period + /// + /// An integer representing the length of the billing period + /// ----------------------------------------------------------------------------- + public int BillingPeriod { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets an sets the Description of the Role + /// + /// A string representing the description of the role + /// ----------------------------------------------------------------------------- + public string Description { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Icon File for the role + /// + /// A string representing the Icon File for the role + /// ----------------------------------------------------------------------------- + public string IconFile { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the role is public + /// + /// A boolean (True/False) + /// ----------------------------------------------------------------------------- + public bool IsPublic { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Portal Id for the Role + /// + /// An Integer representing the Id of the Portal + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int PortalID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Role Id + /// + /// An Integer representing the Id of the Role + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int RoleID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the RoleGroup Id + /// + /// An Integer representing the Id of the RoleGroup + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int RoleGroupID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Role Name + /// + /// A string representing the name of the role + /// ----------------------------------------------------------------------------- + public string RoleName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Role Type + /// + /// A enum representing the type of the role + /// ----------------------------------------------------------------------------- + public RoleType RoleType + { + get + { + if (!_RoleTypeSet) + { + GetRoleType(); + _RoleTypeSet = true; + } + return _RoleType; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the RSVP Code for the role + /// + /// A string representing the RSVP Code for the role + /// ----------------------------------------------------------------------------- + public string RSVPCode { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the role is a security role and can be used in Permission + /// Grids etc. + /// + /// A SecurityMode enum + /// ----------------------------------------------------------------------------- + public SecurityMode SecurityMode { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the fee for the role + /// + /// A single number representing the fee for the role + /// ----------------------------------------------------------------------------- + public float ServiceFee { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the role settings + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public Dictionary Settings + { + get + { + return _settings ?? (_settings = (RoleID == Null.NullInteger) + ? new Dictionary() + : TestableRoleController.Instance.GetRoleSettings(RoleID) as + Dictionary); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the status for the role + /// + /// An enumerated value Pending, Disabled, Approved + /// ----------------------------------------------------------------------------- + public RoleStatus Status { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the trial fee for the role + /// + /// A single number representing the trial fee for the role + /// ----------------------------------------------------------------------------- + public float TrialFee { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Trial Frequency for the role + /// + /// A String representing the Trial Frequency of the Role
    + ///
      + /// N - None + /// O - One time fee + /// D - Daily + /// W - Weekly + /// M - Monthly + /// Y - Yearly + ///
    + ///
    + /// ----------------------------------------------------------------------------- + public string TrialFrequency { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the length of the trial period + /// + /// An integer representing the length of the trial period + /// ----------------------------------------------------------------------------- + public int TrialPeriod { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the number of users in the role + /// + /// An integer representing the number of users + /// ----------------------------------------------------------------------------- + public int UserCount { get; private set; } + + public string PhotoURL + { + get + { + string photoURL = Globals.ApplicationPath + "/images/sample-group-profile.jpg"; + + if ((IconFile != null)) + { + if (!string.IsNullOrEmpty(IconFile)) + { + IFileInfo fileInfo = + FileManager.Instance.GetFile(int.Parse(IconFile.Replace("FileID=", string.Empty))); + if ((fileInfo != null)) + { + photoURL = FileManager.Instance.GetUrl(fileInfo); + } + } + } + return photoURL; + } + } + + #endregion + + #region Private Methods + + private void GetRoleType() + { + PortalInfo portal = new PortalController().GetPortal(PortalID); + if (RoleID == portal.AdministratorRoleId) + { + _RoleType = RoleType.Administrator; + } + else if (RoleID == portal.RegisteredRoleId) + { + _RoleType = RoleType.RegisteredUser; + } + else if (RoleName == "Subscribers") + { + _RoleType = RoleType.Subscriber; + } + else if (RoleName == "Unverified Users") + { + _RoleType = RoleType.UnverifiedUser; + } + } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a RoleInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 03/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public virtual void Fill(IDataReader dr) + { + RoleID = Null.SetNullInteger(dr["RoleId"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + RoleGroupID = Null.SetNullInteger(dr["RoleGroupId"]); + RoleName = Null.SetNullString(dr["RoleName"]); + Description = Null.SetNullString(dr["Description"]); + ServiceFee = Null.SetNullSingle(dr["ServiceFee"]); + BillingPeriod = Null.SetNullInteger(dr["BillingPeriod"]); + BillingFrequency = Null.SetNullString(dr["BillingFrequency"]); + TrialFee = Null.SetNullSingle(dr["TrialFee"]); + TrialPeriod = Null.SetNullInteger(dr["TrialPeriod"]); + TrialFrequency = Null.SetNullString(dr["TrialFrequency"]); + IsPublic = Null.SetNullBoolean(dr["IsPublic"]); + AutoAssignment = Null.SetNullBoolean(dr["AutoAssignment"]); + RSVPCode = Null.SetNullString(dr["RSVPCode"]); + IconFile = Null.SetNullString(dr["IconFile"]); + + //New properties may not be present if called before 6.2 Upgrade has been executed + try + { + int mode = Null.SetNullInteger(dr["SecurityMode"]); + switch (mode) + { + case 0: + SecurityMode = SecurityMode.SecurityRole; + break; + case 1: + SecurityMode = SecurityMode.SocialGroup; + break; + default: + SecurityMode = SecurityMode.Both; + break; + } + + + int status = Null.SetNullInteger(dr["Status"]); + switch (status) + { + case -1: + Status = RoleStatus.Pending; + break; + case 0: + Status = RoleStatus.Disabled; + break; + default: + Status = RoleStatus.Approved; + break; + } + + UserCount = Null.SetNullInteger(dr["UserCount"]); + IsSystemRole = Null.SetNullBoolean(dr["IsSystemRole"]); + } + catch (IndexOutOfRangeException) + { + //do nothing + } + + + //Fill base class fields + FillInternal(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 03/17/2008 Created + /// + /// ----------------------------------------------------------------------------- + public virtual int KeyID + { + get { return RoleID; } + set { RoleID = value; } + } + + #endregion + + #region IPropertyAccess Members + + public CacheLevel Cacheability + { + get { return CacheLevel.fullyCacheable; } + } + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, + Scope accessLevel, ref bool propertyNotFound) + { + string OutputFormat = string.Empty; + if (format == string.Empty) + { + OutputFormat = "g"; + } + else + { + OutputFormat = format; + } + string propName = propertyName.ToLowerInvariant(); + switch (propName) + { + case "roleid": + return PropertyAccess.FormatString(RoleID.ToString(), format); + case "groupid": + return PropertyAccess.FormatString(RoleID.ToString(), format); + case "status": + return PropertyAccess.FormatString(Status.ToString(), format); + case "groupname": + return PropertyAccess.FormatString(RoleName, format); + case "rolename": + return PropertyAccess.FormatString(RoleName, format); + case "groupdescription": + return PropertyAccess.FormatString(Description, format); + case "description": + return PropertyAccess.FormatString(Description, format); + case "usercount": + return PropertyAccess.FormatString(UserCount.ToString(), format); + case "street": + return PropertyAccess.FormatString(GetString("Street", string.Empty), format); + case "city": + return PropertyAccess.FormatString(GetString("City", string.Empty), format); + case "region": + return PropertyAccess.FormatString(GetString("Region", string.Empty), format); + case "country": + return PropertyAccess.FormatString(GetString("Country", string.Empty), format); + case "postalcode": + return PropertyAccess.FormatString(GetString("PostalCode", string.Empty), format); + case "website": + return PropertyAccess.FormatString(GetString("Website", string.Empty), format); + case "datecreated": + return PropertyAccess.FormatString(CreatedOnDate.ToString(), format); + case "photourl": + return PropertyAccess.FormatString(PhotoURL, format); + case "stat_status": + return PropertyAccess.FormatString(GetString("stat_status", string.Empty), format); + case "stat_photo": + return PropertyAccess.FormatString(GetString("stat_photo", string.Empty), format); + case "stat_file": + return PropertyAccess.FormatString(GetString("stat_file", string.Empty), format); + case "url": + return PropertyAccess.FormatString(GetString("URL", string.Empty), format); + case "issystemrole": + return PropertyAccess.Boolean2LocalizedYesNo(IsSystemRole, formatProvider); + case "grouptype": + return IsPublic ? "Public.Text" : "Private.Text"; + case "groupcreatorname": + return PropertyAccess.FormatString(GetString("GroupCreatorName", string.Empty), format); + default: + if (Settings.ContainsKey(propertyName)) + { + return PropertyAccess.FormatString(GetString(propertyName, string.Empty), format); + } + + propertyNotFound = true; + return string.Empty; + } + + + + } + + #endregion + + #region IXmlSerializable Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets an XmlSchema for the RoleInfo + /// + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public XmlSchema GetSchema() + { + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// Reads a RoleInfo from an XmlReader + /// + /// The XmlReader to use + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void ReadXml(XmlReader reader) + { + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.EndElement) + { + break; + } + if (reader.NodeType == XmlNodeType.Whitespace) + { + continue; + } + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name.ToLowerInvariant()) + { + case "rolename": + RoleName = reader.ReadElementContentAsString(); + break; + case "description": + Description = reader.ReadElementContentAsString(); + break; + case "billingfrequency": + BillingFrequency = reader.ReadElementContentAsString(); + if (string.IsNullOrEmpty(BillingFrequency)) + { + BillingFrequency = "N"; + } + break; + case "billingperiod": + BillingPeriod = reader.ReadElementContentAsInt(); + break; + case "servicefee": + ServiceFee = reader.ReadElementContentAsFloat(); + if (ServiceFee < 0) + { + ServiceFee = 0; + } + break; + case "trialfrequency": + TrialFrequency = reader.ReadElementContentAsString(); + if (string.IsNullOrEmpty(TrialFrequency)) + { + TrialFrequency = "N"; + } + break; + case "trialperiod": + TrialPeriod = reader.ReadElementContentAsInt(); + break; + case "trialfee": + TrialFee = reader.ReadElementContentAsFloat(); + if (TrialFee < 0) + { + TrialFee = 0; + } + break; + case "ispublic": + IsPublic = reader.ReadElementContentAsBoolean(); + break; + case "autoassignment": + AutoAssignment = reader.ReadElementContentAsBoolean(); + break; + case "rsvpcode": + RSVPCode = reader.ReadElementContentAsString(); + break; + case "iconfile": + IconFile = reader.ReadElementContentAsString(); + break; + case "issystemrole": + IsSystemRole = reader.ReadElementContentAsBoolean(); + break; + case "roletype": + switch (reader.ReadElementContentAsString()) + { + case "adminrole": + _RoleType = RoleType.Administrator; + break; + case "registeredrole": + _RoleType = RoleType.RegisteredUser; + break; + case "subscriberrole": + _RoleType = RoleType.Subscriber; + break; + case "unverifiedrole": + _RoleType = RoleType.UnverifiedUser; + break; + default: + _RoleType = RoleType.None; + break; + } + _RoleTypeSet = true; + break; + case "securitymode": + switch (reader.ReadElementContentAsString()) + { + case "securityrole": + SecurityMode = SecurityMode.SecurityRole; + break; + case "socialgroup": + SecurityMode = SecurityMode.SocialGroup; + break; + case "both": + SecurityMode = SecurityMode.Both; + break; + } + break; + case "status": + switch (reader.ReadElementContentAsString()) + { + case "pending": + Status = RoleStatus.Pending; + break; + case "disabled": + Status = RoleStatus.Disabled; + break; + default: + Status = RoleStatus.Approved; + break; + } + break; + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Writes a RoleInfo to an XmlWriter + /// + /// The XmlWriter to use + /// + /// [cnurse] 03/14/2008 Created + /// + /// ----------------------------------------------------------------------------- + public void WriteXml(XmlWriter writer) + { + //Write start of main elemenst + writer.WriteStartElement("role"); + + //write out properties + writer.WriteElementString("rolename", RoleName); + writer.WriteElementString("description", Description); + writer.WriteElementString("billingfrequency", BillingFrequency); + writer.WriteElementString("billingperiod", BillingPeriod.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("servicefee", ServiceFee.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("trialfrequency", TrialFrequency); + writer.WriteElementString("trialperiod", TrialPeriod.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("trialfee", TrialFee.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("ispublic", IsPublic.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); + writer.WriteElementString("autoassignment", AutoAssignment.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); + writer.WriteElementString("rsvpcode", RSVPCode); + writer.WriteElementString("iconfile", IconFile); + writer.WriteElementString("issystemrole", IsSystemRole.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); + switch (RoleType) + { + case RoleType.Administrator: + writer.WriteElementString("roletype", "adminrole"); + break; + case RoleType.RegisteredUser: + writer.WriteElementString("roletype", "registeredrole"); + break; + case RoleType.Subscriber: + writer.WriteElementString("roletype", "subscriberrole"); + break; + case RoleType.UnverifiedUser: + writer.WriteElementString("roletype", "unverifiedrole"); + break; + case RoleType.None: + writer.WriteElementString("roletype", "none"); + break; + } + + switch (SecurityMode) + { + case SecurityMode.SecurityRole: + writer.WriteElementString("securitymode", "securityrole"); + break; + case SecurityMode.SocialGroup: + writer.WriteElementString("securitymode", "socialgroup"); + break; + case SecurityMode.Both: + writer.WriteElementString("securitymode", "both"); + break; + } + switch (Status) + { + case RoleStatus.Pending: + writer.WriteElementString("status", "pending"); + break; + case RoleStatus.Disabled: + writer.WriteElementString("status", "disabled"); + break; + case RoleStatus.Approved: + writer.WriteElementString("status", "approved"); + break; + } + + //Write end of main element + writer.WriteEndElement(); + } + + #endregion + + private string GetString(string keyName, string defaultValue) + { + if (Settings == null) + { + return defaultValue; + } + if (Settings.ContainsKey(keyName)) + { + return Settings[keyName]; + } + + return defaultValue; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Roles/RoleProvider.cs b/DNN Platform/Library/Security/Roles/RoleProvider.cs new file mode 100644 index 00000000000..20ed613655f --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleProvider.cs @@ -0,0 +1,208 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles.Internal; + +#endregion + +namespace DotNetNuke.Security.Roles +{ + public abstract class RoleProvider + { + #region Shared/Static Methods + + //return the provider + public static RoleProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region Role Methods + + public virtual bool CreateRole(RoleInfo role) + { + #pragma warning disable 612,618 + + return CreateRole(-1, ref role); + + #pragma warning restore 612,618 + } + + public virtual void DeleteRole(RoleInfo role) + { + #pragma warning disable 612,618 + + DeleteRole(-1, ref role); + + #pragma warning restore 612,618 + } + + public abstract ArrayList GetRoles(int portalId); + + public abstract IList GetRolesBasicSearch(int portalID, int pageSize, string filterBy); + + public virtual IDictionary GetRoleSettings(int roleId) + { + return new Dictionary(); + } + + public abstract void UpdateRole(RoleInfo role); + + public virtual void UpdateRoleSettings(RoleInfo role) + { + + } + + #endregion + + #region RoleGroup Methods + + //Role Groups + public abstract int CreateRoleGroup(RoleGroupInfo roleGroup); + + public abstract void DeleteRoleGroup(RoleGroupInfo roleGroup); + + public abstract RoleGroupInfo GetRoleGroup(int portalId, int roleGroupId); + + public abstract ArrayList GetRoleGroups(int portalId); + + public abstract void UpdateRoleGroup(RoleGroupInfo roleGroup); + + #endregion + + #region UserRole Methods + + public abstract bool AddUserToRole(int portalId, UserInfo user, UserRoleInfo userRole); + + public abstract UserRoleInfo GetUserRole(int PortalId, int UserId, int RoleId); + + public abstract ArrayList GetUserRoles(int portalId, string Username, string Rolename); + + public abstract ArrayList GetUsersByRoleName(int portalId, string roleName); + + public abstract void RemoveUserFromRole(int portalId, UserInfo user, UserRoleInfo userRole); + + public abstract void UpdateUserRole(UserRoleInfo userRole); + + #endregion + + public virtual RoleGroupInfo GetRoleGroupByName(int PortalID, string RoleGroupName) + { + return null; + } + + public virtual IList GetUserRoles(UserInfo user, bool includePrivate) + { +#pragma warning disable 612,618 + //The virtual implmenetations of GetUserRoles(UserInfo, bool) and GetUserRoles(int, int, bool) + //are recursive. A concrete provider will override one of these methods and break the inifinite recursion + return GetUserRoles(user.PortalID, user.UserID, includePrivate).Cast().ToList(); +#pragma warning restore 612,618 + } + + #region Obsolete Methods + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload which takes a single RoleInfo object")] + public virtual bool CreateRole(int portalId, ref RoleInfo role) + { + return CreateRole(role); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload which takes a single RoleInfo object")] + public virtual void DeleteRole(int portalId, ref RoleInfo role) + { + DeleteRole(role); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Roles are cached in the business layer")] + public virtual RoleInfo GetRole(int portalId, int roleId) + { + return GetRoles(portalId).Cast().SingleOrDefault(r => r.RoleID == roleId); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Roles are cached in the business layer")] + public virtual RoleInfo GetRole(int portalId, string roleName) + { + return GetRoles(portalId).Cast().SingleOrDefault(r => r.RoleName == roleName); + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public virtual string[] GetRoleNames(int portalId) + { + string[] roles = { }; + var roleList = TestableRoleController.Instance.GetRoles(portalId, r => r.SecurityMode != SecurityMode.SocialGroup && r.Status == RoleStatus.Approved); + var strRoles = roleList.Aggregate("", (current, role) => current + (role.RoleName + "|")); + if (strRoles.IndexOf("|", StringComparison.Ordinal) > 0) + { + roles = strRoles.Substring(0, strRoles.Length - 1).Split('|'); + } + return roles; + } + + [Obsolete("Deprecated in DotNetNuke 6.2.")] + public virtual string[] GetRoleNames(int portalId, int userId) + { + return UserController.GetUserById(portalId, userId).Roles; + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Roles are cached in the business layer")] + public virtual ArrayList GetRolesByGroup(int portalId, int roleGroupId) + { + return new ArrayList(GetRoles(portalId).Cast().Where(r => r.RoleGroupID == roleGroupId).ToArray()); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by overload that returns IList")] + public virtual ArrayList GetUserRoles(int portalId, int userId, bool includePrivate) + { + UserInfo user; + if(userId != -1) + { + var userController = new UserController(); + user = userController.GetUser(portalId, userId); + } + else + { + user = new UserInfo() {UserID = -1, PortalID = portalId}; + } + + return new ArrayList(GetUserRoles(user, includePrivate).ToArray()); + } + + [Obsolete("Deprecated in DotNetNuke 6.2. Replaced by GetUserRoles overload that returns IList")] + public virtual ArrayList GetUserRolesByRoleName(int portalId, string roleName) + { + return GetUserRoles(portalId, null, roleName); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Roles/RoleStatus.cs b/DNN Platform/Library/Security/Roles/RoleStatus.cs new file mode 100644 index 00000000000..9fe98918163 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleStatus.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Security.Roles +{ + public enum RoleStatus + { + Pending = -1, + Disabled = 0, + Approved = 1 + } +} diff --git a/DNN Platform/Library/Security/Roles/RoleType.cs b/DNN Platform/Library/Security/Roles/RoleType.cs new file mode 100644 index 00000000000..793d7ee3526 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/RoleType.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +namespace DotNetNuke.Security.Roles +{ + public enum RoleType + { + Administrator, + Subscriber, + RegisteredUser, + None, + UnverifiedUser + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Security/Roles/SecurityMode.cs b/DNN Platform/Library/Security/Roles/SecurityMode.cs new file mode 100644 index 00000000000..dca14590980 --- /dev/null +++ b/DNN Platform/Library/Security/Roles/SecurityMode.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Security.Roles +{ + public enum SecurityMode + { + SecurityRole = 0, + SocialGroup = 1, + Both = 2 + } +} diff --git a/DNN Platform/Library/Security/SecurityAccessLevel.cs b/DNN Platform/Library/Security/SecurityAccessLevel.cs new file mode 100644 index 00000000000..4043d94a5ec --- /dev/null +++ b/DNN Platform/Library/Security/SecurityAccessLevel.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Security +{ + ///----------------------------------------------------------------------------- + /// + /// The SecurityAccessLevel enum is used to determine which level of access rights + /// to assign to a specific module or module action. + /// + ///----------------------------------------------------------------------------- + public enum SecurityAccessLevel + { + ControlPanel = -3, + SkinObject = -2, + Anonymous = -1, + View = 0, + Edit = 1, + Admin = 2, + Host = 3, + ViewPermissions = 4 + } +} diff --git a/DNN Platform/Library/Services/Analytics/AnalyticsEngineBase.cs b/DNN Platform/Library/Services/Analytics/AnalyticsEngineBase.cs new file mode 100644 index 00000000000..c141dcc859f --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/AnalyticsEngineBase.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Analytics.Config; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Services.Analytics +{ + public abstract class AnalyticsEngineBase + { + public abstract string EngineName { get; } + + public abstract string RenderScript(string scriptTemplate); + + public string ReplaceTokens(string s) + { + var tokenizer = new TokenReplace(); + tokenizer.AccessingUser = UserController.GetCurrentUserInfo(); + tokenizer.DebugMessages = false; + return (tokenizer.ReplaceEnvironmentTokens(s)); + } + + public AnalyticsConfiguration GetConfig() + { + return AnalyticsConfiguration.GetConfig(EngineName); + } + + public virtual string RenderCustomScript(AnalyticsConfiguration config) + { + return ""; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/Config/AnalyticsConfiguration.cs b/DNN Platform/Library/Services/Analytics/Config/AnalyticsConfiguration.cs new file mode 100644 index 00000000000..e81c400302a --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/Config/AnalyticsConfiguration.cs @@ -0,0 +1,194 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Xml.Serialization; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Analytics.Config +{ + [Serializable, XmlRoot("AnalyticsConfig")] + public class AnalyticsConfiguration + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AnalyticsConfiguration)); + #region "Private Members" + + private AnalyticsRuleCollection _rules; + private AnalyticsSettingCollection _settings; + + #endregion + + #region "Public Properties" + + public AnalyticsSettingCollection Settings + { + get + { + return _settings; + } + set + { + _settings = value; + } + } + + public AnalyticsRuleCollection Rules + { + get + { + return _rules; + } + set + { + _rules = value; + } + } + + #endregion + + #region "Shared Methods" + + public static AnalyticsConfiguration GetConfig(string analyticsEngineName) + { + string cacheKey = analyticsEngineName + "." + PortalSettings.Current.PortalId; + + var Config = new AnalyticsConfiguration(); + Config.Rules = new AnalyticsRuleCollection(); + Config.Settings = new AnalyticsSettingCollection(); + + FileStream fileReader = null; + string filePath = ""; + try + { + Config = (AnalyticsConfiguration) DataCache.GetCache(cacheKey); + if ((Config == null)) + { + filePath = PortalSettings.Current.HomeDirectoryMapPath + "\\" + analyticsEngineName + ".config"; + + if (!File.Exists(filePath)) + { + return null; + } + + //Create a FileStream for the Config file + fileReader = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + + var doc = new XPathDocument(fileReader); + Config = new AnalyticsConfiguration(); + Config.Rules = new AnalyticsRuleCollection(); + Config.Settings = new AnalyticsSettingCollection(); + + var allSettings = new Hashtable(); + foreach (XPathNavigator nav in doc.CreateNavigator().Select("AnalyticsConfig/Settings/AnalyticsSetting")) + { + var setting = new AnalyticsSetting(); + setting.SettingName = nav.SelectSingleNode("SettingName").Value; + setting.SettingValue = nav.SelectSingleNode("SettingValue").Value; + Config.Settings.Add(setting); + } + foreach (XPathNavigator nav in doc.CreateNavigator().Select("AnalyticsConfig/Rules/AnalyticsRule")) + { + var rule = new AnalyticsRule(); + rule.RoleId = Convert.ToInt32(nav.SelectSingleNode("RoleId").Value); + rule.TabId = Convert.ToInt32(nav.SelectSingleNode("TabId").Value); + rule.Label = nav.SelectSingleNode("Label").Value; + var valueNode = nav.SelectSingleNode("Value"); + if (valueNode != null) + { + rule.Value = valueNode.Value; + } + Config.Rules.Add(rule); + } + if (File.Exists(filePath)) + { + //Set back into Cache + DataCache.SetCache(cacheKey, Config, new DNNCacheDependency(filePath)); + } + } + } + catch (Exception ex) + { + //log it + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("Analytics.AnalyticsConfiguration", "GetConfig Failed"); + objEventLogInfo.AddProperty("FilePath", filePath); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.ADMIN_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + Logger.Error(ex); + + } + finally + { + if (fileReader != null) + { + //Close the Reader + fileReader.Close(); + } + } + return Config; + } + + public static void SaveConfig(string analyticsEngineName, AnalyticsConfiguration config) + { + string cacheKey = analyticsEngineName + "." + PortalSettings.Current.PortalId; + if (config.Settings != null) + { + //Create a new Xml Serializer + var ser = new XmlSerializer(typeof (AnalyticsConfiguration)); + string filePath = ""; + + //Create a FileStream for the Config file + filePath = PortalSettings.Current.HomeDirectoryMapPath + "\\" + analyticsEngineName + ".config"; + if (File.Exists(filePath)) + { + File.SetAttributes(filePath, FileAttributes.Normal); + } + var fileWriter = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write); + + //Open up the file to serialize + var writer = new StreamWriter(fileWriter); + + //Serialize the AnalyticsConfiguration + ser.Serialize(writer, config); + + //Close the Writers + writer.Close(); + fileWriter.Close(); + DataCache.SetCache(cacheKey, config, new DNNCacheDependency(filePath)); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/Config/AnalyticsRule.cs b/DNN Platform/Library/Services/Analytics/Config/AnalyticsRule.cs new file mode 100644 index 00000000000..1e43533e11d --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/Config/AnalyticsRule.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Analytics.Config +{ + [Serializable] + public class AnalyticsRule + { + private string _label; + private int _roleId; + private int _tabId; + + public int RoleId + { + get + { + return _roleId; + } + set + { + _roleId = value; + } + } + + public int TabId + { + get + { + return _tabId; + } + set + { + _tabId = value; + } + } + + public string Label + { + get + { + return _label; + } + set + { + _label = value; + } + } + + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/Config/AnalyticsRuleCollection.cs b/DNN Platform/Library/Services/Analytics/Config/AnalyticsRuleCollection.cs new file mode 100644 index 00000000000..ab18fef89da --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/Config/AnalyticsRuleCollection.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Analytics.Config +{ + [Serializable] + public class AnalyticsRuleCollection : CollectionBase + { + public virtual AnalyticsRule this[int index] + { + get + { + return (AnalyticsRule) base.List[index]; + } + set + { + base.List[index] = value; + } + } + + public void Add(AnalyticsRule r) + { + InnerList.Add(r); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/Config/AnalyticsSetting.cs b/DNN Platform/Library/Services/Analytics/Config/AnalyticsSetting.cs new file mode 100644 index 00000000000..f1734088735 --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/Config/AnalyticsSetting.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Analytics.Config +{ + [Serializable] + public class AnalyticsSetting + { + private string _settingName; + private string _settingValue; + + public string SettingName + { + get + { + return _settingName; + } + set + { + _settingName = value; + } + } + + public string SettingValue + { + get + { + return _settingValue; + } + set + { + _settingValue = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/Config/AnalyticsSettingCollection.cs b/DNN Platform/Library/Services/Analytics/Config/AnalyticsSettingCollection.cs new file mode 100644 index 00000000000..bda7d0bc0b1 --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/Config/AnalyticsSettingCollection.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Analytics.Config +{ + [Serializable] + public class AnalyticsSettingCollection : CollectionBase + { + public virtual AnalyticsSetting this[int index] + { + get + { + return (AnalyticsSetting) base.List[index]; + } + set + { + base.List[index] = value; + } + } + + public void Add(AnalyticsSetting r) + { + InnerList.Add(r); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/GenericAnalyticsEngine.cs b/DNN Platform/Library/Services/Analytics/GenericAnalyticsEngine.cs new file mode 100644 index 00000000000..38ee1fd7419 --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/GenericAnalyticsEngine.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Analytics +{ + public class GenericAnalyticsEngine : AnalyticsEngineBase + { + public override string EngineName + { + get + { + return "GenericAnalytics"; + } + } + + public override string RenderScript(string scriptTemplate) + { + return ReplaceTokens(scriptTemplate); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/GoogleAnalyticsController.cs b/DNN Platform/Library/Services/Analytics/GoogleAnalyticsController.cs new file mode 100644 index 00000000000..56631234edb --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/GoogleAnalyticsController.cs @@ -0,0 +1,142 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Analytics +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Analytics + /// Module: GoogleAnalytics + /// ----------------------------------------------------------------------------- + /// + /// Controller class definition for GoogleAnalytics which handles upgrades + /// + /// + /// + /// + /// [vnguyen] 10/08/2010 Created + /// + /// ----------------------------------------------------------------------------- + public class GoogleAnalyticsController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (GoogleAnalyticsController)); + /// ----------------------------------------------------------------------------- + /// + /// Handles module upgrades includes a new Google Analytics Asychronous script. + /// + /// + /// + /// + /// + /// [vnguyen] 10/08/2010 Created + /// + /// ----------------------------------------------------------------------------- + public void UpgradeModule(string Version) + { + // MD5 Hash value of the old synchronous script config file (from previous module versions) + string[] TRADITIONAL_FILEHASHES = {"aRUf9NsElvrpiASJHHlmZg==", "+R2k5mvFvVhWsCm4WinyAA=="}; + + switch (Version) + { + case "05.06.00": + //previous module versions + StreamReader fileReader = GetConfigFile(); + + if (fileReader != null) + { + var fileEncoding = new ASCIIEncoding(); + var md5 = new MD5CryptoServiceProvider(); + string currFileHashValue = ""; + + //calculate md5 hash of existing file + currFileHashValue = Convert.ToBase64String(md5.ComputeHash(fileEncoding.GetBytes(fileReader.ReadToEnd()))); + fileReader.Close(); + + IEnumerable result = (from h in TRADITIONAL_FILEHASHES where h == currFileHashValue select h); + + //compare md5 hash + if (result.Count() > 0) + { + //Copy new config file from \Config + //True causes .config to be overwritten + Common.Utilities.Config.GetPathToFile(Common.Utilities.Config.ConfigFileType.SiteAnalytics, true); + } + } + break; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Retrieves the Google Analytics config file, "SiteAnalytics.config". + /// + /// + /// + /// + /// + /// [vnguyen] 10/08/2010 Created + /// + /// ----------------------------------------------------------------------------- + private StreamReader GetConfigFile() + { + StreamReader fileReader = null; + string filePath = ""; + try + { + filePath = Globals.ApplicationMapPath + "\\SiteAnalytics.config"; + + if (File.Exists(filePath)) + { + fileReader = new StreamReader(filePath); + } + } + catch (Exception ex) + { + //log it + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("GoogleAnalytics.UpgradeModule", "GetConfigFile Failed"); + objEventLogInfo.AddProperty("FilePath", filePath); + objEventLogInfo.AddProperty("ExceptionMessage", ex.Message); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + fileReader.Close(); + Logger.Error(ex); + + } + + return fileReader; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Analytics/GoogleAnalyticsEngine.cs b/DNN Platform/Library/Services/Analytics/GoogleAnalyticsEngine.cs new file mode 100644 index 00000000000..af511e91542 --- /dev/null +++ b/DNN Platform/Library/Services/Analytics/GoogleAnalyticsEngine.cs @@ -0,0 +1,79 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Analytics.Config; + +#endregion + +namespace DotNetNuke.Services.Analytics +{ + public class GoogleAnalyticsEngine : AnalyticsEngineBase + { + public override string EngineName + { + get + { + return "GoogleAnalytics"; + } + } + + public override string RenderScript(string scriptTemplate) + { + AnalyticsConfiguration config = GetConfig(); + if (config == null) + { + return ""; + } + string trackingId = ""; + string urlParameter = ""; + foreach (AnalyticsSetting setting in config.Settings) + { + switch (setting.SettingName.ToLower()) + { + case "trackingid": + trackingId = setting.SettingValue; + break; + case "urlparameter": + urlParameter = setting.SettingValue; + break; + } + } + if (String.IsNullOrEmpty(trackingId)) + { + return ""; + } + scriptTemplate = scriptTemplate.Replace("[TRACKING_ID]", trackingId); + if ((!String.IsNullOrEmpty(urlParameter))) + { + scriptTemplate = scriptTemplate.Replace("[PAGE_URL]", urlParameter); + } + else + { + scriptTemplate = scriptTemplate.Replace("[PAGE_URL]", ""); + } + scriptTemplate = scriptTemplate.Replace("[CUSTOM_SCRIPT]", RenderCustomScript(config)); + return scriptTemplate; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/AuthMode.cs b/DNN Platform/Library/Services/Authentication/AuthMode.cs new file mode 100644 index 00000000000..9bbbd818f1c --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthMode.cs @@ -0,0 +1,31 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + public enum AuthMode + { + Login = 0, + Register = 1 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationConfig.cs b/DNN Platform/Library/Services/Authentication/AuthenticationConfig.cs new file mode 100644 index 00000000000..befa3efcc43 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationConfig.cs @@ -0,0 +1,97 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationConfig class providesa configuration class for the DNN + /// Authentication provider + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class AuthenticationConfig : AuthenticationConfigBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AuthenticationConfig)); + private const string CACHEKEY = "Authentication.DNN"; + + protected AuthenticationConfig(int portalID) : base(portalID) + { + UseCaptcha = Null.NullBoolean; + Enabled = true; + try + { + string setting = Null.NullString; + if (PortalController.GetPortalSettingsDictionary(portalID).TryGetValue("DNN_Enabled", out setting)) + { + Enabled = bool.Parse(setting); + } + setting = Null.NullString; + if (PortalController.GetPortalSettingsDictionary(portalID).TryGetValue("DNN_UseCaptcha", out setting)) + { + UseCaptcha = bool.Parse(setting); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + public bool Enabled { get; set; } + + public bool UseCaptcha { get; set; } + + public static void ClearConfig(int portalId) + { + string key = CACHEKEY + "_" + portalId; + DataCache.RemoveCache(key); + } + + public static AuthenticationConfig GetConfig(int portalId) + { + string key = CACHEKEY + "_" + portalId; + var config = (AuthenticationConfig) DataCache.GetCache(key); + if (config == null) + { + config = new AuthenticationConfig(portalId); + DataCache.SetCache(key, config); + } + return config; + } + + public static void UpdateConfig(AuthenticationConfig config) + { + PortalController.UpdatePortalSetting(config.PortalID, "DNN_Enabled", config.Enabled.ToString()); + PortalController.UpdatePortalSetting(config.PortalID, "DNN_UseCaptcha", config.UseCaptcha.ToString()); + ClearConfig(config.PortalID); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationConfigBase.cs b/DNN Platform/Library/Services/Authentication/AuthenticationConfigBase.cs new file mode 100644 index 00000000000..7576798123f --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationConfigBase.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationConfigBase class provides base configuration class for the + /// Authentication providers + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public abstract class AuthenticationConfigBase + { + protected AuthenticationConfigBase(int portalID) + { + PortalID = portalID; + } + + [Browsable(false)] + public int PortalID { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationController.cs b/DNN Platform/Library/Services/Authentication/AuthenticationController.cs new file mode 100644 index 00000000000..98682750bf6 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationController.cs @@ -0,0 +1,403 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationController class provides the Business Layer for the + /// Authentication Systems. + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public class AuthenticationController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (AuthenticationController)); + #region "Private Members" + + private static readonly DataProvider provider = DataProvider.Instance(); + + #endregion + + #region "Private Shared Methods" + + private static object GetAuthenticationServicesCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillCollection(provider.GetAuthenticationServices()); + } + + #endregion + + #region "Public Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// AddAuthentication adds a new Authentication System to the Data Store. + /// + /// The new Authentication System to add + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static int AddAuthentication(AuthenticationInfo authSystem) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog(authSystem, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.AUTHENTICATION_CREATED); + return provider.AddAuthentication(authSystem.PackageID, + authSystem.AuthenticationType, + authSystem.IsEnabled, + authSystem.SettingsControlSrc, + authSystem.LoginControlSrc, + authSystem.LogoffControlSrc, + UserController.GetCurrentUserInfo().UserID); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddUserAuthentication adds a new UserAuthentication to the User. + /// + /// The new Authentication System to add + /// The authentication type + /// The authentication token + /// + /// [cnurse] 07/12/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static int AddUserAuthentication(int userID, string authenticationType, string authenticationToken) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("userID/authenticationType", + userID + "/" + authenticationType, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.AUTHENTICATION_USER_CREATED); + return provider.AddUserAuthentication(userID, authenticationType, authenticationToken, UserController.GetCurrentUserInfo().UserID); + } + + public static void DeleteAuthentication(AuthenticationInfo authSystem) + { + provider.DeleteAuthentication(authSystem.AuthenticationID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(authSystem, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.AUTHENTICATION_DELETED); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAuthenticationService fetches a single Authentication Systems + /// + /// The ID of the Authentication System + /// An AuthenticationInfo object + /// + /// [cnurse] 07/31/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static AuthenticationInfo GetAuthenticationService(int authenticationID) + { + AuthenticationInfo authInfo = null; + foreach (AuthenticationInfo authService in GetAuthenticationServices()) + { + if (authService.AuthenticationID == authenticationID) + { + authInfo = authService; + break; + } + } + if (authInfo == null) + { + //Go to database + return CBO.FillObject(provider.GetAuthenticationService(authenticationID)); + } + return authInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAuthenticationServiceByPackageID fetches a single Authentication System + /// + /// The id of the Package + /// An AuthenticationInfo object + /// + /// [cnurse] 07/31/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static AuthenticationInfo GetAuthenticationServiceByPackageID(int packageID) + { + AuthenticationInfo authInfo = null; + foreach (AuthenticationInfo authService in GetAuthenticationServices()) + { + if (authService.PackageID == packageID) + { + authInfo = authService; + break; + } + } + if (authInfo == null) + { + //Go to database + return CBO.FillObject(provider.GetAuthenticationServiceByPackageID(packageID)); + } + return authInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAuthenticationServiceByType fetches a single Authentication Systems + /// + /// The type of the Authentication System + /// An AuthenticationInfo object + /// + /// [cnurse] 07/31/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static AuthenticationInfo GetAuthenticationServiceByType(string authenticationType) + { + AuthenticationInfo authInfo = null; + foreach (AuthenticationInfo authService in GetAuthenticationServices()) + { + if (authService.AuthenticationType == authenticationType) + { + authInfo = authService; + break; + } + } + if (authInfo == null) + { + //Go to database + return CBO.FillObject(provider.GetAuthenticationServiceByType(authenticationType)); + } + return authInfo; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAuthenticationServices fetches a list of all the Authentication Systems + /// installed in the system + /// + /// A List of AuthenticationInfo objects + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static List GetAuthenticationServices() + { + return + CBO.GetCachedObject>( + new CacheItemArgs(DataCache.AuthenticationServicesCacheKey, DataCache.AuthenticationServicesCacheTimeOut, DataCache.AuthenticationServicesCachePriority), + GetAuthenticationServicesCallBack); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAuthenticationType fetches the authentication method used by the currently logged on user + /// + /// An AuthenticationInfo object + /// + /// [cnurse] 07/23/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static AuthenticationInfo GetAuthenticationType() + { + AuthenticationInfo objAuthentication = null; + if (HttpContext.Current != null && HttpContext.Current.Request != null) + { + try + { + objAuthentication = GetAuthenticationServiceByType(HttpContext.Current.Request["authentication"]); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + return objAuthentication; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetEnabledAuthenticationServices fetches a list of all the Authentication Systems + /// installed in the system that have been enabled by the Host user + /// + /// A List of AuthenticationInfo objects + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static List GetEnabledAuthenticationServices() + { + var enabled = new List(); + foreach (AuthenticationInfo authService in GetAuthenticationServices()) + { + if (authService.IsEnabled) + { + enabled.Add(authService); + } + } + return enabled; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetLogoffRedirectURL fetches the url to redirect too after logoff + /// + /// A PortalSettings object + /// The current Request + /// The Url + /// + /// [cnurse] 08/15/2007 Created + /// [cnurse] 02/28/2008 DNN-6881 Logoff redirect + /// + /// ----------------------------------------------------------------------------- + public static string GetLogoffRedirectURL(PortalSettings settings, HttpRequest request) + { + string _RedirectURL = ""; + object setting = UserModuleBase.GetSetting(settings.PortalId, "Redirect_AfterLogout"); + if (Convert.ToInt32(setting) == Null.NullInteger) + { + if (TabPermissionController.CanViewPage()) + { + //redirect to current page + _RedirectURL = Globals.NavigateURL(settings.ActiveTab.TabID); + } + else if (settings.HomeTabId != -1) + { + //redirect to portal home page specified + _RedirectURL = Globals.NavigateURL(settings.HomeTabId); + } + else //redirect to default portal root + { + _RedirectURL = Globals.GetPortalDomainName(settings.PortalAlias.HTTPAlias, request, true) + "/" + Globals.glbDefaultPage; + } + } + else //redirect to after logout page + { + _RedirectURL = Globals.NavigateURL(Convert.ToInt32(setting)); + } + return _RedirectURL; + } + + /// ----------------------------------------------------------------------------- + /// + /// SetAuthenticationType sets the authentication method used by the currently logged on user + /// + /// The Authentication type + /// + /// [cnurse] 07/23/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void SetAuthenticationType(string value) + { + SetAuthenticationType(value, false); + } + + public static void SetAuthenticationType(string value, bool CreatePersistentCookie) + { + try + { + int PersistentCookieTimeout = Config.GetPersistentCookieTimeout(); + HttpResponse Response = HttpContext.Current.Response; + if (Response == null) + { + return; + } + + //save the authenticationmethod as a cookie + HttpCookie cookie = null; + cookie = Response.Cookies.Get("authentication"); + if ((cookie == null)) + { + if (!String.IsNullOrEmpty(value)) + { + cookie = new HttpCookie("authentication", value); + if (CreatePersistentCookie) + { + cookie.Expires = DateTime.Now.AddMinutes(PersistentCookieTimeout); + } + Response.Cookies.Add(cookie); + } + } + else + { + cookie.Value = value; + if (!String.IsNullOrEmpty(value)) + { + if (CreatePersistentCookie) + { + cookie.Expires = DateTime.Now.AddMinutes(PersistentCookieTimeout); + } + Response.Cookies.Set(cookie); + } + else + { + Response.Cookies.Remove("authentication"); + } + } + } + catch + { + return; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateAuthentication updates an existing Authentication System in the Data Store. + /// + /// The new Authentication System to update + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static void UpdateAuthentication(AuthenticationInfo authSystem) + { + provider.UpdateAuthentication(authSystem.AuthenticationID, + authSystem.PackageID, + authSystem.AuthenticationType, + authSystem.IsEnabled, + authSystem.SettingsControlSrc, + authSystem.LoginControlSrc, + authSystem.LogoffControlSrc, + UserController.GetCurrentUserInfo().UserID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(authSystem, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.AUTHENTICATION_UPDATED); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationInfo.cs b/DNN Platform/Library/Services/Authentication/AuthenticationInfo.cs new file mode 100644 index 00000000000..31e10f325bf --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationInfo.cs @@ -0,0 +1,152 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationInfo class provides the Entity Layer for the + /// Authentication Systems. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class AuthenticationInfo : BaseEntityInfo, IHydratable + { + #region Private Members + + public AuthenticationInfo() + { + LogoffControlSrc = Null.NullString; + LoginControlSrc = Null.NullString; + SettingsControlSrc = Null.NullString; + AuthenticationType = Null.NullString; + AuthenticationID = Null.NullInteger; + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the ID of the Authentication System + /// + /// ----------------------------------------------------------------------------- + public int AuthenticationID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the PackageID for the Authentication System + /// + /// ----------------------------------------------------------------------------- + public int PackageID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets a flag that determines whether the Authentication System is enabled + /// + /// ----------------------------------------------------------------------------- + public bool IsEnabled { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the type (name) of the Authentication System (eg DNN, OpenID, LiveID) + /// + /// ----------------------------------------------------------------------------- + public string AuthenticationType { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the url for the Settings Control + /// + /// ----------------------------------------------------------------------------- + public string SettingsControlSrc { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the url for the Login Control + /// + /// ----------------------------------------------------------------------------- + public string LoginControlSrc { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the url for the Logoff Control + /// + /// ----------------------------------------------------------------------------- + public string LogoffControlSrc { get; set; } + + #endregion + + #region IHydratable Members + + /// ----------------------------------------------------------------------------- + /// + /// Fills a RoleInfo from a Data Reader + /// + /// The Data Reader to use + /// ----------------------------------------------------------------------------- + public virtual void Fill(IDataReader dr) + { + AuthenticationID = Null.SetNullInteger(dr["AuthenticationID"]); + PackageID = Null.SetNullInteger(dr["PackageID"]); + IsEnabled = Null.SetNullBoolean(dr["IsEnabled"]); + AuthenticationType = Null.SetNullString(dr["AuthenticationType"]); + SettingsControlSrc = Null.SetNullString(dr["SettingsControlSrc"]); + LoginControlSrc = Null.SetNullString(dr["LoginControlSrc"]); + LogoffControlSrc = Null.SetNullString(dr["LogoffControlSrc"]); + + //Fill base class fields + FillInternal(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// ----------------------------------------------------------------------------- + public virtual int KeyID + { + get + { + return AuthenticationID; + } + set + { + AuthenticationID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationLoginBase.cs b/DNN Platform/Library/Services/Authentication/AuthenticationLoginBase.cs new file mode 100644 index 00000000000..10d1e2da73e --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationLoginBase.cs @@ -0,0 +1,124 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationLoginBase class provides a bas class for Authentiication + /// Login controls + /// + /// ----------------------------------------------------------------------------- + public abstract class AuthenticationLoginBase : UserModuleBase + { + #region Delegates + + public delegate void UserAuthenticatedEventHandler(object sender, UserAuthenticatedEventArgs e); + + #endregion + + protected AuthenticationLoginBase() + { + RedirectURL = Null.NullString; + AuthenticationType = Null.NullString; + Mode = AuthMode.Login; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Type of Authentication associated with this control + /// + /// ----------------------------------------------------------------------------- + public string AuthenticationType { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the control is Enabled + /// + /// This property must be overriden in the inherited class + /// ----------------------------------------------------------------------------- + public abstract bool Enabled { get; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the IP address associated with the request + /// + /// ----------------------------------------------------------------------------- + public string IPAddress + { + get + { + return GetIPAddress(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Authentication mode of the control (Login or Register) + /// + /// This property may be overriden in the inherited class + /// ----------------------------------------------------------------------------- + public virtual AuthMode Mode { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Redirect Url for this control + /// + /// ----------------------------------------------------------------------------- + public string RedirectURL { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the control supports Registration + /// + /// This property may be overriden in the inherited class + /// ----------------------------------------------------------------------------- + public virtual bool SupportsRegistration { get { return false; } } + + public event UserAuthenticatedEventHandler UserAuthenticated; + + protected virtual void OnUserAuthenticated(UserAuthenticatedEventArgs ea) + { + if (UserAuthenticated != null) + { + UserAuthenticated(null, ea); + } + } + + public static string GetIPAddress() + { + string _IPAddress = Null.NullString; + if (HttpContext.Current.Request.UserHostAddress != null) + { + _IPAddress = HttpContext.Current.Request.UserHostAddress; + } + return _IPAddress; + } + } +} diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationLogoffBase.cs b/DNN Platform/Library/Services/Authentication/AuthenticationLogoffBase.cs new file mode 100644 index 00000000000..42b0f5afecc --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationLogoffBase.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationLogoffBase class provides a base class for Authentiication + /// Logoff controls + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public abstract class AuthenticationLogoffBase : UserModuleBase + { + private string _AuthenticationType = Null.NullString; + private string _RedirectURL = Null.NullString; + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Type of Authentication associated with this control + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string AuthenticationType + { + get + { + return _AuthenticationType; + } + set + { + _AuthenticationType = value; + } + } + + public event EventHandler LogOff; + public event EventHandler Redirect; + + protected virtual void OnLogOff(EventArgs a) + { + if (LogOff != null) + { + LogOff(null, a); + } + } + + protected virtual void OnRedirect(EventArgs a) + { + if (Redirect != null) + { + Redirect(null, a); + } + } + } +} diff --git a/DNN Platform/Library/Services/Authentication/AuthenticationSettingsBase.cs b/DNN Platform/Library/Services/Authentication/AuthenticationSettingsBase.cs new file mode 100644 index 00000000000..b4b9c2ca8df --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/AuthenticationSettingsBase.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationSettingsBase class provides a base class for Authentiication + /// Settings controls + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public abstract class AuthenticationSettingsBase : PortalModuleBase + { + private string _AuthenticationType = Null.NullString; + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Type of Authentication associated with this control + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public string AuthenticationType + { + get + { + return _AuthenticationType; + } + set + { + _AuthenticationType = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// UpdateSettings updates the settings in the Data Store + /// + /// This method must be overriden in the inherited class + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public abstract void UpdateSettings(); + } +} diff --git a/DNN Platform/Library/Services/Authentication/LogOffHandler.cs b/DNN Platform/Library/Services/Authentication/LogOffHandler.cs new file mode 100644 index 00000000000..e17999b7037 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/LogOffHandler.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web; + +using DotNetNuke.Common; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The LogOffHandler class provides a replacement for the LogOff page + /// + /// + /// [cnurse] 10/26/2007 Created + /// + /// ----------------------------------------------------------------------------- + public class LogOffHandler : IHttpHandler + { + #region IHttpHandler Members + + public bool IsReusable + { + get + { + return true; + } + } + + public void ProcessRequest(HttpContext context) + { + context.Response.Redirect(Globals.NavigateURL("LogOff")); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Authentication/OAuth/AuthExtensions.cs b/DNN Platform/Library/Services/Authentication/OAuth/AuthExtensions.cs new file mode 100644 index 00000000000..7e5f5dc78b0 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/AuthExtensions.cs @@ -0,0 +1,69 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.Text; + +namespace DotNetNuke.Services.Authentication.OAuth +{ + internal static class AuthExtensions + { + public static string ToAuthorizationString(this IList parameters) + { + var sb = new StringBuilder(); + sb.Append("OAuth "); + + for (int i = 0; i < parameters.Count; i++) + { + string format = "{0}=\"{1}\""; + + QueryParameter p = parameters[i]; + sb.AppendFormat(format, OAuthClientBase.UrlEncode(p.Name), OAuthClientBase.UrlEncode(p.Value)); + + if (i < parameters.Count - 1) + { + sb.Append(", "); + } + } + + return sb.ToString(); + } + + public static string ToNormalizedString(this IList parameters) + { + var sb = new StringBuilder(); + for (int i = 0; i < parameters.Count; i++) + { + QueryParameter p = parameters[i]; + sb.AppendFormat("{0}={1}", p.Name, p.Value); + + if (i < parameters.Count - 1) + { + sb.Append("&"); + } + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/AuthorisationResult.cs b/DNN Platform/Library/Services/Authentication/OAuth/AuthorisationResult.cs new file mode 100644 index 00000000000..c7b649f0d18 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/AuthorisationResult.cs @@ -0,0 +1,32 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + public enum AuthorisationResult + { + Denied, + Authorized, + RequestingCode + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/HttpMethod.cs b/DNN Platform/Library/Services/Authentication/OAuth/HttpMethod.cs new file mode 100644 index 00000000000..1aefe2e50c7 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/HttpMethod.cs @@ -0,0 +1,33 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + public enum HttpMethod + { + GET, + POST, + PUT, + DELETE + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/OAuthClientBase.cs b/DNN Platform/Library/Services/Authentication/OAuth/OAuthClientBase.cs new file mode 100644 index 00000000000..07b7726cb9e --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/OAuthClientBase.cs @@ -0,0 +1,738 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//Based on the work of: + +// Base oAuth Class for Twitter and LinkedIn +// Author: Eran Sandler +// Code Url: http://oauth.net/code/ +// Author Url: http://eran.sandler.co.il/ +// +// Some modifications by Shannon Whitley +// Author Url: http://voiceoftech.com/ + +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Membership; + +using System.Collections.Specialized; + +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.Authentication.OAuth +{ + public abstract class OAuthClientBase + { + #region Private Members + + private const string HMACSHA1SignatureType = "HMAC-SHA1"; + + //oAuth 1 + private const string OAuthParameterPrefix = "oauth_"; + private const string OAuthConsumerKeyKey = "oauth_consumer_key"; + private const string OAuthCallbackKey = "oauth_callback"; + private const string OAuthVersionKey = "oauth_version"; + private const string OAuthSignatureKey = "oauth_signature"; + private const string OAuthSignatureMethodKey = "oauth_signature_method"; + private const string OAuthTimestampKey = "oauth_timestamp"; + private const string OAuthNonceKey = "oauth_nonce"; + private const string OAuthTokenSecretKey = "oauth_token_secret"; + private const string OAuthVerifierKey = "oauth_verifier"; + private const string OAuthCallbackConfirmedKey = "oauth_callback_confirmed"; + + //oAuth 2 + private const string OAuthClientIdKey = "client_id"; + private const string OAuthClientSecretKey = "client_secret"; + private const string OAuthRedirectUriKey = "redirect_uri"; + private const string OAuthGrantTyepKey = "grant_type"; + private const string OAuthCodeKey = "code"; + + private readonly Random random = new Random(); + + private const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; + + #endregion + + protected OAuthClientBase(int portalId, AuthMode mode, string service) + { + //Set default Expiry to 14 days + //oAuth v1 tokens do not expire + //oAuth v2 tokens have an expiry + AuthTokenExpiry = new TimeSpan(14, 0, 0, 0); + Service = service; + + APIKey = OAuthConfigBase.GetConfig(Service, portalId).APIKey; + APISecret = OAuthConfigBase.GetConfig(Service, portalId).APISecret; + Mode = mode; + + CallbackUri = Mode == AuthMode.Login + ? new Uri(Globals.LoginURL(String.Empty, false)) + : new Uri(Globals.RegisterURL(String.Empty, String.Empty)); + } + + #region Protected Properties + + protected const string OAuthTokenKey = "oauth_token"; + + protected virtual string UserGuidKey + { + get { return String.Empty; } + } + + protected string APIKey { get; set; } + protected string APISecret { get; set; } + protected AuthMode Mode { get; set; } + protected string OAuthVersion { get; set; } + protected HttpMethod TokenMethod { get; set; } + + //oAuth 1 + protected string OAuthVerifier + { + get { return HttpContext.Current.Request.Params[OAuthVerifierKey]; } + } + protected Uri RequestTokenEndpoint { get; set; } + protected HttpMethod RequestTokenMethod { get; set; } + protected string TokenSecret { get; set; } + protected string UserGuid { get; set; } + + //oAuth 1 and 2 + protected Uri AuthorizationEndpoint { get; set; } + protected string AuthToken { get; private set; } + protected TimeSpan AuthTokenExpiry { get; set; } + protected Uri MeGraphEndpoint { get; set; } + protected Uri TokenEndpoint { get; set; } + + //oAuth 2 + protected string AuthTokenName { get; set; } + protected string Scope { get; set; } + protected string VerificationCode + { + get { return HttpContext.Current.Request.Params[OAuthCodeKey]; } + } + + #endregion + + #region Public Properties + + public Uri CallbackUri { get; set; } + public string Service { get; set; } + + #endregion + + #region Private Methods + + private AuthorisationResult AuthorizeV1() + { + if (!IsCurrentUserAuthorized()) + { + if (!HaveVerificationCode()) + { + string ret = null; + + string response = RequestToken(); + + if (response.Length > 0) + { + //response contains token and token secret. We only need the token. + NameValueCollection qs = HttpUtility.ParseQueryString(response); + + if (qs[OAuthCallbackConfirmedKey] != null) + { + if (qs[OAuthCallbackConfirmedKey] != "true") + { + throw new Exception("OAuth callback not confirmed."); + } + } + + if (qs[OAuthTokenKey] != null) + { + ret = AuthorizationEndpoint + "?" + OAuthTokenKey + "=" + qs[OAuthTokenKey]; + + AuthToken = qs[OAuthTokenKey]; + TokenSecret = qs[OAuthTokenSecretKey]; + SaveTokenCookie("_request"); + } + } + + HttpContext.Current.Response.Redirect(ret, true); + + return AuthorisationResult.RequestingCode; + } + + ExchangeRequestTokenForToken(); + } + + return AuthorisationResult.Authorized; + } + + private AuthorisationResult AuthorizeV2() + { + string errorReason = HttpContext.Current.Request.Params["error_reason"]; + bool userDenied = (errorReason != null); + if (userDenied) + { + return AuthorisationResult.Denied; + } + + if (!HaveVerificationCode()) + { + List parameters = new List(); + parameters.Add(new QueryParameter("scope", Scope)); + parameters.Add(new QueryParameter(OAuthClientIdKey, APIKey)); + parameters.Add(new QueryParameter(OAuthRedirectUriKey, HttpContext.Current.Server.UrlEncode(CallbackUri.ToString()))); + parameters.Add(new QueryParameter("state", Service)); + parameters.Add(new QueryParameter("response_type", "code")); + + HttpContext.Current.Response.Redirect(AuthorizationEndpoint + "?" + parameters.ToNormalizedString(), true); + return AuthorisationResult.RequestingCode; + } + + ExchangeCodeForToken(); + + return AuthorisationResult.Authorized; + } + + private string ComputeHash(HashAlgorithm hashAlgorithm, string data) + { + if (hashAlgorithm == null) + { + throw new ArgumentNullException("hashAlgorithm"); + } + + if (string.IsNullOrEmpty(data)) + { + throw new ArgumentNullException("data"); + } + + byte[] dataBuffer = Encoding.ASCII.GetBytes(data); + byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer); + + return Convert.ToBase64String(hashBytes); + } + + private void ExchangeCodeForToken() + { + IList parameters = new List(); + parameters.Add(new QueryParameter(OAuthClientIdKey, APIKey)); + parameters.Add(new QueryParameter(OAuthRedirectUriKey, HttpContext.Current.Server.UrlEncode(CallbackUri.ToString()))); + parameters.Add(new QueryParameter(OAuthClientSecretKey, APISecret)); + parameters.Add(new QueryParameter(OAuthGrantTyepKey, "authorization_code")); + parameters.Add(new QueryParameter(OAuthCodeKey, VerificationCode)); + + string responseText = ExecuteWebRequest(TokenMethod, TokenEndpoint, parameters.ToNormalizedString(), String.Empty); + + AuthToken = GetToken(responseText); + AuthTokenExpiry = GetExpiry(responseText); + } + + private void ExchangeRequestTokenForToken() + { + LoadTokenCookie("_request"); + + string response = ExecuteAuthorizedRequest(HttpMethod.POST, TokenEndpoint); + + if (response.Length > 0) + { + //Store the Token and Token Secret + NameValueCollection qs = HttpUtility.ParseQueryString(response); + if (qs[OAuthTokenKey] != null) + { + AuthToken = qs[OAuthTokenKey]; + } + if (qs[OAuthTokenSecretKey] != null) + { + TokenSecret = qs[OAuthTokenSecretKey]; + } + if (qs[UserGuidKey] != null) + { + UserGuid = qs[UserGuidKey]; + } + } + } + + private string ExecuteAuthorizedRequest(HttpMethod method, Uri uri) + { + string outUrl; + string ret; + List requestParameters; + + string nonce = GenerateNonce(); + string timeStamp = GenerateTimeStamp(); + + string verifier = (uri == TokenEndpoint) ? OAuthVerifier: String.Empty; + //Generate Signature + string sig = GenerateSignature(uri, + AuthToken, + TokenSecret, + String.Empty, + verifier, + method.ToString(), + timeStamp, + nonce, + out outUrl, + out requestParameters); + + + var headerParameters = new List + { + new QueryParameter(OAuthConsumerKeyKey, APIKey), + new QueryParameter(OAuthNonceKey, nonce), + new QueryParameter(OAuthSignatureKey, sig), + new QueryParameter(OAuthSignatureMethodKey, HMACSHA1SignatureType), + new QueryParameter(OAuthTimestampKey, timeStamp), + new QueryParameter(OAuthTokenKey, AuthToken), + new QueryParameter(OAuthVersionKey, OAuthVersion) + }; + if (uri == TokenEndpoint) + { + headerParameters.Add(new QueryParameter(OAuthVerifierKey, OAuthVerifier)); + } + + ret = ExecuteWebRequest(method, uri, String.Empty, headerParameters.ToAuthorizationString()); + + return ret; + } + + private string ExecuteWebRequest(HttpMethod method, Uri uri, string parameters, string authHeader) + { + WebRequest request; + + if (method == HttpMethod.POST) + { + byte[] byteArray = Encoding.UTF8.GetBytes(parameters); + + request = WebRequest.CreateDefault(uri); + request.Method = "POST"; + request.ContentType = "application/x-www-form-urlencoded"; + //request.ContentType = "text/xml"; + request.ContentLength = byteArray.Length; + + if (!String.IsNullOrEmpty(parameters)) + { + Stream dataStream = request.GetRequestStream(); + dataStream.Write(byteArray, 0, byteArray.Length); + dataStream.Close(); + } + } + else + { + if (String.IsNullOrEmpty(parameters)) + { + request = WebRequest.CreateDefault(new Uri(uri.ToString())); + } + else + { + request = WebRequest.CreateDefault(new Uri(uri + "?" + parameters)); + } + } + + //Add Headers + if (!String.IsNullOrEmpty(authHeader)) + { + request.Headers.Add(HttpRequestHeader.Authorization, authHeader); + } + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + using (var responseReader = new StreamReader(responseStream)) + { + return responseReader.ReadToEnd(); + } + } + } + } + + private string GenerateSignatureBase(Uri url, string token, string callbackurl, string oauthVerifier, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out List requestParameters) + { + if (token == null) + { + token = string.Empty; + } + + if (string.IsNullOrEmpty(httpMethod)) + { + throw new ArgumentNullException("httpMethod"); + } + + requestParameters = GetQueryParameters(url.Query); + requestParameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion)); + requestParameters.Add(new QueryParameter(OAuthNonceKey, nonce)); + requestParameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp)); + requestParameters.Add(new QueryParameter(OAuthSignatureMethodKey, HMACSHA1SignatureType)); + requestParameters.Add(new QueryParameter(OAuthConsumerKeyKey, APIKey)); + + if (!string.IsNullOrEmpty(callbackurl)) + { + requestParameters.Add(new QueryParameter(OAuthCallbackKey, UrlEncode(callbackurl))); + } + + if (!string.IsNullOrEmpty(oauthVerifier)) + { + requestParameters.Add(new QueryParameter(OAuthVerifierKey, oauthVerifier)); + } + + if (!string.IsNullOrEmpty(token)) + { + requestParameters.Add(new QueryParameter(OAuthTokenKey, token)); + } + + requestParameters.Sort(new QueryParameterComparer()); + + normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host); + if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) + { + normalizedUrl += ":" + url.Port; + } + normalizedUrl += url.AbsolutePath; + string normalizedRequestParameters = requestParameters.ToNormalizedString(); + + var signatureBase = new StringBuilder(); + signatureBase.AppendFormat("{0}&", httpMethod.ToUpper()); + signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl)); + signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters)); + + return signatureBase.ToString(); + } + + private string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) + { + return ComputeHash(hash, signatureBase); + } + + private List GetQueryParameters(string parameters) + { + if (parameters.StartsWith("?")) + { + parameters = parameters.Remove(0, 1); + } + + var result = new List(); + + if (!string.IsNullOrEmpty(parameters)) + { + string[] p = parameters.Split('&'); + foreach (string s in p) + { + if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix)) + { + if (s.IndexOf('=') > -1) + { + string[] temp = s.Split('='); + result.Add(new QueryParameter(temp[0], temp[1])); + } + else + { + result.Add(new QueryParameter(s, string.Empty)); + } + } + } + } + + return result; + } + + private string RequestToken() + { + string outUrl = String.Empty; + List requestParameters; + string ret = String.Empty; + + string nonce = GenerateNonce(); + string timeStamp = GenerateTimeStamp(); + + string sig = GenerateSignature(RequestTokenEndpoint, + String.Empty, + String.Empty, + CallbackUri.OriginalString, + String.Empty, + RequestTokenMethod.ToString(), + timeStamp, + nonce, + out outUrl, + out requestParameters); + + var headerParameters = new List + { + new QueryParameter(OAuthCallbackKey, CallbackUri.OriginalString), + new QueryParameter(OAuthConsumerKeyKey, APIKey), + new QueryParameter(OAuthNonceKey, nonce), + new QueryParameter(OAuthSignatureKey, sig), + new QueryParameter(OAuthSignatureMethodKey, HMACSHA1SignatureType), + new QueryParameter(OAuthTimestampKey, timeStamp), + new QueryParameter(OAuthVersionKey, OAuthVersion) + }; + + ret = ExecuteWebRequest(RequestTokenMethod, new Uri(outUrl), String.Empty, headerParameters.ToAuthorizationString()); + + return ret; + } + + private void SaveTokenCookie(string suffix) + { + var authTokenCookie = new HttpCookie(AuthTokenName + suffix); + authTokenCookie.Values[OAuthTokenKey] = AuthToken; + authTokenCookie.Values[OAuthTokenSecretKey] = TokenSecret; + authTokenCookie.Values[UserGuidKey] = UserGuid; + + authTokenCookie.Expires = DateTime.Now.Add(AuthTokenExpiry); + HttpContext.Current.Response.SetCookie(authTokenCookie); + } + + #endregion + + #region Protected Methods + + /// + /// Generate the timestamp for the signature + /// + /// + protected virtual string GenerateTimeStamp() + { + // Default implementation of UNIX time of the current UTC time + TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds).ToString(CultureInfo.InvariantCulture); + } + + /// + /// Generate a nonce + /// + /// + protected virtual string GenerateNonce() + { + // Just a simple implementation of a random number between 123400 and 9999999 + return random.Next(123400, 9999999).ToString(CultureInfo.InvariantCulture); + } + + protected virtual TimeSpan GetExpiry(string responseText) + { + return TimeSpan.MinValue; + } + + protected virtual string GetToken(string responseText) + { + return responseText; + } + + protected void LoadTokenCookie(string suffix) + { + HttpCookie authTokenCookie = HttpContext.Current.Request.Cookies[AuthTokenName + suffix]; + if (authTokenCookie != null) + { + if (authTokenCookie.HasKeys) + { + AuthToken = authTokenCookie.Values[OAuthTokenKey]; + TokenSecret = authTokenCookie.Values[OAuthTokenSecretKey]; + UserGuid = authTokenCookie.Values[UserGuidKey]; + } + } + } + + #endregion + + public void AuthenticateUser(UserData user, PortalSettings settings, string IPAddress, Action addCustomProperties, Action onAuthenticated) + { + UserLoginStatus loginStatus = UserLoginStatus.LOGIN_FAILURE; + + string userName = Service + "-" + user.Id; + + UserInfo objUserInfo = UserController.ValidateUser(settings.PortalId, userName, "", + Service, "", + settings.PortalName, IPAddress, + ref loginStatus); + + + //Raise UserAuthenticated Event + UserAuthenticatedEventArgs eventArgs = new UserAuthenticatedEventArgs(objUserInfo, userName, loginStatus, Service); + + eventArgs.AutoRegister = true; + + NameValueCollection profileProperties = new NameValueCollection(); + + profileProperties.Add("FirstName", user.FirstName); + profileProperties.Add("LastName", user.LastName); + profileProperties.Add("Email", user.PreferredEmail); + profileProperties.Add("DisplayName", user.DisplayName); + if (!String.IsNullOrEmpty(user.Locale)) + { + profileProperties.Add("PreferredLocale", user.Locale.Replace('_', '-')); + } + //profileProperties.Add("City", user.City); + profileProperties.Add("ProfileImage", user.ProfileImage); + profileProperties.Add("Website", user.Website); + + if (String.IsNullOrEmpty(user.TimeZoneInfo)) + { +#pragma warning disable 612,618 + + int timeZone; + if (Int32.TryParse(user.Timezone, out timeZone)) + { + TimeZoneInfo timeZoneInfo = Localization.Localization.ConvertLegacyTimeZoneOffsetToTimeZoneInfo(timeZone); + + profileProperties.Add("PreferredTimeZone", timeZoneInfo.Id); + } + +#pragma warning restore 612,618 + } + else + { + profileProperties.Add("PreferredTimeZone", user.TimeZoneInfo); + } + + + addCustomProperties(profileProperties); + + eventArgs.Profile = profileProperties; + + if (Mode == AuthMode.Login) + { + SaveTokenCookie(String.Empty); + } + + onAuthenticated(eventArgs); + } + + public AuthorisationResult Authorize() + { + if (OAuthVersion == "1.0") + { + return AuthorizeV1(); + } + else + { + return AuthorizeV2(); + } + } + + /// + /// Generates a signature using the HMAC-SHA1 algorithm + /// + /// The full url that needs to be signed including its non OAuth url parameters + /// The token, if available. If not available pass null or an empty string + /// The token secret, if available. If not available pass null or an empty string + /// + /// This value MUST be included when exchanging Request Tokens for Access Tokens. Otherwise pass a null or an empty string + /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc) + /// + /// + /// + /// + /// A base64 string of the hash value + public string GenerateSignature(Uri url, string token, string tokenSecret, string callbackurl, string oauthVerifier, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out List requestParameters) + { + string signatureBase = GenerateSignatureBase(url, token, callbackurl, oauthVerifier, httpMethod, timeStamp, nonce, out normalizedUrl, out requestParameters); + + var hmacsha1 = new HMACSHA1 + { + Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(APISecret), + string.IsNullOrEmpty(tokenSecret) + ? "" + : UrlEncode(tokenSecret))) + }; + + return GenerateSignatureUsingHash(signatureBase, hmacsha1); + } + + public TUserData GetCurrentUser() where TUserData : UserData + { + LoadTokenCookie(String.Empty); + + if (!IsCurrentUserAuthorized()) + { + return null; + } + + string responseText; + if (OAuthVersion == "1.0") + { + responseText = ExecuteAuthorizedRequest(HttpMethod.GET, MeGraphEndpoint); + } + else + { + responseText = ExecuteWebRequest(HttpMethod.GET, new Uri(MeGraphEndpoint + "?" + "access_token=" + AuthToken), null, String.Empty); + } + TUserData user = Json.Deserialize(responseText); + return user; + } + + public bool HaveVerificationCode() + { + return (OAuthVersion == "1.0") ? (OAuthVerifier != null) : (VerificationCode != null); + } + + public bool IsCurrentService() + { + string service = HttpContext.Current.Request.Params["state"]; + return !String.IsNullOrEmpty(service) && service == Service; + } + + public Boolean IsCurrentUserAuthorized() + { + return !String.IsNullOrEmpty(AuthToken); + } + + public void RemoveToken() + { + HttpCookie authTokenCookie = new HttpCookie(AuthTokenName); + authTokenCookie.Expires = DateTime.Now.AddDays(-30); + HttpContext.Current.Response.SetCookie(authTokenCookie); + } + + /// + /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case. + /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth + /// + /// The value to Url encode + /// Returns a Url encoded string + public static string UrlEncode(string value) + { + var result = new StringBuilder(); + + foreach (char symbol in value) + { + if (UnreservedChars.IndexOf(symbol) != -1) + { + result.Append(symbol); + } + else + { + result.Append('%' + String.Format("{0:X2}", (int)symbol)); + } + } + + return result.ToString(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/OAuthConfigBase.cs b/DNN Platform/Library/Services/Authentication/OAuth/OAuthConfigBase.cs new file mode 100644 index 00000000000..ad9c58b45fe --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/OAuthConfigBase.cs @@ -0,0 +1,88 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Globalization; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.Authentication.OAuth +{ + /// + /// The Config class provides a central area for management of Module Configuration Settings. + /// + [Serializable] + public class OAuthConfigBase : AuthenticationConfigBase + { + private const string _cacheKey = "Authentication"; + + protected OAuthConfigBase(string service, int portalId) + : base(portalId) + { + Service = service; + + APIKey = PortalController.GetPortalSetting(Service + "_APIKey", portalId, ""); + APISecret = PortalController.GetPortalSetting(Service + "_APISecret", portalId, ""); + Enabled = PortalController.GetPortalSettingAsBoolean(Service + "_Enabled", portalId, false); + } + + protected string Service { get; set; } + + public string APIKey { get; set; } + + public string APISecret { get; set; } + + public bool Enabled { get; set; } + + private static string GetCacheKey(string service, int portalId) + { + return _cacheKey + "." + service + "_" + portalId; + } + + public static void ClearConfig(string service, int portalId) + { + DataCache.RemoveCache(GetCacheKey(service, portalId)); + } + + public static OAuthConfigBase GetConfig(string service, int portalId) + { + string key = GetCacheKey(service, portalId); + var config = (OAuthConfigBase)DataCache.GetCache(key); + if (config == null) + { + config = new OAuthConfigBase(service, portalId); + DataCache.SetCache(key, config); + } + return config; + } + + public static void UpdateConfig(OAuthConfigBase config) + { + PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_APIKey", config.APIKey); + PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_APISecret", config.APISecret); + PortalController.UpdatePortalSetting(config.PortalID, config.Service + "_Enabled", config.Enabled.ToString(CultureInfo.InvariantCulture)); + ClearConfig(config.Service, config.PortalID); + } + } +} diff --git a/DNN Platform/Library/Services/Authentication/OAuth/OAuthLoginBase.cs b/DNN Platform/Library/Services/Authentication/OAuth/OAuthLoginBase.cs new file mode 100644 index 00000000000..4e2c3c044dc --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/OAuthLoginBase.cs @@ -0,0 +1,82 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Web; +using System.Web.UI; + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + public abstract class OAuthLoginBase : AuthenticationLoginBase + { + protected virtual string AuthSystemApplicationName + { + get { return String.Empty; } + } + + protected OAuthClientBase OAuthClient { get; set; } + + protected abstract UserData GetCurrentUser(); + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if (!IsPostBack) + { + //Save the return Url in the cookie + HttpContext.Current.Response.Cookies.Set(new HttpCookie("returnurl", RedirectURL) + {Expires = DateTime.Now.AddMinutes(5)}); + } + + bool shouldAuthorize = OAuthClient.IsCurrentService() && OAuthClient.HaveVerificationCode(); + if(Mode == AuthMode.Login) + { + shouldAuthorize = shouldAuthorize || OAuthClient.IsCurrentUserAuthorized(); + } + + if (shouldAuthorize) + { + if (OAuthClient.Authorize() == AuthorisationResult.Authorized) + { + OAuthClient.AuthenticateUser(GetCurrentUser(), PortalSettings, IPAddress, + (properties) => { }, + OnUserAuthenticated); + } + } + } + + #region Overrides of AuthenticationLoginBase + + public override bool Enabled + { + get { return OAuthConfigBase.GetConfig(AuthSystemApplicationName, PortalId).Enabled; } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/OAuthSettingsBase.cs b/DNN Platform/Library/Services/Authentication/OAuth/OAuthSettingsBase.cs new file mode 100644 index 00000000000..58dba76f1bc --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/OAuthSettingsBase.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Linq; +using DotNetNuke.UI.WebControls; + +namespace DotNetNuke.Services.Authentication.OAuth +{ + public class OAuthSettingsBase : AuthenticationSettingsBase + { + protected PropertyEditorControl SettingsEditor; + + protected virtual string AuthSystemApplicationName { get { return String.Empty; } } + + public override void UpdateSettings() + { + if (SettingsEditor.IsValid && SettingsEditor.IsDirty) + { + var config = (OAuthConfigBase)SettingsEditor.DataSource; + OAuthConfigBase.UpdateConfig(config); + } + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + OAuthConfigBase config = OAuthConfigBase.GetConfig(AuthSystemApplicationName, PortalId); + SettingsEditor.DataSource = config; + SettingsEditor.DataBind(); + } + } +} diff --git a/DNN Platform/Library/Services/Authentication/OAuth/QueryParameter.cs b/DNN Platform/Library/Services/Authentication/OAuth/QueryParameter.cs new file mode 100644 index 00000000000..bf0e51c5010 --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/QueryParameter.cs @@ -0,0 +1,41 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + /// + /// Provides an internal structure to sort the query parameter + /// + public class QueryParameter + { + public QueryParameter(string name, string value) + { + this.Name = name; + this.Value = value; + } + + public string Name { get;private set; } + + public string Value { get;private set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/QueryParameterComparer.cs b/DNN Platform/Library/Services/Authentication/OAuth/QueryParameterComparer.cs new file mode 100644 index 00000000000..77c65b004ec --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/QueryParameterComparer.cs @@ -0,0 +1,51 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + /// + /// Comparer class used to perform the sorting of the query parameters + /// + internal class QueryParameterComparer : IComparer + { + #region IComparer Members + + public int Compare(QueryParameter x, QueryParameter y) + { + if (x.Name == y.Name) + { + return String.CompareOrdinal(x.Value, y.Value); + } + return String.CompareOrdinal(x.Name, y.Name); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/OAuth/UserData.cs b/DNN Platform/Library/Services/Authentication/OAuth/UserData.cs new file mode 100644 index 00000000000..2963f8d407d --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/OAuth/UserData.cs @@ -0,0 +1,125 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +#endregion + +namespace DotNetNuke.Services.Authentication.OAuth +{ + [DataContract] + public class UserData + { + [DataMember(Name = "id")] + public string Id { get; set; } + + public virtual string DisplayName + { + get + { + return Name; + } + set { } + } + + [DataMember(Name = "email")] + public virtual string Email { get; set; } + + [DataMember(Name = "emails")] + public EmailData Emails { get; set; } + + public virtual string FirstName + { + get + { + return (!String.IsNullOrEmpty(Name) && Name.IndexOf(" ", StringComparison.Ordinal) > 0) ? Name.Substring(0, Name.IndexOf(" ", StringComparison.Ordinal)) : String.Empty; + } + set { Name = value + " " + LastName; } + } + + [DataMember(Name = "gender")] + public string Gender { get; set; } + + public virtual string LastName + { + get + { + return (!String.IsNullOrEmpty(Name) && Name.IndexOf(" ", StringComparison.Ordinal) > 0) ? Name.Substring(Name.IndexOf(" ", StringComparison.Ordinal) + 1) : Name; + } + set { Name = FirstName + " " + value; } + + } + + [DataMember(Name = "locale")] + public virtual string Locale { get; set; } + + [DataMember(Name = "name")] + public virtual string Name { get; set; } + + public string PreferredEmail + { + get + { + if (Emails == null) + { + return Email; + } + return Emails.PreferredEmail; + } + } + + public virtual string ProfileImage { get; set; } + + [DataMember(Name = "timezone")] + public string Timezone { get; set; } + + [DataMember(Name = "time_zone")] + public string TimeZoneInfo { get; set; } + + [DataMember(Name = "username")] + public virtual string UserName { get; set; } + + [DataMember(Name = "website")] + public virtual string Website { get; set; } + } + + [DataContract] + public class EmailData + { + [DataMember(Name = "preferred")] + public string PreferredEmail { get; set; } + + [DataMember(Name = "account")] + public string AccountEmail { get; set; } + + [DataMember(Name = "personal")] + public string PersonalEmail { get; set; } + + [DataMember(Name = "business")] + public string BusinessEmail { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Authentication/UserAuthenticatedEventArgs.cs b/DNN Platform/Library/Services/Authentication/UserAuthenticatedEventArgs.cs new file mode 100644 index 00000000000..cc9e92890cb --- /dev/null +++ b/DNN Platform/Library/Services/Authentication/UserAuthenticatedEventArgs.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Specialized; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Membership; + +#endregion + +namespace DotNetNuke.Services.Authentication +{ + /// ----------------------------------------------------------------------------- + /// + /// The UserAuthenticatedEventArgs class provides a custom EventArgs object for the + /// UserAuthenticated event + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + public class UserAuthenticatedEventArgs : EventArgs + { + /// ----------------------------------------------------------------------------- + /// + /// All properties Constructor. + /// + /// The user being authenticated. + /// The user token + /// The login status. + /// The type of Authentication + /// ----------------------------------------------------------------------------- + public UserAuthenticatedEventArgs(UserInfo user, string token, UserLoginStatus status, string type) + { + Profile = new NameValueCollection(); + Message = String.Empty; + AutoRegister = false; + Authenticated = true; + User = user; + LoginStatus = status; + UserToken = token; + AuthenticationType = type; + RememberMe = false; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a flag that determines whether the User was authenticated + /// + /// ----------------------------------------------------------------------------- + public bool Authenticated { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Authentication Type + /// + /// ----------------------------------------------------------------------------- + public string AuthenticationType { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a flag that determines whether the user should be automatically registered + /// + /// ----------------------------------------------------------------------------- + public bool AutoRegister { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Login Status + /// + /// ----------------------------------------------------------------------------- + public UserLoginStatus LoginStatus { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Message + /// + /// ----------------------------------------------------------------------------- + public string Message { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Profile + /// + /// ----------------------------------------------------------------------------- + public NameValueCollection Profile { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the RememberMe setting + /// + /// ----------------------------------------------------------------------------- + public bool RememberMe { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the User + /// + /// ----------------------------------------------------------------------------- + public UserInfo User { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the UserToken (the userid or authenticated id) + /// + /// ----------------------------------------------------------------------------- + public string UserToken { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Cache/CachingProvider.cs b/DNN Platform/Library/Services/Cache/CachingProvider.cs new file mode 100644 index 00000000000..371d2f2d015 --- /dev/null +++ b/DNN Platform/Library/Services/Cache/CachingProvider.cs @@ -0,0 +1,554 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Web; +using System.Web.Caching; +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Cache +{ + /// + /// CachingProvider provides basic component of cache system, by default it will use HttpRuntime.Cache. + /// + /// + /// Using cache will speed up the application to a great degree, we recommend to use cache for whole modules, + /// but sometimes cache also make confuse for user, if we didn't take care of how to make cache expired when needed, + /// such as if a data has already been deleted but the cache arn't clear, it will cause un expected errors. + /// so you should choose a correct performance setting type when you trying to cache some stuff, and always remember + /// update cache immediately after the data changed. + /// + /// + /// + /// public static void ClearCache(string cachePrefix) + /// { + /// CachingProvider.Instance().Clear("Prefix", GetDnnCacheKey(cachePrefix)); + /// } + /// + /// + public abstract class CachingProvider + { + #region Private Members + + private static System.Web.Caching.Cache _cache; + private const string CachePrefix = "DNN_"; + + #endregion + + #region Protected Properties + + /// + /// Gets the default cache provider. + /// + /// HttpRuntime.Cache + protected static System.Web.Caching.Cache Cache + { + get + { + return _cache ?? (_cache = HttpRuntime.Cache); + } + } + + #endregion + + #region Shared/Static Methods + + /// + /// Cleans the cache key by remove cache key prefix. + /// + /// The cache key. + /// cache key without prefix. + /// cache key is empty. + public static string CleanCacheKey(string CacheKey) + { + if (String.IsNullOrEmpty(CacheKey)) + { + throw new ArgumentException("Argument cannot be null or an empty string", "CacheKey"); + } + return CacheKey.Substring(CachePrefix.Length); + } + + /// + /// Gets the cache key with key prefix. + /// + /// The cache key. + /// CachePrefix + CacheKey + /// Cache key is empty. + public static string GetCacheKey(string CacheKey) + { + if (string.IsNullOrEmpty(CacheKey)) + { + throw new ArgumentException("Argument cannot be null or an empty string", "CacheKey"); + } + return CachePrefix + CacheKey; + } + + /// + /// Instances of caching provider. + /// + /// The Implemments provider of cache system defind in web.config. + public static CachingProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region Private Methods + + private void ClearCacheInternal(string prefix, bool clearRuntime) + { + foreach (DictionaryEntry objDictionaryEntry in HttpRuntime.Cache) + { + if (Convert.ToString(objDictionaryEntry.Key).StartsWith(prefix)) + { + if (clearRuntime) + { + //remove item from runtime cache + RemoveInternal(Convert.ToString(objDictionaryEntry.Key)); + } + else + { + //Call provider's remove method + Remove(Convert.ToString(objDictionaryEntry.Key)); + } + } + } + } + + private void ClearCacheKeysByPortalInternal(int portalId, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.PortalCacheKey, clearRuntime, Null.NullInteger, string.Empty); + RemoveFormattedCacheKey(DataCache.LocalesCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.ProfileDefinitionsCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.ListsCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.SkinsCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.PortalUserCountCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.PackagesCacheKey, clearRuntime, portalId); + + RemoveCacheKey(DataCache.AllPortalsCacheKey, clearRuntime); + } + + private void ClearDesktopModuleCacheInternal(int portalId, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.DesktopModuleCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.PortalDesktopModuleCacheKey, clearRuntime, portalId); + RemoveCacheKey(DataCache.ModuleDefinitionCacheKey, clearRuntime); + RemoveCacheKey(DataCache.ModuleControlsCacheKey, clearRuntime); + } + + private void ClearFolderCacheInternal(int portalId, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.FolderCacheKey, clearRuntime, portalId); + + // FolderUserCacheKey also includes permissions and userId but we don't have that information + // here so we remove them using a prefix + var folderUserCachePrefix = GetCacheKey(string.Format("Folders|{0}|", portalId)); + ClearCacheInternal(folderUserCachePrefix, clearRuntime); + + RemoveFormattedCacheKey(DataCache.FolderPermissionCacheKey, clearRuntime, portalId); + } + + private void ClearHostCacheInternal(bool clearRuntime) + { + RemoveCacheKey(DataCache.HostSettingsCacheKey, clearRuntime); + RemoveCacheKey(DataCache.SecureHostSettingsCacheKey, clearRuntime); + RemoveCacheKey(DataCache.UnSecureHostSettingsCacheKey, clearRuntime); + RemoveCacheKey(DataCache.PortalAliasCacheKey, clearRuntime); + RemoveCacheKey("CSS", clearRuntime); + RemoveCacheKey("StyleSheets", clearRuntime); + RemoveCacheKey(DataCache.DesktopModulePermissionCacheKey, clearRuntime); + RemoveCacheKey("GetRoles", clearRuntime); + RemoveCacheKey("CompressionConfig", clearRuntime); + + //Clear "portal keys" for Host + ClearFolderCacheInternal(-1, clearRuntime); + ClearDesktopModuleCacheInternal(-1, clearRuntime); + ClearCacheKeysByPortalInternal(-1, clearRuntime); + ClearTabCacheInternal(-1, clearRuntime); + + } + + private void ClearModuleCacheInternal(int tabId, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.TabModuleCacheKey, clearRuntime, tabId); + RemoveFormattedCacheKey(DataCache.ModulePermissionCacheKey, clearRuntime, tabId); + } + + private void ClearModulePermissionsCachesByPortalInternal(int portalId, bool clearRuntime) + { + var objTabs = new TabController(); + foreach (KeyValuePair tabPair in objTabs.GetTabsByPortal(portalId)) + { + RemoveFormattedCacheKey(DataCache.ModulePermissionCacheKey, clearRuntime, tabPair.Value.TabID); + } + } + + private void ClearPortalCacheInternal(int portalId, bool cascade, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.PortalSettingsCacheKey, clearRuntime, portalId); + + Dictionary locales = LocaleController.Instance.GetLocales(portalId); + if (locales == null || locales.Count == 0) + { + //At least attempt to remove default locale + string defaultLocale = PortalController.GetPortalDefaultLanguage(portalId); + RemoveCacheKey(String.Format(DataCache.PortalCacheKey, portalId, defaultLocale), clearRuntime); + } + else + { + foreach (Locale portalLocale in LocaleController.Instance.GetLocales(portalId).Values) + { + RemoveCacheKey(String.Format(DataCache.PortalCacheKey, portalId, portalLocale.Code), clearRuntime); + } + } + if (cascade) + { + var objTabs = new TabController(); + foreach (KeyValuePair tabPair in objTabs.GetTabsByPortal(portalId)) + { + ClearModuleCacheInternal(tabPair.Value.TabID, clearRuntime); + } + var moduleController = new ModuleController(); + foreach (ModuleInfo moduleInfo in moduleController.GetModules(portalId)) + { + RemoveCacheKey("GetModuleSettings" + moduleInfo.ModuleID, clearRuntime); + } + } + + //Clear "portal keys" for Portal + ClearFolderCacheInternal(portalId, clearRuntime); + ClearCacheKeysByPortalInternal(portalId, clearRuntime); + ClearDesktopModuleCacheInternal(portalId, clearRuntime); + ClearTabCacheInternal(portalId, clearRuntime); + + RemoveCacheKey(String.Format(DataCache.RolesCacheKey, portalId), clearRuntime); + } + + private void ClearTabCacheInternal(int portalId, bool clearRuntime) + { + RemoveFormattedCacheKey(DataCache.TabCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.TabAliasSkinCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.TabCustomAliasCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.TabUrlCacheKey, clearRuntime, portalId); + RemoveFormattedCacheKey(DataCache.TabPermissionCacheKey, clearRuntime, portalId); + Dictionary locales = LocaleController.Instance.GetLocales(portalId); + if (locales == null || locales.Count == 0) + { + //At least attempt to remove default locale + string defaultLocale = PortalController.GetPortalDefaultLanguage(portalId); + RemoveCacheKey(string.Format(DataCache.TabPathCacheKey, defaultLocale, portalId), clearRuntime); + } + else + { + foreach (Locale portalLocale in LocaleController.Instance.GetLocales(portalId).Values) + { + RemoveCacheKey(string.Format(DataCache.TabPathCacheKey, portalLocale.Code, portalId), clearRuntime); + } + } + + RemoveCacheKey(string.Format(DataCache.TabPathCacheKey, Null.NullString, portalId), clearRuntime); + } + + private void RemoveCacheKey(string CacheKey, bool clearRuntime) + { + if (clearRuntime) + { + //remove item from runtime cache + RemoveInternal(GetCacheKey(CacheKey)); + } + else + { + //Call provider's remove method + Remove(GetCacheKey(CacheKey)); + } + } + + private void RemoveFormattedCacheKey(string CacheKeyBase, bool clearRuntime, params object[] parameters) + { + if (clearRuntime) + { + //remove item from runtime cache + RemoveInternal(string.Format(GetCacheKey(CacheKeyBase), parameters)); + } + else + { + //Call provider's remove method + Remove(string.Format(GetCacheKey(CacheKeyBase), parameters)); + } + } + + #endregion + + #region Protected Methods + + /// + /// Clears the cache internal. + /// + /// Type of the cache. + /// The data. + /// if set to true clear runtime cache. + protected void ClearCacheInternal(string cacheType, string data, bool clearRuntime) + { + switch (cacheType) + { + case "Prefix": + ClearCacheInternal(data, clearRuntime); + break; + case "Host": + ClearHostCacheInternal(clearRuntime); + break; + case "Folder": + ClearFolderCacheInternal(int.Parse(data), clearRuntime); + break; + case "Module": + ClearModuleCacheInternal(int.Parse(data), clearRuntime); + break; + case "ModulePermissionsByPortal": + ClearModulePermissionsCachesByPortalInternal(int.Parse(data), clearRuntime); + break; + case "Portal": + ClearPortalCacheInternal(int.Parse(data), false, clearRuntime); + break; + case "PortalCascade": + ClearPortalCacheInternal(int.Parse(data), true, clearRuntime); + break; + case "Tab": + ClearTabCacheInternal(int.Parse(data), clearRuntime); + break; + case "ServiceFrameworkRoutes": + ReloadServicesFrameworkRoutes(); + break; + } + } + + private void ReloadServicesFrameworkRoutes() + { + //registration of routes when the servers is operating is done as part of the cache + //because the web request cahcing provider is the only inter-server communication channel + //that is reliable + ServicesRoutingManager.RegisterServiceRoutes(); + } + + /// + /// Removes the internal. + /// + /// The cache key. + protected void RemoveInternal(string cacheKey) + { + //attempt remove from private dictionary + DataCache.RemoveFromPrivateDictionary(cacheKey); + //remove item from memory + if (Cache[cacheKey] != null) + { + Cache.Remove(cacheKey); + } + } + + /// + /// Clears the specified type. + /// + /// The type. + /// The data. + public virtual void Clear(string type, string data) + { + ClearCacheInternal(type, data, false); + } + + public virtual IDictionaryEnumerator GetEnumerator() + { + return Cache.GetEnumerator(); + } + + /// + /// Gets the item. + /// + /// The cache key. + /// cache content + public virtual object GetItem(string cacheKey) + { + return Cache[cacheKey]; + } + + /// + /// Inserts the specified cache key. + /// + /// The cache key. + /// The object. + public virtual void Insert(string cacheKey, object itemToCache) + { + Insert(cacheKey, itemToCache, null as DNNCacheDependency, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); + } + + /// + /// Inserts the specified cache key. + /// + /// The cache key. + /// The object. + /// The dependency. + public virtual void Insert(string cacheKey, object itemToCache, DNNCacheDependency dependency) + { + Insert(cacheKey, itemToCache, dependency, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); + } + + /// + /// Inserts the specified cache key. + /// + /// The cache key. + /// The object. + /// The dependency. + /// The absolute expiration. + /// The sliding expiration. + public virtual void Insert(string cacheKey, object itemToCache, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration) + { + Insert(cacheKey, itemToCache, dependency, absoluteExpiration, slidingExpiration, CacheItemPriority.Default, null); + } + + /// + /// Inserts the specified cache key. + /// + /// The cache key. + /// The value. + /// The dependency. + /// The absolute expiration. + /// The sliding expiration. + /// The priority. + /// The on remove callback. + public virtual void Insert(string cacheKey, object itemToCache, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, + CacheItemRemovedCallback onRemoveCallback) + { + Cache.Insert(cacheKey, itemToCache, dependency == null ? null : dependency.SystemCacheDependency, absoluteExpiration, slidingExpiration, priority, onRemoveCallback); + } + + /// + /// Determines whether is web farm. + /// + /// + /// true if is web farm; otherwise, false. + /// + public virtual bool IsWebFarm() + { + return (ServerController.GetEnabledServers().Count > 1); + } + + /// + /// Purges the cache. + /// + /// + public virtual string PurgeCache() + { + return Localization.Localization.GetString("PurgeCacheUnsupported.Text", Localization.Localization.GlobalResourceFile); + } + + /// + /// Removes the specified cache key. + /// + /// The cache key. + public virtual void Remove(string CacheKey) + { + RemoveInternal(CacheKey); + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DNN 5.1 - Use one of the INsert methods")] + public virtual object Add(string CacheKey, object objObject, CacheDependency objDependency, DateTime AbsoluteExpiration, TimeSpan SlidingExpiration, CacheItemPriority Priority, CacheItemRemovedCallback OnRemoveCallback) + { + object retValue = GetItem(CacheKey); + if (retValue == null) + { + Insert(CacheKey, objObject, new DNNCacheDependency(objDependency), AbsoluteExpiration, SlidingExpiration, Priority, OnRemoveCallback); + } + return retValue; + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public virtual object GetPersistentCacheItem(string CacheKey, Type objType) + { + return GetItem(CacheKey); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public virtual void Insert(string cacheKey, object itemToCache, bool PersistAppRestart) + { + Insert(cacheKey, itemToCache); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public virtual void Insert(string cacheKey, object itemToCache, CacheDependency objDependency, bool PersistAppRestart) + { + Insert(cacheKey, itemToCache, new DNNCacheDependency(objDependency), System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public virtual void Insert(string cacheKey, object itemToCache, CacheDependency objDependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, bool PersistAppRestart) + { + Insert(cacheKey, itemToCache, new DNNCacheDependency(objDependency), absoluteExpiration, slidingExpiration, CacheItemPriority.Default, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Cache Persistence is not supported")] + public virtual void Insert(string Key, object itemToCache, CacheDependency objDependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback, bool PersistAppRestart) + { + Insert(Key, itemToCache, new DNNCacheDependency(objDependency), absoluteExpiration, slidingExpiration, priority, onRemoveCallback); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public virtual void Insert(string cacheKey, object itemToCache, CacheDependency objDependency) + { + Insert(cacheKey, itemToCache, new DNNCacheDependency(objDependency), System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public virtual void Insert(string cacheKey, object itemToCache, CacheDependency objDependency, DateTime absoluteExpiration, TimeSpan slidingExpiration) + { + Insert(cacheKey, itemToCache, new DNNCacheDependency(objDependency), absoluteExpiration, slidingExpiration, CacheItemPriority.Default, null); + } + + [Obsolete("Deprecated in DNN 5.1 - Use new overload that uses a DNNCacheDependency")] + public virtual void Insert(string cacheKey, object itemToCache, CacheDependency objDependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) + { + Insert(cacheKey, itemToCache, new DNNCacheDependency(objDependency), absoluteExpiration, slidingExpiration, priority, onRemoveCallback); + } + + [Obsolete("Deprecated in DNN 5.1.1 - Cache Persistence is not supported")] + public virtual void RemovePersistentCacheItem(string CacheKey) + { + Remove(CacheKey); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Cache/DNNCacheDependency.cs b/DNN Platform/Library/Services/Cache/DNNCacheDependency.cs new file mode 100644 index 00000000000..9dfd0be6b04 --- /dev/null +++ b/DNN Platform/Library/Services/Cache/DNNCacheDependency.cs @@ -0,0 +1,298 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.Caching; + +#endregion + +namespace DotNetNuke.Services.Cache +{ + /// + /// DNNCacheDependency provides dependency policies of cache system. + /// + /// + /// The CacheDependency class monitors the dependency relationships so that when any of them changes, the cached item will be automatically removed. + /// + public class DNNCacheDependency : IDisposable + { + #region "Private Members" + + private readonly DateTime _utcStart = DateTime.MaxValue; + private DNNCacheDependency _cacheDependency; + private string[] _cacheKeys; + private string[] _fileNames; + private CacheDependency _systemCacheDependency; + + #endregion + + #region "Constructors" + + /// + /// Initializes a new instance of the class. + /// + /// The system cache dependency. + public DNNCacheDependency(CacheDependency systemCacheDependency) + { + _systemCacheDependency = systemCacheDependency; + } + + /// + /// Initializes a new instance of the class that monitors a file or directory for changes. + /// + /// + public DNNCacheDependency(string filename) + { + _fileNames = new[] {filename}; + } + + /// + /// Initializes a new instance of the class that monitors an array of paths (to files or directories) for changes. + /// + /// set the cache depend on muti files. + public DNNCacheDependency(string[] filenames) + { + _fileNames = filenames; + } + + /// + /// Initializes a new instance of the class that monitors an array of paths + /// (to files or directories) for changes and specifies a time when change monitoring begins. + /// + /// The filenames. + /// The start. + public DNNCacheDependency(string[] filenames, DateTime start) + { + _utcStart = start.ToUniversalTime(); + _fileNames = filenames; + } + + /// + /// Initializes a new instance of the class that monitors an array of paths (to files or directories), + /// an array of cache keys, or both for changes. + /// + /// The filenames. + /// The cachekeys. + public DNNCacheDependency(string[] filenames, string[] cachekeys) + { + _fileNames = filenames; + _cacheKeys = cachekeys; + } + + /// + /// Initializes a new instance of the class that monitors a file or directory for changes. + /// + /// The filename. + /// The start. + public DNNCacheDependency(string filename, DateTime start) + { + _utcStart = start.ToUniversalTime(); + if (filename != null) + { + _fileNames = new[] {filename}; + } + } + + /// + /// Initializes a new instance of the class that monitors an array of paths (to files or directories), + /// an array of cache keys, or both for changes. + /// + /// The filenames. + /// The cachekeys. + /// The start. + public DNNCacheDependency(string[] filenames, string[] cachekeys, DateTime start) + { + _utcStart = start.ToUniversalTime(); + _fileNames = filenames; + _cacheKeys = cachekeys; + } + + /// + /// Initializes a new instance of the classthat monitors an array of paths (to files or directories), + /// an array of cache keys, or both for changes. It also makes itself dependent upon a separate instance of the class. + /// + /// The filenames. + /// The cachekeys. + /// The dependency. + public DNNCacheDependency(string[] filenames, string[] cachekeys, DNNCacheDependency dependency) + { + _fileNames = filenames; + _cacheKeys = cachekeys; + _cacheDependency = dependency; + } + + /// + /// Initializes a new instance of the class that monitors an array of paths (to files or directories), + /// an array of cache keys, or both for changes. + /// It also makes itself dependent upon another instance of the class and a time when the change monitoring begins. + /// + /// The filenames. + /// The cachekeys. + /// The dependency. + /// The start. + public DNNCacheDependency(string[] filenames, string[] cachekeys, DNNCacheDependency dependency, DateTime start) + { + _utcStart = start.ToUniversalTime(); + _fileNames = filenames; + _cacheKeys = cachekeys; + _cacheDependency = dependency; + } + + #endregion + + #region "Public Properties" + + /// + /// Gets the cache keys. + /// + public string[] CacheKeys + { + get + { + return _cacheKeys; + } + } + + /// + /// Gets the file names. + /// + public string[] FileNames + { + get + { + return _fileNames; + } + } + + /// + /// Gets a value indicating whether this instance has changed. + /// + /// + /// true if this instance has changed; otherwise, false. + /// + public bool HasChanged + { + get + { + return SystemCacheDependency.HasChanged; + } + } + + /// + /// Gets the cache dependency. + /// + public DNNCacheDependency CacheDependency + { + get + { + return _cacheDependency; + } + } + + /// + /// Gets the start time. + /// + public DateTime StartTime + { + get + { + return _utcStart; + } + } + + /// + /// Gets the system cache dependency. + /// + public CacheDependency SystemCacheDependency + { + get + { + try + { + if (_systemCacheDependency == null) + { + if (_cacheDependency == null) + { + _systemCacheDependency = new CacheDependency(_fileNames, _cacheKeys, _utcStart); + } + else + { + _systemCacheDependency = new CacheDependency(_fileNames, _cacheKeys, _cacheDependency.SystemCacheDependency, _utcStart); + } + } + return _systemCacheDependency; + } + catch (Exception ex) + { + throw ex; + } + } + } + + /// + /// Gets the UTC last modified. + /// + public DateTime UtcLastModified + { + get + { + return SystemCacheDependency.UtcLastModified; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + + //Method that does the actual disposal of resources + protected virtual void Dispose(bool disposing) + { + if ((disposing)) + { + if (_cacheDependency != null) + { + _cacheDependency.Dispose(disposing); + } + if (_systemCacheDependency != null) + { + _systemCacheDependency.Dispose(); + } + _fileNames = null; + _cacheKeys = null; + _cacheDependency = null; + _systemCacheDependency = null; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Cache/FBCachingProvider.cs b/DNN Platform/Library/Services/Cache/FBCachingProvider.cs new file mode 100644 index 00000000000..1415b68960c --- /dev/null +++ b/DNN Platform/Library/Services/Cache/FBCachingProvider.cs @@ -0,0 +1,216 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Cache +{ + public class FBCachingProvider : CachingProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (FBCachingProvider)); + internal const string CacheFileExtension = ".resources"; + internal static string CachingDirectory = "Cache\\"; + + #region Abstract Method Implementation + + public override void Insert(string cacheKey, object itemToCache, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, + CacheItemRemovedCallback onRemoveCallback) + { + //initialize cache dependency + DNNCacheDependency d = dependency; + + //if web farm is enabled + if (IsWebFarm()) + { + //get hashed file name + var f = new string[1]; + f[0] = GetFileName(cacheKey); + //create a cache file for item + CreateCacheFile(f[0], cacheKey); + //create a cache dependency on the cache file + d = new DNNCacheDependency(f, null, dependency); + } + + //Call base class method to add obect to cache + base.Insert(cacheKey, itemToCache, d, absoluteExpiration, slidingExpiration, priority, onRemoveCallback); + } + + public override bool IsWebFarm() + { + bool _IsWebFarm = Null.NullBoolean; + if (!string.IsNullOrEmpty(Config.GetSetting("IsWebFarm"))) + { + _IsWebFarm = bool.Parse(Config.GetSetting("IsWebFarm")); + } + return _IsWebFarm; + } + + public override string PurgeCache() + { + //called by scheduled job to remove cache files which are no longer active + return PurgeCacheFiles(Globals.HostMapPath + CachingDirectory); + } + + public override void Remove(string Key) + { + base.Remove(Key); + + //if web farm is enabled in config file + if (IsWebFarm()) + { + //get hashed filename + string f = GetFileName(Key); + //delete cache file - this synchronizes the cache across servers in the farm + DeleteCacheFile(f); + } + } + + #endregion + + #region Private Methods + + private static string ByteArrayToString(byte[] arrInput) + { + int i; + var sOutput = new StringBuilder(arrInput.Length); + for (i = 0; i <= arrInput.Length - 1; i++) + { + sOutput.Append(arrInput[i].ToString("X2")); + } + return sOutput.ToString(); + } + + private static void CreateCacheFile(string FileName, string CacheKey) + { + //declare stream + StreamWriter s = null; + try + { + //if the cache file does not already exist + if (!File.Exists(FileName)) + { + //create the cache file + s = File.CreateText(FileName); + //write the CacheKey to the file to provide a documented link between cache item and cache file + s.Write(CacheKey); + //close the stream + } + } + catch (Exception ex) + { + //permissions issue creating cache file or more than one thread may have been trying to write the cache file simultaneously + Exceptions.Exceptions.LogException(ex); + } + finally + { + if (s != null) + { + s.Close(); + } + } + } + + private static void DeleteCacheFile(string FileName) + { + try + { + if (File.Exists(FileName)) + { + File.Delete(FileName); + } + } + catch (Exception ex) + { + //an error occurred when trying to delete the cache file - this is serious as it means that the cache will not be synchronized + Exceptions.Exceptions.LogException(ex); + } + } + + private static string GetFileName(string CacheKey) + { + //cache key may contain characters invalid for a filename - this method creates a valid filename + byte[] FileNameBytes = Encoding.ASCII.GetBytes(CacheKey); + var md5 = new MD5CryptoServiceProvider(); + FileNameBytes = md5.ComputeHash(FileNameBytes); + string FinalFileName = ByteArrayToString(FileNameBytes); + return Path.GetFullPath(Globals.HostMapPath + CachingDirectory + FinalFileName + CacheFileExtension); + } + + private string PurgeCacheFiles(string Folder) + { + //declare counters + int PurgedFiles = 0; + int PurgeErrors = 0; + int i; + + //get list of cache files + string[] f; + f = Directory.GetFiles(Folder); + + //loop through cache files + for (i = 0; i <= f.Length - 1; i++) + { + //get last write time for file + DateTime dtLastWrite; + dtLastWrite = File.GetLastWriteTime(f[i]); + //if the cache file is more than 2 hours old ( no point in checking most recent cache files ) + if (dtLastWrite < DateTime.Now.Subtract(new TimeSpan(2, 0, 0))) + { + //get cachekey + string strCacheKey = Path.GetFileNameWithoutExtension(f[i]); + //if the cache key does not exist in memory + if (DataCache.GetCache(strCacheKey) == null) + { + try + { + //delete the file + File.Delete(f[i]); + PurgedFiles += 1; + } + catch (Exception exc) + { + //an error occurred + Logger.Error(exc); + + PurgeErrors += 1; + } + } + } + } + + //return a summary message for the job + return string.Format("Cache Synchronization Files Processed: " + f.Length + ", Purged: " + PurgedFiles + ", Errors: " + PurgeErrors); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Cache/PurgeCache.cs b/DNN Platform/Library/Services/Cache/PurgeCache.cs new file mode 100644 index 00000000000..43e1e69cdd6 --- /dev/null +++ b/DNN Platform/Library/Services/Cache/PurgeCache.cs @@ -0,0 +1,61 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Cache +{ + public class PurgeCache : SchedulerClient + { + public PurgeCache(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; //REQUIRED + } + + public override void DoWork() + { + try + { + string str = CachingProvider.Instance().PurgeCache(); + + ScheduleHistoryItem.Succeeded = true; //REQUIRED + ScheduleHistoryItem.AddLogNote(str); + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + + ScheduleHistoryItem.AddLogNote(string.Format("Purging cache task failed: {0}.", exc.ToString())); + + //notification that we have errored + Errored(ref exc); //REQUIRED + + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + } +} diff --git a/DNN Platform/Library/Services/ClientCapability/ClientCapability.cs b/DNN Platform/Library/Services/ClientCapability/ClientCapability.cs new file mode 100644 index 00000000000..b2dca69338c --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/ClientCapability.cs @@ -0,0 +1,117 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using DotNetNuke.Services.ClientCapability; + + +namespace DotNetNuke.Services.ClientCapability +{ + /// + /// Default Implementation of IClientCapability + /// + public class ClientCapability : IClientCapability + { + /// + /// Default Constructor. + /// + public ClientCapability() + { + Capabilities = new Dictionary(); + } + + #region Implementation of IClientCapability + + /// + /// Unique ID of the client making request. + /// + public string ID { get; set; } + + /// + /// User Agent of the client making request + /// + public string UserAgent { get; set; } + + /// + /// Is request coming from a mobile device. + /// + public bool IsMobile { get; set; } + + /// + /// Is request coming from a tablet device. + /// + public bool IsTablet { get; set; } + + /// + /// Does the requesting device supports touch screen. + /// + public bool IsTouchScreen { get; set; } + + /// + /// FacebookRequest property is filled when request is coming though Facebook iFrame (e.g. fan pages). + /// + /// + /// FacebookRequest property is populated based on data in "signed_request" headers coming from Facebook. + /// In order to ensure request is coming from Facebook, FacebookRequest.IsValidSignature method should be called with the secrety key provided by Facebook. + /// + public FacebookRequest FacebookRequest { get; set; } + + /// + /// ScreenResolution Width of the requester in Pixels. + /// + public int ScreenResolutionWidthInPixels { get; set; } + + /// + /// ScreenResolution Height of the requester in Pixels. + /// + public int ScreenResolutionHeightInPixels { get; set; } + + /// + /// Does requester support Flash. + /// + public bool SupportsFlash { get; set; } + + /// + /// A key-value collection containing all capabilities supported by requester + /// + public IDictionary Capabilities { get; set; } + + /// + /// Represents the name of the broweser in the request + /// + public string BrowserName { get; set; } + + /// + /// Returns the request prefered HTML DTD + /// + public string HtmlPreferedDTD { get; set; } + + /// + /// Http server variable used for SSL offloading - if this value is empty offloading is not enabled + /// + public string SSLOffload { get; set; } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/ClientCapability/ClientCapabilityProvider.cs b/DNN Platform/Library/Services/ClientCapability/ClientCapabilityProvider.cs new file mode 100644 index 00000000000..4d0c3bfb126 --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/ClientCapabilityProvider.cs @@ -0,0 +1,108 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Linq; +using System.Web; + +using DotNetNuke.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.ClientCapability +{ + public abstract class ClientCapabilityProvider : IClientCapabilityProvider + { + #region Virtual Properties + + /// + /// Support detect the device whether is a tablet. + /// + public virtual bool SupportsTabletDetection + { + get + { + return true; + } + } + + #endregion + + #region Abstract Methods + /// + /// Returns ClientCapability based on userAgent + /// + public abstract IClientCapability GetClientCapability(string userAgent); + + /// + /// Returns ClientCapability based on ClientCapabilityId + /// + public abstract IClientCapability GetClientCapabilityById(string clientId); + + /// + /// Returns available Capability Values for every Capability Name + /// + /// + /// Dictionary of Capability Name along with List of possible values of the Capability + /// + /// Capability Name = mobile_browser, value = Safari, Andriod Webkit + public abstract IDictionary> GetAllClientCapabilityValues(); + + /// + /// Returns All available Client Capabilities present + /// + /// + /// List of IClientCapability present + /// + public abstract IQueryable GetAllClientCapabilities(); + + #endregion + + #region Virtual Methods + /// + /// Returns ClientCapability based on HttpRequest + /// + public virtual IClientCapability GetClientCapability(HttpRequest httpRequest) + { + IClientCapability clientCapability = GetClientCapability(httpRequest.UserAgent); + clientCapability.FacebookRequest = FacebookRequestController.GetFacebookDetailsFromRequest(httpRequest); + + return clientCapability; + } + #endregion + + #region static methods + public static ClientCapabilityProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + public static IClientCapability CurrentClientCapability + { + get + { + return Instance().GetClientCapability(HttpContext.Current.Request); + } + } + #endregion + } +} diff --git a/DNN Platform/Library/Services/ClientCapability/FacebookRequest.cs b/DNN Platform/Library/Services/ClientCapability/FacebookRequest.cs new file mode 100644 index 00000000000..1456bb495ac --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/FacebookRequest.cs @@ -0,0 +1,131 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security.Cryptography; +using System.Web; + +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.ClientCapability +{ + /// + /// Make modules that are aware of Facebook’s signed_request – a parameter that is POSTed to the web page being loaded in the iFrame, + /// giving it variables such as if the Page has been Liked, and the age range of the user. + /// + /// For more details visit http://developers.facebook.com/docs/authentication/signed_request/ + /// + public class FacebookRequest + { + #region Public Properties + + /// + /// Mechanism used to sign the request + /// + public string Algorithm { get; set; } + + /// + /// Token you can pass to the Graph API or the Legacy REST API. + /// + public string OauthToken{ get; set; } + + /// + /// DateTime when the oauth_token expires + /// + public DateTime Expires { get; set; } + + /// + /// DateTime when the request was signed. + /// + public DateTime IssuedAt { get; set; } + + /// + /// Facebook user identifier (UID) of the current user. + /// + public string UserID { get; set; } + + /// + /// User's locale. + /// + public string UserLocale { get; set; } + + /// + /// User's country. + /// + public string UserCountry { get; set; } + + /// + /// User's minimum age range. + /// + public long UserMinAge { get; set; } + + /// + /// User's maximum age range. + /// + public long UserMaxAge { get; set; } + + /// + /// Page's Id. Only available if your app is an iframe loaded in a Page tab. + /// + public string PageId { get; set; } + + /// + /// Has the user has liked the page. Only available if your app is an iframe loaded in a Page tab. + /// + public bool PageLiked { get; set; } + + /// + /// Is the page user Admin of the page. Only available if your app is an iframe loaded in a Page tab. + /// + public bool PageUserAdmin { get; set; } + + /// + /// Page ID if your app is loaded within. Only available if your app is written in FBML and loaded in a Page tab. + /// + public long ProfileId { get; set; } + + /// + /// Content of a query string parameter also called app_data. Usually specified when the application built the link to pass some data to itself. Only available if your app is an iframe loaded in a Page tab. + /// + public string AppData { get; set; } + + /// + /// Raw signed request coming from FaceBook in Post + /// + public string RawSignedRequest { get; set; } + + /// + /// Is this a valid FaceBook Request. Check this value prior to accessing any other property + /// + public bool IsValid { get; set; } + #endregion + + #region Public Methods + public bool IsValidSignature (string secretKey) + { + return FacebookRequestController.IsValidSignature(RawSignedRequest,secretKey); + } + #endregion + } + +} diff --git a/DNN Platform/Library/Services/ClientCapability/FacebookRequestController.cs b/DNN Platform/Library/Services/ClientCapability/FacebookRequestController.cs new file mode 100644 index 00000000000..b0df8a4c573 --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/FacebookRequestController.cs @@ -0,0 +1,199 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security.Cryptography; +using System.Web; + +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.ClientCapability +{ + /// + /// Make modules that are aware of Facebook’s signed_request – a parameter that is POSTed to the web page being loaded in the iFrame, + /// giving it variables such as if the Page has been Liked, and the age range of the user. + /// + /// + public class FacebookRequestController + { + public string AccessToken{ get; set; } + public DateTime Expires { get; set; } + public long UserID { get; set; } + public long ProfileId { get; set; } + public static string API_SECRET { get; set; } + public static string APP_ID { get; set; } + public string RawSignedRequest { get; set; } + const string SignedRequestParameter = "signed_request"; + public bool IsValid { get; set; } + + public static FacebookRequest GetFacebookDetailsFromRequest(HttpRequest Request) + { + if (Request == null) return null; + if (Request.RequestType != "POST") return null; + string rawSignedRequest = Request[SignedRequestParameter]; + return GetFacebookDetailsFromRequest(rawSignedRequest); + } + + public static FacebookRequest GetFacebookDetailsFromRequest(string rawSignedRequest) + { + if (string.IsNullOrEmpty(rawSignedRequest)) return null; + + try + { + var facebookRequest = new FacebookRequest(); + facebookRequest.RawSignedRequest = rawSignedRequest; + facebookRequest.IsValid = false; + + string[] signedRequestSplit = rawSignedRequest.Split('.'); + string expectedSignature = signedRequestSplit[0]; + string payload = signedRequestSplit[1]; + + var decodedJson = ReplaceSpecialCharactersInSignedRequest(payload); + var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length%4)%4, '=')); + + var encoding = new UTF8Encoding(); + FaceBookData faceBookData = encoding.GetString(base64JsonArray).FromJson(); + + if (faceBookData.algorithm == "HMAC-SHA256") + { + facebookRequest.IsValid = true; + facebookRequest.Algorithm = faceBookData.algorithm; + facebookRequest.ProfileId = faceBookData.profile_id; + facebookRequest.AppData = faceBookData.app_data; + facebookRequest.OauthToken = !string.IsNullOrEmpty(faceBookData.oauth_token) ? faceBookData.oauth_token : ""; + facebookRequest.Expires = ConvertToTimestamp(faceBookData.expires); + facebookRequest.IssuedAt = ConvertToTimestamp(faceBookData.issued_at); + facebookRequest.UserID = !string.IsNullOrEmpty(faceBookData.user_id) ? faceBookData.user_id : ""; + + facebookRequest.PageId = faceBookData.page.id; + facebookRequest.PageLiked = faceBookData.page.liked; + facebookRequest.PageUserAdmin = faceBookData.page.admin; + + facebookRequest.UserLocale = faceBookData.user.locale; + facebookRequest.UserCountry = faceBookData.user.country; + facebookRequest.UserMinAge = faceBookData.user.age.min; + facebookRequest.UserMaxAge = faceBookData.user.age.max; + } + + return facebookRequest; + } + catch(Exception) + { + return null; + } + } + + public static bool IsValidSignature(string rawSignedRequest, string secretKey) + { + if (!string.IsNullOrEmpty(secretKey) && !string.IsNullOrEmpty(rawSignedRequest)) + { + string[] signedRequestSplit = rawSignedRequest.Split('.'); + string expectedSignature = signedRequestSplit[0]; + string payload = signedRequestSplit[1]; + + if (!string.IsNullOrEmpty(expectedSignature) && !string.IsNullOrEmpty(payload)) + { + // Attempt to get same hash + var encoding = new UTF8Encoding(); + var hmac = SignWithHmac(encoding.GetBytes(payload), encoding.GetBytes(secretKey)); + var hmacBase64 = Base64UrlDecode(Convert.ToBase64String(hmac)); + if (hmacBase64 == expectedSignature) + return true; + } + } + + return false; + } + + /// + /// Converts the base 64 url encoded string to standard base 64 encoding. + /// + /// The encoded value. + /// The base 64 string. + private static string Base64UrlDecode(string encodedValue) + { + if (String.IsNullOrEmpty(encodedValue)) return null; + encodedValue = encodedValue.Replace('+', '-').Replace('/', '_').Replace("=", string.Empty).Trim(); + return encodedValue; + } + + private static string ReplaceSpecialCharactersInSignedRequest(string str) + { + return str.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/'); + } + + private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) + { + using (var hmacAlgorithm = new HMACSHA256(keyBody)) + { + hmacAlgorithm.ComputeHash(dataToSign); + return hmacAlgorithm.Hash; + } + } + /// + /// method for converting a System.DateTime value to a UNIX Timestamp + /// + /// date to convert + /// + private static DateTime ConvertToTimestamp(long value) + { + //create Timespan by subtracting the value provided from + //the Unix Epoch + DateTime epoc = new DateTime(1970, 1, 1, 0, 0, 0, 0); + return epoc.AddSeconds((double)value); + } + } + + struct Page + { + public string id { get; set; } + public bool liked { get; set; } + public bool admin { get; set; } + } + + struct Age + { + public long min { get; set; } + public long max { get; set; } + } + + struct User + { + public string locale { get; set; } + public string country { get; set; } + public Age age { get; set; } + } + + struct FaceBookData + { + public User user { get; set; } + public string algorithm { get; set; } + public long issued_at { get; set; } + public string user_id { get; set; } + public string oauth_token { get; set; } + public long expires { get; set; } + public string app_data { get; set; } + public Page page { get; set; } + public long profile_id { get; set; } + } +} diff --git a/DNN Platform/Library/Services/ClientCapability/IClientCapability.cs b/DNN Platform/Library/Services/ClientCapability/IClientCapability.cs new file mode 100644 index 00000000000..b66eb3bd0df --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/IClientCapability.cs @@ -0,0 +1,107 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Web; +#endregion + +namespace DotNetNuke.Services.ClientCapability +{ + /// + /// ClientCapability provides capabilities supported by the http requester (e.g. Mobile Device, TV, Desktop) + /// + /// + /// The capabilities are primarily derived based on UserAgent. + /// + public interface IClientCapability + { + /// + /// Unique ID of the client making request. + /// + string ID { get; set; } + + /// + /// User Agent of the client making request + /// + string UserAgent { get; set; } + + /// + /// Is request coming from a mobile device. + /// + bool IsMobile { get; set; } + + /// + /// Is request coming from a tablet device. + /// + bool IsTablet { get; set; } + + /// + /// Does the requesting device supports touch screen. + /// + bool IsTouchScreen { get; set; } + + /// + /// FacebookRequest property is filled when request is coming though Facebook iFrame (e.g. fan pages). + /// + /// + /// FacebookRequest property is populated based on data in "signed_request" headers coming from Facebook. + /// In order to ensure request is coming from Facebook, FacebookRequest.IsValidSignature method should be called with the secrety key provided by Facebook. + /// Most of the properties in IClientCapability doesnot apply to Facebook + /// + FacebookRequest FacebookRequest { get; set; } + + /// + /// ScreenResolution Width of the requester in Pixels. + /// + int ScreenResolutionWidthInPixels { get; set; } + + /// + /// ScreenResolution Height of the requester in Pixels. + /// + int ScreenResolutionHeightInPixels { get; set; } + + /// + /// Represents the name of the broweser in the request + /// + string BrowserName { get; set; } + + /// + /// Does requester support Flash. + /// + bool SupportsFlash { get; set; } + + /// + /// A key-value collection containing all capabilities supported by requester + /// + IDictionary Capabilities { get; set; } + + /// + /// Returns the request prefered HTML DTD + /// + string HtmlPreferedDTD { get; set; } + + /// + /// Http server variable used for SSL offloading - if this value is empty offloading is not enabled + /// + string SSLOffload { get; set; } + } +} diff --git a/DNN Platform/Library/Services/ClientCapability/IClientCapabilityProvider.cs b/DNN Platform/Library/Services/ClientCapability/IClientCapabilityProvider.cs new file mode 100644 index 00000000000..780ca71ac93 --- /dev/null +++ b/DNN Platform/Library/Services/ClientCapability/IClientCapabilityProvider.cs @@ -0,0 +1,61 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace DotNetNuke.Services.ClientCapability +{ + public interface IClientCapabilityProvider + { + /// + /// Returns ClientCapability based on userAgent + /// + IClientCapability GetClientCapability(string userAgent); + + /// + /// Returns ClientCapability based on ClientCapabilityId + /// + IClientCapability GetClientCapabilityById(string clientId); + + /// + /// Returns available Capability Values for every Capability Name + /// + /// + /// Dictionary of Capability Name along with List of possible values of the Capability + /// + /// Capability Name = mobile_browser, value = Safari, Andriod Webkit + IDictionary> GetAllClientCapabilityValues(); + + /// + /// Returns All available Client Capabilities present + /// + /// + /// List of IClientCapability present + /// + IQueryable GetAllClientCapabilities(); + + /// + /// Returns ClientCapability based on HttpRequest + /// + IClientCapability GetClientCapability(HttpRequest httpRequest); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/Config/EventQueueConfiguration.cs b/DNN Platform/Library/Services/EventQueue/Config/EventQueueConfiguration.cs new file mode 100644 index 00000000000..398df8ee11c --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/Config/EventQueueConfiguration.cs @@ -0,0 +1,183 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.Services.EventQueue.Config +{ + [Serializable] + internal class EventQueueConfiguration + { + #region "Constructors" + + internal EventQueueConfiguration() + { + PublishedEvents = new Dictionary(); + EventQueueSubscribers = new Dictionary(); + } + + #endregion + + #region "Public Properties" + + internal Dictionary EventQueueSubscribers { get; set; } + + internal Dictionary PublishedEvents { get; set; } + + #endregion + + #region "Private Methods" + + private void Deserialize(string configXml) + { + if (!String.IsNullOrEmpty(configXml)) + { + var xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(configXml); + foreach (XmlElement xmlItem in xmlDoc.SelectNodes("/EventQueueConfig/PublishedEvents/Event")) + { + var oPublishedEvent = new PublishedEvent(); + oPublishedEvent.EventName = xmlItem.SelectSingleNode("EventName").InnerText; + oPublishedEvent.Subscribers = xmlItem.SelectSingleNode("Subscribers").InnerText; + PublishedEvents.Add(oPublishedEvent.EventName, oPublishedEvent); + } + foreach (XmlElement xmlItem in xmlDoc.SelectNodes("/EventQueueConfig/EventQueueSubscribers/Subscriber")) + { + var oSubscriberInfo = new SubscriberInfo(); + oSubscriberInfo.ID = xmlItem.SelectSingleNode("ID").InnerText; + oSubscriberInfo.Name = xmlItem.SelectSingleNode("Name").InnerText; + oSubscriberInfo.Address = xmlItem.SelectSingleNode("Address").InnerText; + oSubscriberInfo.Description = xmlItem.SelectSingleNode("Description").InnerText; + oSubscriberInfo.PrivateKey = xmlItem.SelectSingleNode("PrivateKey").InnerText; + EventQueueSubscribers.Add(oSubscriberInfo.ID, oSubscriberInfo); + } + } + } + + public static void RegisterEventSubscription(EventQueueConfiguration config, string eventname, SubscriberInfo subscriber) + { + var e = new PublishedEvent(); + e.EventName = eventname; + e.Subscribers = subscriber.ID; + config.PublishedEvents.Add(e.EventName, e); + if (!config.EventQueueSubscribers.ContainsKey(subscriber.ID)) + { + config.EventQueueSubscribers.Add(subscriber.ID, subscriber); + } + } + + private string Serialize() + { + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Document; + settings.Indent = true; + settings.CloseOutput = true; + settings.OmitXmlDeclaration = false; + + var sb = new StringBuilder(); + + XmlWriter writer = XmlWriter.Create(sb, settings); + writer.WriteStartElement("EventQueueConfig"); + + writer.WriteStartElement("PublishedEvents"); + foreach (string key in PublishedEvents.Keys) + { + writer.WriteStartElement("Event"); + + writer.WriteElementString("EventName", PublishedEvents[key].EventName); + writer.WriteElementString("Subscribers", PublishedEvents[key].Subscribers); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.WriteStartElement("EventQueueSubscribers"); + foreach (string key in EventQueueSubscribers.Keys) + { + writer.WriteStartElement("Subscriber"); + + writer.WriteElementString("ID", EventQueueSubscribers[key].ID); + writer.WriteElementString("Name", EventQueueSubscribers[key].Name); + writer.WriteElementString("Address", EventQueueSubscribers[key].Address); + writer.WriteElementString("Description", EventQueueSubscribers[key].Description); + writer.WriteElementString("PrivateKey", EventQueueSubscribers[key].PrivateKey); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + //Close EventQueueConfig + writer.WriteEndElement(); + + writer.Close(); + + return sb.ToString(); + } + #endregion + internal static EventQueueConfiguration GetConfig() + { + var config = (EventQueueConfiguration) DataCache.GetCache("EventQueueConfig"); + if ((config == null)) + { + string filePath = Globals.HostMapPath + "EventQueue\\EventQueue.config"; + if (File.Exists(filePath)) + { + config = new EventQueueConfiguration(); + //Deserialize into EventQueueConfiguration + config.Deserialize(FileSystemUtils.ReadFile(filePath)); + //Set back into Cache + DataCache.SetCache("EventQueueConfig", config, new DNNCacheDependency(filePath)); + } + else + { + //make a default config file + config = new EventQueueConfiguration(); + config.PublishedEvents = new Dictionary(); + config.EventQueueSubscribers = new Dictionary(); + var subscriber = new SubscriberInfo("DNN Core"); + RegisterEventSubscription(config, "Application_Start", subscriber); + RegisterEventSubscription(config, "Application_Start_FirstRequest", subscriber); + SaveConfig(config, filePath); + } + } + return config; + } + + internal static void SaveConfig(EventQueueConfiguration config, string filePath) + { + StreamWriter oStream = File.CreateText(filePath); + oStream.WriteLine(config.Serialize()); + oStream.Close(); + //Set back into Cache + DataCache.SetCache("EventQueueConfig", config, new DNNCacheDependency(filePath)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/Config/PublishedEvent.cs b/DNN Platform/Library/Services/EventQueue/Config/PublishedEvent.cs new file mode 100644 index 00000000000..29dbd152668 --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/Config/PublishedEvent.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.Serialization; + +#endregion + +namespace DotNetNuke.Services.EventQueue.Config +{ + [Serializable] + public class PublishedEvent + { + public string EventName { get; set; } + + public string Subscribers { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/Config/SubscriberInfo.cs b/DNN Platform/Library/Services/EventQueue/Config/SubscriberInfo.cs new file mode 100644 index 00000000000..bdcfe428854 --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/Config/SubscriberInfo.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.EventQueue.Config +{ + [Serializable] + public class SubscriberInfo + { + public SubscriberInfo() + { + ID = Guid.NewGuid().ToString(); + Name = ""; + Description = ""; + Address = ""; + var oPortalSecurity = new PortalSecurity(); + PrivateKey = oPortalSecurity.CreateKey(16); + } + + public SubscriberInfo(string subscriberName) : this() + { + Name = subscriberName; + } + + public string ID { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } + + public string Address { get; set; } + + public string PrivateKey { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/EventMessage.cs b/DNN Platform/Library/Services/EventQueue/EventMessage.cs new file mode 100644 index 00000000000..bbe6be095f6 --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/EventMessage.cs @@ -0,0 +1,352 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Specialized; +using System.IO; +using System.Text; +using System.Xml; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.EventQueue +{ + public enum MessagePriority + { + High, + Medium, + Low + } + + [Serializable] + public class EventMessage + { + #region "Private Members" + + private NameValueCollection _attributes; + private string _authorizedRoles = Null.NullString; + private string _body = Null.NullString; + private int _eventMessageID = Null.NullInteger; + private string _exceptionMessage = Null.NullString; + private DateTime _expirationDate; + private MessagePriority _priority = MessagePriority.Low; + private string _processorCommand = Null.NullString; + private string _processorType = Null.NullString; + private string _sender = Null.NullString; + private DateTime _sentDate; + private string _subscribers = Null.NullString; + + #endregion + + #region "Constructors" + + public EventMessage() + { + _attributes = new NameValueCollection(); + } + + #endregion + + #region "Public Properties" + + public int EventMessageID + { + get + { + return _eventMessageID; + } + set + { + _eventMessageID = value; + } + } + + public string ProcessorType + { + get + { + if (_processorType == null) + { + return string.Empty; + } + else + { + return _processorType; + } + } + set + { + _processorType = value; + } + } + + public string ProcessorCommand + { + get + { + if (_processorCommand == null) + { + return string.Empty; + } + else + { + return _processorCommand; + } + } + set + { + _processorCommand = value; + } + } + + public string Body + { + get + { + if (_body == null) + { + return string.Empty; + } + else + { + return _body; + } + } + set + { + _body = value; + } + } + + public string Sender + { + get + { + if (_sender == null) + { + return string.Empty; + } + else + { + return _sender; + } + } + set + { + _sender = value; + } + } + + public string Subscribers + { + get + { + if (_subscribers == null) + { + return string.Empty; + } + else + { + return _subscribers; + } + } + set + { + _subscribers = value; + } + } + + public string AuthorizedRoles + { + get + { + if (_authorizedRoles == null) + { + return string.Empty; + } + else + { + return _authorizedRoles; + } + } + set + { + _authorizedRoles = value; + } + } + + public MessagePriority Priority + { + get + { + return _priority; + } + set + { + _priority = value; + } + } + + public string ExceptionMessage + { + get + { + if (_exceptionMessage == null) + { + return string.Empty; + } + else + { + return _exceptionMessage; + } + } + set + { + _exceptionMessage = value; + } + } + + public DateTime SentDate + { + get + { + return _sentDate.ToLocalTime(); + } + set + { + _sentDate = value.ToUniversalTime(); + } + } + + public DateTime ExpirationDate + { + get + { + return _expirationDate.ToLocalTime(); + } + set + { + _expirationDate = value.ToUniversalTime(); + } + } + + public NameValueCollection Attributes + { + get + { + return _attributes; + } + set + { + _attributes = value; + } + } + + #endregion + + #region "Public Methods" + + public void DeserializeAttributes(string configXml) + { + string attName = Null.NullString; + string attValue = Null.NullString; + var settings = new XmlReaderSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + XmlReader reader = XmlReader.Create(new StringReader(configXml)); + reader.ReadStartElement("Attributes"); + if (!reader.IsEmptyElement) + { + //Loop throug the Attributes + do + { + reader.ReadStartElement("Attribute"); + + //Load it from the Xml + reader.ReadStartElement("Name"); + attName = reader.ReadString(); + reader.ReadEndElement(); + if (!reader.IsEmptyElement) + { + reader.ReadStartElement("Value"); + attValue = reader.ReadString(); + reader.ReadEndElement(); + } + else + { + reader.Read(); + } + + //Add attribute to the collection + _attributes.Add(attName, attValue); + } while (reader.ReadToNextSibling("Attribute")); + } + } + + public string SerializeAttributes() + { + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.OmitXmlDeclaration = true; + + var sb = new StringBuilder(); + + XmlWriter writer = XmlWriter.Create(sb, settings); + writer.WriteStartElement("Attributes"); + + foreach (string key in Attributes.Keys) + { + writer.WriteStartElement("Attribute"); + + //Write the Name element + writer.WriteElementString("Name", key); + + //Write the Value element + if (Attributes[key].IndexOfAny("<'>\"&".ToCharArray()) > -1) + { + writer.WriteStartElement("Value"); + writer.WriteCData(Attributes[key]); + writer.WriteEndElement(); + } + else + { + //Write value + writer.WriteElementString("Value", Attributes[key]); + } + + //Close the Attribute node + writer.WriteEndElement(); + } + + //Close the Attributes node + writer.WriteEndElement(); + + //Close Writer + writer.Close(); + + return sb.ToString(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/EventMessageCollection.cs b/DNN Platform/Library/Services/EventQueue/EventMessageCollection.cs new file mode 100644 index 00000000000..f0e5f248a33 --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/EventMessageCollection.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.EventQueue +{ + public class EventMessageCollection : CollectionBase + { + public virtual EventMessage this[int index] + { + get + { + return (EventMessage) base.List[index]; + } + set + { + base.List[index] = value; + } + } + + public void Add(EventMessage message) + { + InnerList.Add(message); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/EventMessageProcessor.cs b/DNN Platform/Library/Services/EventQueue/EventMessageProcessor.cs new file mode 100644 index 00000000000..010f6baed0b --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/EventMessageProcessor.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.EventQueue +{ + /// + /// Basic class of EventMessageProcessor. + /// + public abstract class EventMessageProcessorBase + { + public abstract bool ProcessMessage(EventMessage message); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/EventQueue/EventQueueController.cs b/DNN Platform/Library/Services/EventQueue/EventQueueController.cs new file mode 100644 index 00000000000..5800a8b72f7 --- /dev/null +++ b/DNN Platform/Library/Services/EventQueue/EventQueueController.cs @@ -0,0 +1,310 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework; +using DotNetNuke.Services.EventQueue.Config; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.EventQueue +{ + /// + /// EventQueueController provides business layer of event queue. + /// + /// + /// Sometimes when your module running in DotNetNuke,and contains some operats didn't want to execute immediately. + /// e.g: after your module installed into system, and some component you want to registed when the application restart, + /// you can send an 'Application_Start' message, so your specific operation will be executed when application has been restart. + /// + /// + /// + /// var oAppStartMessage = new EventMessage + /// { + /// Sender = sender, + /// Priority = MessagePriority.High, + /// ExpirationDate = DateTime.Now.AddYears(-1), + /// SentDate = DateTime.Now, + /// Body = "", + /// ProcessorType = "DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke", + /// ProcessorCommand = "UpdateSupportedFeatures" + /// }; + /// oAppStartMessage.Attributes.Add("BusinessControllerClass", desktopModuleInfo.BusinessControllerClass); + /// oAppStartMessage.Attributes.Add("DesktopModuleId", desktopModuleInfo.DesktopModuleID.ToString()); + /// EventQueueController.SendMessage(oAppStartMessage, "Application_Start"); + /// if ((forceAppRestart)) + /// { + /// Config.Touch(); + /// } + /// + /// + public class EventQueueController + { + #region "Private Shared Methods" + + private static EventMessage FillMessage(IDataReader dr, bool CheckForOpenDataReader) + { + EventMessage message; + + //read datareader + bool canContinue = true; + if (CheckForOpenDataReader) + { + canContinue = false; + if (dr.Read()) + { + canContinue = true; + } + } + if (canContinue) + { + message = new EventMessage(); + message.EventMessageID = Convert.ToInt32(Null.SetNull(dr["EventMessageID"], message.EventMessageID)); + message.Priority = (MessagePriority) Enum.Parse(typeof (MessagePriority), Convert.ToString(Null.SetNull(dr["Priority"], message.Priority))); + message.ProcessorType = Convert.ToString(Null.SetNull(dr["ProcessorType"], message.ProcessorType)); + message.ProcessorCommand = Convert.ToString(Null.SetNull(dr["ProcessorCommand"], message.ProcessorCommand)); + message.Body = Convert.ToString(Null.SetNull(dr["Body"], message.Body)); + message.Sender = Convert.ToString(Null.SetNull(dr["Sender"], message.Sender)); + message.Subscribers = Convert.ToString(Null.SetNull(dr["Subscriber"], message.Subscribers)); + message.AuthorizedRoles = Convert.ToString(Null.SetNull(dr["AuthorizedRoles"], message.AuthorizedRoles)); + message.ExceptionMessage = Convert.ToString(Null.SetNull(dr["ExceptionMessage"], message.ExceptionMessage)); + message.SentDate = Convert.ToDateTime(Null.SetNull(dr["SentDate"], message.SentDate)); + message.ExpirationDate = Convert.ToDateTime(Null.SetNull(dr["ExpirationDate"], message.ExpirationDate)); + + //Deserialize Attributes + string xmlAttributes = Null.NullString; + xmlAttributes = Convert.ToString(Null.SetNull(dr["Attributes"], xmlAttributes)); + message.DeserializeAttributes(xmlAttributes); + } + else + { + message = null; + } + return message; + } + + private static EventMessageCollection FillMessageCollection(IDataReader dr) + { + var arr = new EventMessageCollection(); + try + { + EventMessage obj; + while (dr.Read()) + { + //fill business object + obj = FillMessage(dr, false); + //add to collection + arr.Add(obj); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + finally + { + //close datareader + CBO.CloseDataReader(dr, true); + } + return arr; + } + + private static string[] GetSubscribers(string eventName) + { + //Get the subscribers to this event + string[] subscribers = null; + PublishedEvent publishedEvent = null; + if (EventQueueConfiguration.GetConfig().PublishedEvents.TryGetValue(eventName, out publishedEvent)) + { + subscribers = publishedEvent.Subscribers.Split(";".ToCharArray()); + } + else + { + subscribers = new string[] {}; + } + return subscribers; + } + + #endregion + + #region "Public Shared Methods" + + /// + /// Gets the messages. + /// + /// Name of the event. + /// event message collection. + public static EventMessageCollection GetMessages(string eventName) + { + return FillMessageCollection(DataProvider.Instance().GetEventMessages(eventName)); + } + + /// + /// Gets the messages. + /// + /// Name of the event. + /// The subscriber id. + /// + public static EventMessageCollection GetMessages(string eventName, string subscriberId) + { + return FillMessageCollection(DataProvider.Instance().GetEventMessagesBySubscriber(eventName, subscriberId)); + } + + /// + /// Processes the messages. + /// + /// Name of the event. + /// + public static bool ProcessMessages(string eventName) + { + return ProcessMessages(GetMessages(eventName)); + } + + /// + /// Processes the messages. + /// + /// Name of the event. + /// The subscriber id. + /// + public static bool ProcessMessages(string eventName, string subscriberId) + { + return ProcessMessages(GetMessages(eventName, subscriberId)); + } + + /// + /// Processes the messages. + /// + /// The event messages. + /// + public static bool ProcessMessages(EventMessageCollection eventMessages) + { + bool success = Null.NullBoolean; + EventMessage message; + for (int messageNo = 0; messageNo <= eventMessages.Count - 1; messageNo++) + { + message = eventMessages[messageNo]; + try + { + object oMessageProcessor = Reflection.CreateObject(message.ProcessorType, message.ProcessorType); + if (!((EventMessageProcessorBase) oMessageProcessor).ProcessMessage(message)) + { + throw new Exception(); + } + + //Set Message comlete so it is not run a second time + DataProvider.Instance().SetEventMessageComplete(message.EventMessageID); + + success = true; + } + catch + { + //log if message could not be processed + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("EventQueue.ProcessMessage", "Message Processing Failed"); + objEventLogInfo.AddProperty("ProcessorType", message.ProcessorType); + objEventLogInfo.AddProperty("Body", message.Body); + objEventLogInfo.AddProperty("Sender", message.Sender); + foreach (string key in message.Attributes.Keys) + { + objEventLogInfo.AddProperty(key, message.Attributes[key]); + } + if (!String.IsNullOrEmpty(message.ExceptionMessage)) + { + objEventLogInfo.AddProperty("ExceptionMessage", message.ExceptionMessage); + } + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLog.AddLog(objEventLogInfo); + if (message.ExpirationDate < DateTime.Now) + { + //Set Message comlete so it is not run a second time + DataProvider.Instance().SetEventMessageComplete(message.EventMessageID); + } + } + } + return success; + } + + /// + /// Sends the message. + /// + /// The message. + /// Name of the event. + /// + public static bool SendMessage(EventMessage message, string eventName) + { + //set the sent date if it wasn't set by the sender + if (message.SentDate != null) + { + message.SentDate = DateTime.Now; + } + + //Get the subscribers to this event + string[] subscribers = GetSubscribers(eventName); + + //send a message for each subscriber of the specified event + int intMessageID = Null.NullInteger; + bool success = true; + try + { + for (int indx = 0; indx <= subscribers.Length - 1; indx++) + { + intMessageID = DataProvider.Instance().AddEventMessage(eventName, + (int) message.Priority, + message.ProcessorType, + message.ProcessorCommand, + message.Body, + message.Sender, + subscribers[indx], + message.AuthorizedRoles, + message.ExceptionMessage, + message.SentDate, + message.ExpirationDate, + message.SerializeAttributes()); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + success = Null.NullBoolean; + } + return success; + } + + #endregion + + #region "Obsolete Methods" + + [Obsolete("This method is obsolete. Use Sendmessage(message, eventName) instead")] + public bool SendMessage(EventMessage message, string eventName, bool encryptMessage) + { + return SendMessage(message, eventName); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/BasePortalException.cs b/DNN Platform/Library/Services/Exceptions/BasePortalException.cs new file mode 100644 index 00000000000..b66311509d4 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/BasePortalException.cs @@ -0,0 +1,311 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Runtime.Serialization; +using System.Security.Permissions; +using System.Web; +using System.Xml.Serialization; + +using DotNetNuke.Application; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework.Providers; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + /// + /// Base Portal Exception. + /// + public class BasePortalException : Exception + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (BasePortalException)); + private string m_InnerExceptionString; + private string m_Message; + private string m_Source; + private string m_StackTrace; + + //default constructor + public BasePortalException() + { + } + + //constructor with exception message + public BasePortalException(string message) : base(message) + { + InitializePrivateVariables(); + } + + //constructor with message and inner exception + public BasePortalException(string message, Exception inner) : base(message, inner) + { + InitializePrivateVariables(); + } + + protected BasePortalException(SerializationInfo info, StreamingContext context) : base(info, context) + { + InitializePrivateVariables(); + AssemblyVersion = info.GetString("m_AssemblyVersion"); + PortalID = info.GetInt32("m_PortalID"); + PortalName = info.GetString("m_PortalName"); + UserID = info.GetInt32("m_UserID"); + UserName = info.GetString("m_Username"); + ActiveTabID = info.GetInt32("m_ActiveTabID"); + ActiveTabName = info.GetString("m_ActiveTabName"); + RawURL = info.GetString("m_RawURL"); + AbsoluteURL = info.GetString("m_AbsoluteURL"); + AbsoluteURLReferrer = info.GetString("m_AbsoluteURLReferrer"); + UserAgent = info.GetString("m_UserAgent"); + DefaultDataProvider = info.GetString("m_DefaultDataProvider"); + ExceptionGUID = info.GetString("m_ExceptionGUID"); + m_InnerExceptionString = info.GetString("m_InnerExceptionString"); + FileName = info.GetString("m_FileName"); + FileLineNumber = info.GetInt32("m_FileLineNumber"); + FileColumnNumber = info.GetInt32("m_FileColumnNumber"); + Method = info.GetString("m_Method"); + m_StackTrace = info.GetString("m_StackTrace"); + m_Message = info.GetString("m_Message"); + m_Source = info.GetString("m_Source"); + } + + public string AssemblyVersion { get; private set; } + + public int PortalID { get; private set; } + + public string PortalName { get; private set; } + + public int UserID { get; private set; } + + public string UserName { get; private set; } + + public int ActiveTabID { get; private set; } + + public string ActiveTabName { get; private set; } + + public string RawURL { get; private set; } + + public string AbsoluteURL { get; private set; } + + public string AbsoluteURLReferrer { get; private set; } + + public string UserAgent { get; private set; } + + public string DefaultDataProvider { get; private set; } + + public string ExceptionGUID { get; private set; } + + public string FileName { get; private set; } + + public int FileLineNumber { get; private set; } + + public int FileColumnNumber { get; private set; } + + public string Method { get; private set; } + + [XmlIgnore] + public new MethodBase TargetSite + { + get + { + return base.TargetSite; + } + } + + private void InitializePrivateVariables() + { + //Try and get the Portal settings from context + //If an error occurs getting the context then set the variables to -1 + try + { + var context = HttpContext.Current; + var portalSettings = PortalController.GetCurrentPortalSettings(); + var innerException = new Exception(Message, this); + while (innerException.InnerException != null) + { + innerException = innerException.InnerException; + } + var exceptionInfo = Exceptions.GetExceptionInfo(innerException); + + AssemblyVersion = DotNetNukeContext.Current.Application.Version.ToString(3); + if (portalSettings != null) + { + PortalID = portalSettings.PortalId; + PortalName = portalSettings.PortalName; + ActiveTabID = portalSettings.ActiveTab.TabID; + ActiveTabName = portalSettings.ActiveTab.TabName; + } + else + { + PortalID = -1; + PortalName = ""; + ActiveTabID = -1; + ActiveTabName = ""; + } + + var currentUserInfo = UserController.GetCurrentUserInfo(); + UserID = (currentUserInfo != null) ? currentUserInfo.UserID : -1; + + if (UserID != -1) + { + currentUserInfo = UserController.GetUserById(PortalID, UserID); + UserName = currentUserInfo != null ? currentUserInfo.Username : ""; + } + else + { + UserName = ""; + } + + if (context != null) + { + RawURL = context.Request.RawUrl; + AbsoluteURL = context.Request.Url.AbsolutePath; + if (context.Request.UrlReferrer != null) + { + AbsoluteURLReferrer = context.Request.UrlReferrer.AbsoluteUri; + } + UserAgent = context.Request.UserAgent; + } + else + { + RawURL = ""; + AbsoluteURL = ""; + AbsoluteURLReferrer = ""; + UserAgent = ""; + } + try + { + ProviderConfiguration objProviderConfiguration = ProviderConfiguration.GetProviderConfiguration("data"); + string strTypeName = ((Provider)objProviderConfiguration.Providers[objProviderConfiguration.DefaultProvider]).Type; + DefaultDataProvider = strTypeName; + + } + catch (Exception exc) + { + Logger.Error(exc); + + DefaultDataProvider = ""; + } + + ExceptionGUID = Guid.NewGuid().ToString(); + + if (exceptionInfo != null) + { + FileName = exceptionInfo.FileName; + FileLineNumber = exceptionInfo.FileLineNumber; + FileColumnNumber = exceptionInfo.FileColumnNumber; + Method = exceptionInfo.Method; + } + else + { + FileName = ""; + FileLineNumber = -1; + FileColumnNumber = -1; + Method = ""; + } + + try + { + m_StackTrace = StackTrace; + } + catch (Exception exc) + { + Logger.Error(exc); + + m_StackTrace = ""; + } + try + { + m_Message = Message; + } + catch (Exception exc) + { + Logger.Error(exc); + + m_Message = ""; + } + try + { + m_Source = Source; + } + catch (Exception exc) + { + Logger.Error(exc); + + m_Source = ""; + } + } + catch (Exception exc) + { + PortalID = -1; + UserID = -1; + AssemblyVersion = "-1"; + ActiveTabID = -1; + ActiveTabName = ""; + RawURL = ""; + AbsoluteURL = ""; + AbsoluteURLReferrer = ""; + UserAgent = ""; + DefaultDataProvider = ""; + ExceptionGUID = ""; + FileName = ""; + FileLineNumber = -1; + FileColumnNumber = -1; + Method = ""; + m_StackTrace = ""; + m_Message = ""; + m_Source = ""; + Logger.Error(exc); + + } + } + + //public override void GetObjectData(SerializationInfo info, StreamingContext context) + //{ + // //Serialize this class' state and then call the base class GetObjectData + // info.AddValue("m_AssemblyVersion", AssemblyVersion, typeof (string)); + // info.AddValue("m_PortalID", PortalID, typeof (Int32)); + // info.AddValue("m_PortalName", PortalName, typeof (string)); + // info.AddValue("m_UserID", UserID, typeof (Int32)); + // info.AddValue("m_UserName", UserName, typeof (string)); + // info.AddValue("m_ActiveTabID", ActiveTabID, typeof (Int32)); + // info.AddValue("m_ActiveTabName", ActiveTabName, typeof (string)); + // info.AddValue("m_RawURL", RawURL, typeof (string)); + // info.AddValue("m_AbsoluteURL", AbsoluteURL, typeof (string)); + // info.AddValue("m_AbsoluteURLReferrer", AbsoluteURLReferrer, typeof (string)); + // info.AddValue("m_UserAgent", UserAgent, typeof (string)); + // info.AddValue("m_DefaultDataProvider", DefaultDataProvider, typeof (string)); + // info.AddValue("m_ExceptionGUID", ExceptionGUID, typeof (string)); + // info.AddValue("m_FileName", FileName, typeof (string)); + // info.AddValue("m_FileLineNumber", FileLineNumber, typeof (Int32)); + // info.AddValue("m_FileColumnNumber", FileColumnNumber, typeof (Int32)); + // info.AddValue("m_Method", Method, typeof (string)); + // info.AddValue("m_StackTrace", m_StackTrace, typeof (string)); + // info.AddValue("m_Message", m_Message, typeof (string)); + // info.AddValue("m_Source", m_Source, typeof (string)); + // base.GetObjectData(info, context); + //} + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/ErrorContainer.cs b/DNN Platform/Library/Services/Exceptions/ErrorContainer.cs new file mode 100644 index 00000000000..87337e11475 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/ErrorContainer.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; +using System.Web.UI; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.UI.Skins.Controls; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class ErrorContainer : Control + { + public ErrorContainer(string strError) + { + Container = FormatException(strError); + } + + public ErrorContainer(string strError, Exception exc) + { + Container = FormatException(strError, exc); + } + + public ErrorContainer(PortalSettings _PortalSettings, string strError, Exception exc) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + if (objUserInfo.IsSuperUser) + { + Container = FormatException(strError, exc); + } + else + { + Container = FormatException(strError); + } + } + + public ModuleMessage Container { get; set; } + + private ModuleMessage FormatException(string strError) + { + ModuleMessage m; + m = UI.Skins.Skin.GetModuleMessageControl(Localization.Localization.GetString("ErrorOccurred"), strError, ModuleMessage.ModuleMessageType.RedError); + return m; + } + + private ModuleMessage FormatException(string strError, Exception exc) + { + ModuleMessage m; + if (exc != null) + { + m = UI.Skins.Skin.GetModuleMessageControl(strError, HttpUtility.HtmlEncode(exc.ToString()), ModuleMessage.ModuleMessageType.RedError); + } + else + { + m = UI.Skins.Skin.GetModuleMessageControl(Localization.Localization.GetString("ErrorOccurred"), strError, ModuleMessage.ModuleMessageType.RedError); + } + return m; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/ExceptionInfo.cs b/DNN Platform/Library/Services/Exceptions/ExceptionInfo.cs new file mode 100644 index 00000000000..475f71ccd0c --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/ExceptionInfo.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + [Serializable] + public class ExceptionInfo + { + private int _FileColumnNumber; + private int _FileLineNumber; + private string _FileName; + private string _Method; + + public string Method + { + get + { + return _Method; + } + set + { + _Method = value; + } + } + + public int FileColumnNumber + { + get + { + return _FileColumnNumber; + } + set + { + _FileColumnNumber = value; + } + } + + public string FileName + { + get + { + return _FileName; + } + set + { + _FileName = value; + } + } + + public int FileLineNumber + { + get + { + return _FileLineNumber; + } + set + { + _FileLineNumber = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/Exceptions.cs b/DNN Platform/Library/Services/Exceptions/Exceptions.cs new file mode 100644 index 00000000000..30bc6306be8 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/Exceptions.cs @@ -0,0 +1,489 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Threading; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.UI.Modules; + +using Microsoft.VisualBasic.CompilerServices; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + /// + /// Exceptions class provides operation to log most of the exceptions occured in system. + /// + /// + /// + /// For most developers, there is a hard problem need to face to is that our product will run on many and many servers with + /// much different environment, such as hardware, network, system version, framework version and so on, so there is many of reasons + /// will make our application throw lof of exceptions,even will stop our app to working. so when some error occured, we need a way + /// to find out the reason, we know we need to log all the exception, but the point is how to log useful information, you should log + /// the information what you need to location the code caught the error, but DONOT just log 'ERROR'. so we provide a full support of + /// exception log system. when error occured, we can found the detail information in event log and can locationt the error quickly. + /// + /// + /// Current we immplement lot of custom exception to use in different levels: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [StandardModule] + public sealed class Exceptions + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Exceptions)); + /// + /// Gets the exception info. + /// + /// The exception. + /// Exception info. + public static ExceptionInfo GetExceptionInfo(Exception e) + { + var objExceptionInfo = new ExceptionInfo(); + + while (e.InnerException != null) + { + e = e.InnerException; + } + var st = new StackTrace(e, true); + StackFrame sf = st.GetFrame(0); + if (sf != null) + { + try + { + //Get the corresponding method for that stack frame. + MemberInfo mi = sf.GetMethod(); + //Get the namespace where that method is defined. + string res = mi.DeclaringType.Namespace + "."; + //Append the type name. + res += mi.DeclaringType.Name + "."; + //Append the name of the method. + res += mi.Name; + objExceptionInfo.Method = res; + } + catch (Exception exc) + { + Logger.Error(exc); + + objExceptionInfo.Method = "N/A - Reflection Permission required"; + } + if (!String.IsNullOrEmpty(sf.GetFileName())) + { + objExceptionInfo.FileName = sf.GetFileName(); + objExceptionInfo.FileColumnNumber = sf.GetFileColumnNumber(); + objExceptionInfo.FileLineNumber = sf.GetFileLineNumber(); + } + } + return objExceptionInfo; + } + + /// + /// Threads the abort check if the exception is a ThreadAbortCheck. + /// + /// The exc. + /// + private static bool ThreadAbortCheck(Exception exc) + { + if (exc is ThreadAbortException) + { + Thread.ResetAbort(); + return true; + } + else + { + return false; + } + } + + public static void ProcessHttpException() + { + var notFoundErrorString = Localization.Localization.GetString("ResourceNotFound", Localization.Localization.SharedResourceFile); + var exc = new HttpException(404, notFoundErrorString); + ProcessHttpException(exc, HttpContext.Current.Request.RawUrl); + } + + public static void ProcessHttpException(string URL) + { + var notFoundErrorString = Localization.Localization.GetString("ResourceNotFound", Localization.Localization.SharedResourceFile); + var exc = new HttpException(404, notFoundErrorString); + ProcessHttpException(exc, URL); + } + + public static void ProcessHttpException(HttpException exc) + { + ProcessHttpException(exc, HttpContext.Current.Request.RawUrl); + } + + public static void ProcessHttpException(HttpRequest request) + { + var notFoundErrorString = Localization.Localization.GetString("ResourceNotFound", Localization.Localization.SharedResourceFile); + var exc = new HttpException(404, notFoundErrorString); + ProcessHttpException(exc, request.RawUrl); + } + + private static void ProcessHttpException(HttpException exc, string URL) + { + var notFoundErrorString = Localization.Localization.GetString("ResourceNotFound", Localization.Localization.SharedResourceFile); + Logger.Error(notFoundErrorString + ": - " + URL, exc); + + var eventLogInfo = new LogInfo + { + BypassBuffering = true, + LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString() + }; + eventLogInfo.LogProperties.Add(new LogDetailInfo(notFoundErrorString, "URL")); + var context = HttpContext.Current; + if (context != null) + { + eventLogInfo.LogProperties.Add(new LogDetailInfo("URL:", URL)); + } + var eventLogController = new EventLogController(); + eventLogController.AddLog(eventLogInfo); + + + throw exc; + } + + /// + /// Processes the module load exception. + /// + /// The portal module base. + /// The exc. + public static void ProcessModuleLoadException(PortalModuleBase objPortalModuleBase, Exception exc) + { + ProcessModuleLoadException((Control) objPortalModuleBase, exc); + } + + /// + /// Processes the module load exception. + /// + /// The portal module base. + /// The exc. + /// if set to true display error message. + public static void ProcessModuleLoadException(PortalModuleBase objPortalModuleBase, Exception exc, bool DisplayErrorMessage) + { + ProcessModuleLoadException((Control) objPortalModuleBase, exc, DisplayErrorMessage); + } + + /// + /// Processes the module load exception. + /// + /// The friendly message. + /// The obj portal module base. + /// The exc. + /// if set to true display error message. + public static void ProcessModuleLoadException(string FriendlyMessage, PortalModuleBase objPortalModuleBase, Exception exc, bool DisplayErrorMessage) + { + ProcessModuleLoadException(FriendlyMessage, (Control) objPortalModuleBase, exc, DisplayErrorMessage); + } + + /// + /// Processes the module load exception. + /// + /// The CTRL. + /// The exc. + public static void ProcessModuleLoadException(Control ctrl, Exception exc) + { + //Exit Early if ThreadAbort Exception + if (ThreadAbortCheck(exc)) + { + return; + } + ProcessModuleLoadException(ctrl, exc, true); + } + + /// + /// Processes the module load exception. + /// + /// The CTRL. + /// The exc. + /// if set to true [display error message]. + public static void ProcessModuleLoadException(Control ctrl, Exception exc, bool DisplayErrorMessage) + { + //Exit Early if ThreadAbort Exception + if (ThreadAbortCheck(exc)) + { + return; + } + string friendlyMessage = Localization.Localization.GetString("ErrorOccurred"); + var ctrlModule = ctrl as IModuleControl; + if (ctrlModule == null) + { + //Regular Control + friendlyMessage = Localization.Localization.GetString("ErrorOccurred"); + } + else + { + //IModuleControl + string moduleTitle = Null.NullString; + if (ctrlModule != null && ctrlModule.ModuleContext.Configuration != null) + { + moduleTitle = ctrlModule.ModuleContext.Configuration.ModuleTitle; + } + friendlyMessage = string.Format(Localization.Localization.GetString("ModuleUnavailable"), moduleTitle); + } + ProcessModuleLoadException(friendlyMessage, ctrl, exc, DisplayErrorMessage); + } + + /// + /// Processes the module load exception. + /// + /// The friendly message. + /// The CTRL. + /// The exc. + public static void ProcessModuleLoadException(string FriendlyMessage, Control ctrl, Exception exc) + { + //Exit Early if ThreadAbort Exception + if (ThreadAbortCheck(exc)) + { + return; + } + ProcessModuleLoadException(FriendlyMessage, ctrl, exc, true); + } + + /// + /// Processes the module load exception. + /// + /// The friendly message. + /// The CTRL. + /// The exc. + /// if set to true display error message. + public static void ProcessModuleLoadException(string FriendlyMessage, Control ctrl, Exception exc, bool DisplayErrorMessage) + { + //Exit Early if ThreadAbort Exception + if (ThreadAbortCheck(exc)) + { + return; + } + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + try + { + if (!Host.UseCustomErrorMessages) + { + throw new ModuleLoadException(FriendlyMessage, exc); + } + else + { + var ctrlModule = ctrl as IModuleControl; + ModuleLoadException lex = null; + if (ctrlModule == null) + { + lex = new ModuleLoadException(exc.Message, exc); + } + else + { + lex = new ModuleLoadException(exc.Message, exc, ctrlModule.ModuleContext.Configuration); + } + //publish the exception + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(lex); + //Some modules may want to suppress an error message + //and just log the exception. + if (DisplayErrorMessage) + { + PlaceHolder ErrorPlaceholder = null; + if (ctrl.Parent != null) + { + ErrorPlaceholder = (PlaceHolder) ctrl.Parent.FindControl("MessagePlaceHolder"); + } + if (ErrorPlaceholder != null) + { + //hide the module + ctrl.Visible = false; + ErrorPlaceholder.Visible = true; + ErrorPlaceholder.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container); + } + else + { + //there's no ErrorPlaceholder, add it to the module's control collection + ctrl.Controls.Add(new ErrorContainer(_portalSettings, FriendlyMessage, lex).Container); + } + } + } + } + catch (Exception exc2) + { + Logger.Fatal(exc2); + ProcessPageLoadException(exc2); + } + Logger.ErrorFormat("FriendlyMessage=\"{0}\" ctrl=\"{1}\" exc=\"{2}\"", FriendlyMessage, ctrl, exc); + + } + + /// + /// Processes the page load exception. + /// + /// The exc. + public static void ProcessPageLoadException(Exception exc) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + string appURL = Globals.ApplicationURL(); + if (appURL.IndexOf("?") == Null.NullInteger) + { + appURL += "?def=ErrorMessage"; + } + else + { + appURL += "&def=ErrorMessage"; + } + ProcessPageLoadException(exc, appURL); + } + + /// + /// Processes the page load exception. + /// + /// The exc. + /// The URL. + public static void ProcessPageLoadException(Exception exc, string URL) + { + Logger.Error(URL, exc); + if (ThreadAbortCheck(exc)) + { + return; + } + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + if (!Host.UseCustomErrorMessages) + { + throw new PageLoadException((exc == null ? "" : exc.Message), exc); + } + else + { + var lex = new PageLoadException((exc == null ? "" : exc.Message), exc); + //publish the exception + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(lex); + if (!String.IsNullOrEmpty(URL)) + { + //redirect + if (URL.IndexOf("error=terminate") != -1) + { + + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer("~/ErrorPage.aspx"); + } + else + { + HttpContext.Current.Response.Redirect(URL, true); + } + } + } + } + + /// + /// Logs the ModuleLoadException. + /// + /// The exc. + public static void LogException(ModuleLoadException exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.MODULE_LOAD_EXCEPTION); + } + + /// + /// Logs the PageLoadException. + /// + /// The exc. + public static void LogException(PageLoadException exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.PAGE_LOAD_EXCEPTION); + } + + /// + /// Logs the SchedulerException. + /// + /// The exc. + public static void LogException(SchedulerException exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.SCHEDULER_EXCEPTION); + } + + /// + /// Logs the SecurityException. + /// + /// The exc. + public static void LogException(SecurityException exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.SECURITY_EXCEPTION); + } + + /// + /// Logs all the basic exception. + /// + /// The exc. + public static void LogException(Exception exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.GENERAL_EXCEPTION); + } + + /// + /// Processes the scheduler exception. + /// + /// The exc. + public static void ProcessSchedulerException(Exception exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.SCHEDULER_EXCEPTION); + } + + /// + /// Logs the search exception. + /// + /// The exc. + public static void LogSearchException(SearchException exc) + { + Logger.Error(exc); + var objExceptionLog = new ExceptionLogController(); + objExceptionLog.AddLog(exc, ExceptionLogController.ExceptionLogType.SEARCH_INDEXER_EXCEPTION); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/ModuleLoadException.cs b/DNN Platform/Library/Services/Exceptions/ModuleLoadException.cs new file mode 100644 index 00000000000..9c1deb6e412 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/ModuleLoadException.cs @@ -0,0 +1,138 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Runtime.Serialization; +using System.Security.Permissions; +using System.Xml.Serialization; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class ModuleLoadException : BasePortalException + { + private readonly ModuleInfo m_ModuleConfiguration; + private string m_FriendlyName; + private string m_ModuleControlSource; + private int m_ModuleDefId; + private int m_ModuleId; + + //default constructor + public ModuleLoadException() + { + } + + //constructor with exception message + public ModuleLoadException(string message) : base(message) + { + InitilizePrivateVariables(); + } + + //constructor with exception message + public ModuleLoadException(string message, Exception inner, ModuleInfo ModuleConfiguration) : base(message, inner) + { + m_ModuleConfiguration = ModuleConfiguration; + InitilizePrivateVariables(); + } + + //constructor with message and inner exception + public ModuleLoadException(string message, Exception inner) : base(message, inner) + { + InitilizePrivateVariables(); + } + + protected ModuleLoadException(SerializationInfo info, StreamingContext context) : base(info, context) + { + InitilizePrivateVariables(); + m_ModuleId = info.GetInt32("m_ModuleId"); + m_ModuleDefId = info.GetInt32("m_ModuleDefId"); + m_FriendlyName = info.GetString("m_FriendlyName"); + } + + [XmlElement("ModuleID")] + public int ModuleId + { + get + { + return m_ModuleId; + } + } + + [XmlElement("ModuleDefId")] + public int ModuleDefId + { + get + { + return m_ModuleDefId; + } + } + + [XmlElement("FriendlyName")] + public string FriendlyName + { + get + { + return m_FriendlyName; + } + } + + [XmlElement("ModuleControlSource")] + public string ModuleControlSource + { + get + { + return m_ModuleControlSource; + } + } + + private void InitilizePrivateVariables() + { + //Try and get the Portal settings from context + //If an error occurs getting the context then set the variables to -1 + if ((m_ModuleConfiguration != null)) + { + m_ModuleId = m_ModuleConfiguration.ModuleID; + m_ModuleDefId = m_ModuleConfiguration.ModuleDefID; + m_FriendlyName = m_ModuleConfiguration.ModuleTitle; + m_ModuleControlSource = m_ModuleConfiguration.ModuleControl.ControlSrc; + } + else + { + m_ModuleId = -1; + m_ModuleDefId = -1; + } + } + + //public override void GetObjectData(SerializationInfo info, StreamingContext context) + //{ + // //Serialize this class' state and then call the base class GetObjectData + // info.AddValue("m_ModuleId", m_ModuleId, typeof (Int32)); + // info.AddValue("m_ModuleDefId", m_ModuleDefId, typeof (Int32)); + // info.AddValue("m_FriendlyName", m_FriendlyName, typeof (string)); + // info.AddValue("m_ModuleControlSource", m_ModuleControlSource, typeof (string)); + // base.GetObjectData(info, context); + //} + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/ObjectHydrationException.cs b/DNN Platform/Library/Services/Exceptions/ObjectHydrationException.cs new file mode 100644 index 00000000000..2e2efcb821c --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/ObjectHydrationException.cs @@ -0,0 +1,95 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Runtime.Serialization; +using System.Security.Permissions; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class ObjectHydrationException : BasePortalException + { + private List _Columns; + private Type _Type; + + public ObjectHydrationException(string message, Exception innerException) : base(message, innerException) + { + } + + public ObjectHydrationException(string message, Exception innerException, Type type, IDataReader dr) : base(message, innerException) + { + _Type = type; + _Columns = new List(); + foreach (DataRow row in dr.GetSchemaTable().Rows) + { + _Columns.Add(row["ColumnName"].ToString()); + } + } + + protected ObjectHydrationException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + + public List Columns + { + get + { + return _Columns; + } + set + { + _Columns = value; + } + } + + public Type Type + { + get + { + return _Type; + } + set + { + _Type = value; + } + } + + public override string Message + { + get + { + string _Message = base.Message; + _Message += " Expecting - " + Type + "."; + _Message += " Returned - "; + foreach (string columnName in Columns) + { + _Message += columnName + ", "; + } + return _Message; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/PageLoadException.cs b/DNN Platform/Library/Services/Exceptions/PageLoadException.cs new file mode 100644 index 00000000000..d08ca7edae0 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/PageLoadException.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Runtime.Serialization; +using System.Security.Permissions; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class PageLoadException : BasePortalException + { + //default constructor + public PageLoadException() + { + } + + //constructor with exception message + public PageLoadException(string message) : base(message) + { + } + + //constructor with message and inner exception + public PageLoadException(string message, Exception inner) : base(message, inner) + { + } + + protected PageLoadException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/SchedulerException.cs b/DNN Platform/Library/Services/Exceptions/SchedulerException.cs new file mode 100644 index 00000000000..20c05ad7af5 --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/SchedulerException.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Runtime.Serialization; +using System.Security.Permissions; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class SchedulerException : BasePortalException + { + //default constructor + public SchedulerException() + { + } + + //constructor with exception message + public SchedulerException(string message) : base(message) + { + } + + //constructor with message and inner exception + public SchedulerException(string message, Exception inner) : base(message, inner) + { + } + + protected SchedulerException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/SearchException.cs b/DNN Platform/Library/Services/Exceptions/SearchException.cs new file mode 100644 index 00000000000..6ce7e4261af --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/SearchException.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Search; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + #pragma warning disable 0618 + public class SearchException : BasePortalException + { + private readonly SearchItemInfo m_SearchItem; + + //default constructor + public SearchException() + { + } + + public SearchException(string message, Exception inner, SearchItemInfo searchItem) : base(message, inner) + { + m_SearchItem = searchItem; + } + + public SearchItemInfo SearchItem + { + get + { + return m_SearchItem; + } + } + } + #pragma warning restore 0618 +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Exceptions/SearchIndexEmptyException.cs b/DNN Platform/Library/Services/Exceptions/SearchIndexEmptyException.cs new file mode 100644 index 00000000000..2fb24026d5f --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/SearchIndexEmptyException.cs @@ -0,0 +1,11 @@ +using System; + +namespace DotNetNuke.Services.Exceptions +{ + public class SearchIndexEmptyException : Exception + { + public SearchIndexEmptyException(string message) : base(message) + { + } + } +} diff --git a/DNN Platform/Library/Services/Exceptions/SecurityException.cs b/DNN Platform/Library/Services/Exceptions/SecurityException.cs new file mode 100644 index 00000000000..8224c14c9ff --- /dev/null +++ b/DNN Platform/Library/Services/Exceptions/SecurityException.cs @@ -0,0 +1,111 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Runtime.Serialization; +using System.Security.Permissions; +using System.Web; +using System.Xml.Serialization; + +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Exceptions +{ + public class SecurityException : BasePortalException + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SecurityException)); + private string m_IP; + private string m_Querystring; + + //default constructor + public SecurityException() + { + } + + //constructor with exception message + public SecurityException(string message) : base(message) + { + InitilizePrivateVariables(); + } + + //constructor with message and inner exception + public SecurityException(string message, Exception inner) : base(message, inner) + { + InitilizePrivateVariables(); + } + + protected SecurityException(SerializationInfo info, StreamingContext context) : base(info, context) + { + InitilizePrivateVariables(); + m_IP = info.GetString("m_IP"); + m_Querystring = info.GetString("m_Querystring"); + } + + [XmlElement("IP")] + public string IP + { + get + { + return m_IP; + } + } + + [XmlElement("Querystring")] + public string Querystring + { + get + { + return m_Querystring; + } + } + + private void InitilizePrivateVariables() + { + //Try and get the Portal settings from httpcontext + try + { + if (HttpContext.Current.Request.UserHostAddress != null) + { + m_IP = HttpContext.Current.Request.UserHostAddress; + } + m_Querystring = HttpContext.Current.Request.MapPath(Querystring, HttpContext.Current.Request.ApplicationPath, false); + } + catch (Exception exc) + { + m_IP = ""; + m_Querystring = ""; + Logger.Error(exc); + + } + } + + //public override void GetObjectData(SerializationInfo info, StreamingContext context) + //{ + // //Serialize this class' state and then call the base class GetObjectData + // info.AddValue("m_IP", m_IP, typeof (string)); + // info.AddValue("m_Querystring", m_Querystring, typeof (string)); + // base.GetObjectData(info, context); + //} + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/ContentDisposition.cs b/DNN Platform/Library/Services/FileSystem/ContentDisposition.cs new file mode 100644 index 00000000000..9fd43b61056 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/ContentDisposition.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Represents the different options when downloading a file. + /// + public enum ContentDisposition + { + /// + /// The browser will display a dialog to allow the user to save or view the document. + /// + Attachment, + /// + /// The document will be displayed automatically. + /// + Inline + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/DefaultMetadataNames.cs b/DNN Platform/Library/Services/FileSystem/DefaultMetadataNames.cs new file mode 100644 index 00000000000..002574f85ad --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/DefaultMetadataNames.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Services.FileSystem +{ + public struct DefaultMetadataNames + { + public const string Created = "Created"; + public const string CreatedBy = "CreatedBy"; + public const string Modified = "Modified"; + public const string ModifiedBy = "ModifiedBy"; + public const string Type = "Type"; + public const string Size = "Size"; + public const string Title = "Title"; + public const string TotalFiles = "TotalFiles"; + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/FileAlreadyExistsException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/FileAlreadyExistsException.cs new file mode 100644 index 00000000000..48e694f8a77 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/FileAlreadyExistsException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class FileAlreadyExistsException : Exception + { + public FileAlreadyExistsException() + { + } + + public FileAlreadyExistsException(string message) + : base(message) + { + } + + public FileAlreadyExistsException(string message, Exception inner) + : base(message, inner) + { + } + + public FileAlreadyExistsException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/FileLockedException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/FileLockedException.cs new file mode 100644 index 00000000000..f65c79e4b15 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/FileLockedException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class FileLockedException : Exception + { + public FileLockedException() + { + } + + public FileLockedException(string message) + : base(message) + { + } + + public FileLockedException(string message, Exception inner) + : base(message, inner) + { + } + + public FileLockedException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/FolderAlreadyExistsException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/FolderAlreadyExistsException.cs new file mode 100644 index 00000000000..036ba8a4902 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/FolderAlreadyExistsException.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class FolderAlreadyExistsException : Exception + { + public FolderAlreadyExistsException() + { + } + + public FolderAlreadyExistsException(string message) + : base(message) + { + } + + public FolderAlreadyExistsException(string message, Exception inner) + : base(message, inner) + { + } + + public FolderAlreadyExistsException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/FolderProviderException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/FolderProviderException.cs new file mode 100644 index 00000000000..3dc43124de2 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/FolderProviderException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class FolderProviderException : Exception + { + public FolderProviderException() + { + } + + public FolderProviderException(string message) + : base(message) + { + } + + public FolderProviderException(string message, Exception inner) + : base(message, inner) + { + } + + public FolderProviderException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidFileExtensionException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidFileExtensionException.cs new file mode 100644 index 00000000000..802abd7fe02 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidFileExtensionException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class InvalidFileExtensionException : Exception + { + public InvalidFileExtensionException() + { + } + + public InvalidFileExtensionException(string message) + : base(message) + { + } + + public InvalidFileExtensionException(string message, Exception inner) + : base(message, inner) + { + } + + public InvalidFileExtensionException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidMetadataValuesException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidMetadataValuesException.cs new file mode 100644 index 00000000000..fa74960d878 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/InvalidMetadataValuesException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class InvalidMetadataValuesException : Exception + { + public InvalidMetadataValuesException() + { + } + + public InvalidMetadataValuesException(string message) + : base(message) + { + } + + public InvalidMetadataValuesException(string message, Exception inner) + : base(message, inner) + { + } + + public InvalidMetadataValuesException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/NoNetworkAvailableException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/NoNetworkAvailableException.cs new file mode 100644 index 00000000000..bf45a024b5a --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/NoNetworkAvailableException.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class NoNetworkAvailableException : Exception + { + public NoNetworkAvailableException() + { + } + + public NoNetworkAvailableException(string message) + : base(message) + { + } + + public NoNetworkAvailableException(string message, Exception inner) + : base(message, inner) + { + } + + public NoNetworkAvailableException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/NoSpaceAvailableException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/NoSpaceAvailableException.cs new file mode 100644 index 00000000000..394f58a471b --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/NoSpaceAvailableException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class NoSpaceAvailableException : Exception + { + public NoSpaceAvailableException() + { + } + + public NoSpaceAvailableException(string message) + : base(message) + { + } + + public NoSpaceAvailableException(string message, Exception inner) + : base(message, inner) + { + } + + public NoSpaceAvailableException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Exceptions/PermissionsNotMetException.cs b/DNN Platform/Library/Services/FileSystem/Exceptions/PermissionsNotMetException.cs new file mode 100644 index 00000000000..049bab589a1 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Exceptions/PermissionsNotMetException.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Runtime.Serialization; + +using DotNetNuke.Services.Exceptions; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class PermissionsNotMetException : Exception + { + public PermissionsNotMetException() + { + } + + public PermissionsNotMetException(string message) + : base(message) + { + } + + public PermissionsNotMetException(string message, Exception inner) + : base(message, inner) + { + } + + public PermissionsNotMetException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FileController.cs b/DNN Platform/Library/Services/FileSystem/FileController.cs new file mode 100644 index 00000000000..5aaeeacd706 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileController.cs @@ -0,0 +1,531 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.IO; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : FileController + /// + /// ----------------------------------------------------------------------------- + /// + /// Business Class that provides access to the Database for the functions within the calling classes + /// Instantiates the instance of the DataProvider and returns the object, if any + /// + /// + /// + /// + /// [DYNST] 2/1/2004 Created + /// [vnguyen] 30/04/2010 Modified: Added Guid and VersionG + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager class.")] + public class FileController + { + #region "Obsolete Methods" + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) ")] + public int AddFile(FileInfo file) + { + var fileManager = FileManager.Instance; + + var folder = FolderManager.Instance.GetFolder(file.FolderId); + + var existingFile = fileManager.GetFile(folder, file.FileName); + + if (existingFile == null) + { + using (var fileContent = fileManager.GetFileContent(file)) + { + file.FileId = fileManager.AddFile(folder, file.FileName, fileContent, false).FileId; + } + } + else + { + using (var fileContent = fileManager.GetFileContent(file)) + { + file.FileId = fileManager.UpdateFile(file, fileContent).FileId; + } + } + + return file.FileId; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.UpdateFile(IFileInfo file) ")] + public void UpdateFile(FileInfo file) + { + FileManager.Instance.UpdateFile(file); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by DatabaseFolderProvider.ClearFileContent(int fileId) ")] + public void ClearFileContent(int fileId) + { + DatabaseFolderProvider.ClearFileContent(fileId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public int ConvertFilePathToFileId(string filePath, int portalID) + { + var fileName = Path.GetFileName(filePath); + + var folderPath = filePath.Substring(0, filePath.LastIndexOf(fileName)); + var folder = FolderManager.Instance.GetFolder(portalID, folderPath); + + var file = FileManager.Instance.GetFile(folder, fileName); + + return file.FileId; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.DeleteFile(IFileInfo file) ")] + public void DeleteFile(int portalId, string fileName, int folderID, bool clearCache) + { + var folder = FolderManager.Instance.GetFolder(folderID); + var file = FileManager.Instance.GetFile(folder, fileName); + FileManager.Instance.DeleteFile(file); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void DeleteFiles(int portalId) + { + DeleteFiles(portalId, true); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void DeleteFiles(int portalId, bool clearCache) + { + DataProvider.Instance().DeleteFiles(portalId); + + if (clearCache) + { + GetAllFilesRemoveCache(); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public DataTable GetAllFiles() + { + var dt = (DataTable) DataCache.GetCache("GetAllFiles"); + if (dt == null) + { + dt = DataProvider.Instance().GetAllFiles(); + DataCache.SetCache("GetAllFiles", dt); + } + + if (dt != null) + { + return dt.Copy(); + } + + return new DataTable(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void GetAllFilesRemoveCache() + { + DataCache.RemoveCache("GetAllFiles"); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.GetFile(IFolderInfo folder, string fileName) ")] + public FileInfo GetFile(string fileName, int portalId, int folderID) + { + var folder = FolderManager.Instance.GetFolder(folderID); + return (FileInfo)FileManager.Instance.GetFile(folder, fileName); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.GetFile(int fileID) ")] + public FileInfo GetFileById(int fileId, int portalId) + { + return (FileInfo)FileManager.Instance.GetFile(fileId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public FileInfo GetFileByUniqueID(Guid uniqueId) + { + return (FileInfo) CBO.FillObject(DataProvider.Instance().GetFileByUniqueID(uniqueId), typeof (FileInfo)); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FileManager.Instance.GetFileContent(IFileInfo file) ")] + public byte[] GetFileContent(int fileId, int portalId) + { + return null; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFiles(IFolderInfo folder) ")] + public IDataReader GetFiles(int portalId, int folderID) + { + return DataProvider.Instance().GetFiles(folderID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by DatabaseFolderProvider.UpdateFileContent(int fileId, Stream content) ")] + public void UpdateFileContent(int fileId, Stream content) + { + DatabaseFolderProvider.UpdateFileContent(fileId, content); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by DatabaseFolderProvider.UpdateFileContent(int fileId, byte[] content) ")] + public void UpdateFileContent(int fileId, byte[] content) + { + DatabaseFolderProvider.UpdateFileContent(fileId, content); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static XmlNode SerializeFile(XmlDocument xmlFile, FileInfo file) + { + CBO.SerializeObject(file, xmlFile); + + XmlNode nodeTab = xmlFile.SelectSingleNode("file"); + nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsd"]); + nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsi"]); + + return nodeTab; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public static FileInfo DeserializeFile(XmlNode nodeFile, int portalId, int folderId) + { + var node = nodeFile.SelectSingleNode("file"); + + var newFile = new FileInfo + { + UniqueId = new Guid(XmlUtils.GetNodeValue(node.CreateNavigator(), "uniqueid")), + VersionGuid = new Guid(XmlUtils.GetNodeValue(node.CreateNavigator(), "versionguid")), + PortalId = portalId, + FileName = XmlUtils.GetNodeValue(node.CreateNavigator(), "filename"), + Folder = XmlUtils.GetNodeValue(node.CreateNavigator(), "folder"), + FolderId = folderId, + ContentType = XmlUtils.GetNodeValue(node.CreateNavigator(), "contenttype"), + Extension = XmlUtils.GetNodeValue(node.CreateNavigator(), "extension"), + StorageLocation = XmlUtils.GetNodeValueInt(node, "storagelocation"), + IsCached = XmlUtils.GetNodeValueBoolean(node, "iscached", false), + Size = XmlUtils.GetNodeValueInt(node, "size", Null.NullInteger), + Width = XmlUtils.GetNodeValueInt(node, "width", Null.NullInteger), + Height = XmlUtils.GetNodeValueInt(node, "height", Null.NullInteger) + }; + + // create/update file + var fileCtrl = new FileController(); + + var originalFile = fileCtrl.GetFileByUniqueID(newFile.UniqueId); + + if (originalFile == null) + { + var folder = FolderManager.Instance.GetFolder(folderId); + using (var fileContent = FileManager.Instance.GetFileContent(newFile)) + { + newFile.FileId = FileManager.Instance.AddFile(folder, newFile.FileName, fileContent, false).FileId; + } + } + else + { + newFile.FileId = originalFile.FileId; + } + + return (FileInfo)FileManager.Instance.UpdateFile(newFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")] + public int AddFile(FileInfo file, string folderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(file.PortalId, folderPath, false); + file.FolderId = objFolder.FolderID; + file.Folder = folderPath; + return AddFile(file); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")] + public int AddFile(int portalId, string fileName, string extension, long size, int width, int height, string contentType, string folderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(portalId, folderPath, false); + var objFile = new FileInfo(); + + objFile.UniqueId = Guid.NewGuid(); + objFile.VersionGuid = Guid.NewGuid(); + + objFile.PortalId = portalId; + objFile.FileName = fileName; + objFile.Extension = extension; + objFile.Size = Convert.ToInt32(size); + objFile.Width = width; + objFile.Height = height; + objFile.ContentType = contentType; + objFile.Folder = FileSystemUtils.FormatFolderPath(folderPath); + objFile.FolderId = objFolder.FolderID; + objFile.IsCached = true; + + return AddFile(objFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by AddFile(ByVal file As FileInfo)")] + public int AddFile(int portalId, string fileName, string extension, long size, int width, int height, string ContentType, string FolderPath, bool ClearCache) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(portalId, FolderPath, false); + var objFile = new FileInfo(); + + objFile.UniqueId = Guid.NewGuid(); + objFile.VersionGuid = Guid.NewGuid(); + + objFile.PortalId = portalId; + objFile.FileName = fileName; + objFile.Extension = extension; + objFile.Size = Convert.ToInt32(size); + objFile.Width = width; + objFile.Height = height; + objFile.ContentType = ContentType; + objFile.Folder = FileSystemUtils.FormatFolderPath(FolderPath); + objFile.FolderId = objFolder.FolderID; + objFile.IsCached = ClearCache; + + return AddFile(objFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by DeleteFile(PortalId, FileName, FolderID, ClearCache)")] + public void DeleteFile(int PortalId, string FileName, string FolderPath, bool ClearCache) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false); + DeleteFile(PortalId, FileName, objFolder.FolderID, ClearCache); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by DeleteFile(PortalId, FileName, FolderID, ClearCache)")] + public void DeleteFile(int PortalId, string FileName, string FolderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false); + DeleteFile(PortalId, FileName, objFolder.FolderID, true); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFile(FileName, PortalId, FolderID)")] + public FileInfo GetFile(string FilePath, int PortalId) + { + var objFolders = new FolderController(); + string FileName = Path.GetFileName(FilePath); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FilePath.Replace(FileName, ""), false); + if (objFolder == null) + { + return null; + } + else + { + return GetFile(FileName, PortalId, objFolder.FolderID); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFile(FileName, PortalId, FolderID)")] + public FileInfo GetFile(string FileName, int PortalId, string FolderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false); + if (objFolder == null) + { + return null; + } + else + { + return GetFile(FileName, PortalId, objFolder.FolderID); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by GetFiles(PortalId, FolderID)")] + public IDataReader GetFiles(int PortalId, string FolderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, FolderPath, false); + if (objFolder == null) + { + return null; + } + return GetFiles(PortalId, objFolder.FolderID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This function has been replaced by ???")] + public ArrayList GetFilesByFolder(int portalId, string folderPath) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(portalId, folderPath, false); + if (objFolder == null) + { + return null; + } + return CBO.FillCollection(GetFiles(portalId, objFolder.FolderID), typeof (FileInfo)); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")] + public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, + string DestinationFolder) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, DestinationFolder, false); + FileInfo objFile = GetFile(OriginalFileName, PortalId, objFolder.FolderID); + + objFile.FileName = FileName; + objFile.Extension = Extension; + objFile.Size = Convert.ToInt32(Size); + objFile.Width = Width; + objFile.Height = Height; + objFile.ContentType = ContentType; + objFile.Folder = DestinationFolder; + + if ((objFile != null)) + { + UpdateFile(objFile); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")] + public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, + string DestinationFolder, bool ClearCache) + { + var objFolders = new FolderController(); + FolderInfo objFolder = objFolders.GetFolder(PortalId, DestinationFolder, false); + FileInfo objFile = GetFile(OriginalFileName, PortalId, objFolder.FolderID); + + objFile.FileName = FileName; + objFile.Extension = Extension; + objFile.Size = Convert.ToInt32(Size); + objFile.Width = Width; + objFile.Height = Height; + objFile.ContentType = ContentType; + objFile.Folder = DestinationFolder; + + if ((objFile != null)) + { + UpdateFile(objFile); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")] + public void UpdateFile(int PortalId, string OriginalFileName, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string SourceFolder, + string DestinationFolder, int FolderID, bool ClearCache) + { + FileInfo objFile = GetFile(OriginalFileName, PortalId, FolderID); + + objFile.FileName = FileName; + objFile.Extension = Extension; + objFile.Size = Convert.ToInt32(Size); + objFile.Width = Width; + objFile.Height = Height; + objFile.ContentType = ContentType; + objFile.Folder = DestinationFolder; + objFile.FolderId = FolderID; + + if ((objFile != null)) + { + UpdateFile(objFile); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by AddFile(ByVal file As FileInfo)")] + public int AddFile(int PortalId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string FolderPath, int FolderID, bool ClearCache) + { + var objFile = new FileInfo(); + + objFile.UniqueId = Guid.NewGuid(); + objFile.VersionGuid = Guid.NewGuid(); + + objFile.PortalId = PortalId; + objFile.FileName = FileName; + objFile.Extension = Extension; + objFile.Size = Convert.ToInt32(Size); + objFile.Width = Width; + objFile.Height = Height; + objFile.ContentType = ContentType; + objFile.Folder = FileSystemUtils.FormatFolderPath(FolderPath); + objFile.FolderId = FolderID; + + if (ClearCache) + { + GetAllFilesRemoveCache(); + } + + return AddFile(objFile); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by UpdateFile(ByVal file As FileInfo)")] + public void UpdateFile(int FileId, string FileName, string Extension, long Size, int Width, int Height, string ContentType, string DestinationFolder, int FolderID) + { + var objFile = new FileInfo(); + + objFile.FileId = FileId; + objFile.VersionGuid = Guid.NewGuid(); + + objFile.FileName = FileName; + objFile.Extension = Extension; + objFile.Size = Convert.ToInt32(Size); + objFile.Width = Width; + objFile.Height = Height; + objFile.ContentType = ContentType; + objFile.Folder = FileSystemUtils.FormatFolderPath(DestinationFolder); + objFile.FolderId = FolderID; + + UpdateFile(objFile); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FileInfo.cs b/DNN Platform/Library/Services/FileSystem/FileInfo.cs new file mode 100644 index 00000000000..14a8c68dd8c --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileInfo.cs @@ -0,0 +1,496 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Drawing; +using System.IO; +using System.Web; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : FileInfo + /// + /// ----------------------------------------------------------------------------- + /// + /// Represents the File object and holds the Properties of that object + /// + /// + /// [DYNST] 02/01/2004 Created + /// [vnguyen] 04/28/2010 Modified: Added GUID and Version GUID properties + /// + /// ----------------------------------------------------------------------------- + [XmlRoot("file", IsNullable = false)] + [Serializable] + public class FileInfo : BaseEntityInfo, IFileInfo + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(FileInfo)); + private string _folder; + private bool? _supportsFileAttributes; + private DateTime? _lastModificationTime; + private int _folderMappingID; + + private int? _width = null; + private int? _height = null; + private string _sha1Hash = null; + + #region Constructors + + public FileInfo() + { + UniqueId = Guid.NewGuid(); + VersionGuid = Guid.NewGuid(); + } + + public FileInfo(int portalId, string filename, string extension, int filesize, int width, int height, string contentType, string folder, int folderId, int storageLocation, bool cached) + : this(portalId, filename, extension, filesize, width, height, contentType, folder, folderId, storageLocation, cached, Null.NullString) + { + } + + public FileInfo(int portalId, string filename, string extension, int filesize, int width, int height, string contentType, string folder, int folderId, int storageLocation, bool cached, + string hash) + : this(Guid.NewGuid(), Guid.NewGuid(), portalId, filename, extension, filesize, width, height, contentType, folder, folderId, storageLocation, cached, hash) + { + } + + public FileInfo(Guid uniqueId, Guid versionGuid, int portalId, string filename, string extension, int filesize, int width, int height, string contentType, string folder, int folderId, + int storageLocation, bool cached, string hash) + { + UniqueId = uniqueId; + VersionGuid = versionGuid; + PortalId = portalId; + FileName = filename; + Extension = extension; + Size = filesize; + Width = width; + Height = height; + ContentType = contentType; + Folder = folder; + FolderId = folderId; + StorageLocation = storageLocation; + IsCached = cached; + SHA1Hash = hash; + } + + #endregion + + #region Properties + + [XmlElement("contenttype")] + public string ContentType { get; set; } + + [XmlElement("extension")] + public string Extension { get; set; } + + [XmlElement("fileid")] + public int FileId { get; set; } + + [XmlElement("uniqueid")] + public Guid UniqueId { get; set; } + + [XmlElement("versionguid")] + public Guid VersionGuid { get; set; } + + [XmlElement("filename")] + public string FileName { get; set; } + + [XmlElement("folder")] + public string Folder + { + get + { + return _folder; + } + set + { + //Make sure folder name ends with / + if (!string.IsNullOrEmpty(value) && !value.EndsWith("/")) + { + value = value + "/"; + } + + _folder = value; + } + } + + [XmlElement("folderid")] + public int FolderId { get; set; } + + [XmlElement("height")] + public int Height + { + get + { + if (FileId != 0 && (!_height.HasValue || _height.Value == Null.NullInteger)) + { + LoadImageProperties(); + } + + return _height.Value; + } + set + { + _height = value; + } + } + + [XmlElement("iscached")] + public bool IsCached { get; set; } + + [XmlElement("physicalpath")] + public string PhysicalPath + { + get + { + string physicalPath = Null.NullString; + PortalSettings portalSettings = null; + if (HttpContext.Current != null) + { + portalSettings = PortalController.GetCurrentPortalSettings(); + } + + if (PortalId == Null.NullInteger) + { + physicalPath = Globals.HostMapPath + RelativePath; + } + else + { + if (portalSettings == null || portalSettings.PortalId != PortalId) + { + //Get the PortalInfo based on the Portalid + var objPortals = new PortalController(); + PortalInfo objPortal = objPortals.GetPortal(PortalId); + if ((objPortal != null)) + { + physicalPath = objPortal.HomeDirectoryMapPath + RelativePath; + } + } + else + { + physicalPath = portalSettings.HomeDirectoryMapPath + RelativePath; + } + } + + if ((!string.IsNullOrEmpty(physicalPath))) + { + physicalPath = physicalPath.Replace("/", "\\"); + } + + return physicalPath; + } + } + + [XmlIgnore] + public int PortalId { get; set; } + + public string RelativePath + { + get + { + return Folder + FileName; + } + } + + [XmlElement("size")] + public int Size { get; set; } + + [XmlElement("storagelocation")] + public int StorageLocation { get; set; } + + [XmlElement("width")] + public int Width + { + get + { + if (FileId != 0 && (!_width.HasValue || _width.Value == Null.NullInteger)) + { + LoadImageProperties(); + } + + return _width.Value; + } + set + { + _width = value; + } + } + + [XmlElement("sha1hash")] + public string SHA1Hash + { + get + { + if (FileId != 0 && string.IsNullOrEmpty(_sha1Hash)) + { + LoadHashProperty(); + } + + return _sha1Hash; + } + set + { + _sha1Hash = value; + } + } + + public FileAttributes? FileAttributes + { + get + { + FileAttributes? _fileAttributes = null; + + if (SupportsFileAttributes) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(PortalId, FolderMappingID); + _fileAttributes = FolderProvider.Instance(folderMapping.FolderProviderType).GetFileAttributes(this); + } + + return _fileAttributes; + } + } + + public bool SupportsFileAttributes + { + get + { + if (!_supportsFileAttributes.HasValue) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(PortalId, FolderMappingID); + + try + { + _supportsFileAttributes = FolderProvider.Instance(folderMapping.FolderProviderType).SupportsFileAttributes(); + } + catch + { + _supportsFileAttributes = false; + } + } + + return _supportsFileAttributes.Value; + } + } + + public DateTime LastModificationTime + { + get + { + if(!_lastModificationTime.HasValue) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(PortalId, FolderMappingID); + + try + { + return FolderProvider.Instance(folderMapping.FolderProviderType).GetLastModificationTime(this); + } + catch + { + return Null.NullDate; + } + } + + return _lastModificationTime.Value; + } + set + { + _lastModificationTime = value; + } + } + + public int FolderMappingID + { + get + { + if (_folderMappingID == 0) + { + if (FolderId > 0) + { + var folder = FolderManager.Instance.GetFolder(FolderId); + + if (folder != null) + { + _folderMappingID = folder.FolderMappingID; + return _folderMappingID; + } + } + + switch (StorageLocation) + { + case (int)FolderController.StorageLocationTypes.InsecureFileSystem: + _folderMappingID = FolderMappingController.Instance.GetFolderMapping(PortalId, "Standard").FolderMappingID; + break; + case (int)FolderController.StorageLocationTypes.SecureFileSystem: + _folderMappingID = FolderMappingController.Instance.GetFolderMapping(PortalId, "Secure").FolderMappingID; + break; + case (int)FolderController.StorageLocationTypes.DatabaseSecure: + _folderMappingID = FolderMappingController.Instance.GetFolderMapping(PortalId, "Database").FolderMappingID; + break; + default: + _folderMappingID = FolderMappingController.Instance.GetDefaultFolderMapping(PortalId).FolderMappingID; + break; + } + } + + return _folderMappingID; + } + set + { + _folderMappingID = value; + } + } + + /// + /// Gets or sets a metadata field with an optional title associated to the file + /// + public string Title { get; set; } + + /// + /// Gets or sets the date on which the file starts to be published + /// + public DateTime StartDate { get; set; } + + /// + /// Gets or sets the date on which the file ends to be published + /// + public DateTime EndDate { get; set; } + + /// + /// Gets or sets a value indicating whether publish period is enabled for the file + /// + public bool EnablePublishPeriod { get; set; } + + /// + /// Gets or sets the published version number of the file + /// + public int PublishedVersion { get; set; } + + /// + /// Gets a value indicating whether the file is enabled, + /// considering if the publish period is active and if the current date is within the publish period + /// + public bool IsEnabled + { + get + { + var today = DateTime.Today; + return !EnablePublishPeriod + || (StartDate.Date <= today && (EndDate == Null.NullDate || today <= EndDate.Date)); + } + } + + /// + /// Gets or sets a reference to ContentItem, to use in Workflows + /// + public int ContentItemID { get; set; } + + #endregion + + #region Private methods + + private void LoadImageProperties() + { + var fileManager = (FileManager)FileManager.Instance; + var fileContent = fileManager.GetFileContent(this); + + if (fileContent == null) + { + //If can't get file content then just exit the function, so it will load again next time. + return; + } + + if (!fileContent.CanSeek) + { + var tmp = fileManager.GetSeekableStream(fileContent); + fileContent.Close(); + fileContent = tmp; + } + + if (fileManager.IsImageFile(this)) + { + Image image = null; + + try + { + image = fileManager.GetImageFromStream(fileContent); + + _width = image.Width; + _height = image.Height; + } + catch + { + _width = 0; + _height = 0; + ContentType = "application/octet-stream"; + } + finally + { + if (image != null) + { + image.Dispose(); + } + fileContent.Position = 0; + } + } + else + { + _width = _height = 0; + } + + fileContent.Close(); + } + + private void LoadHashProperty() + { + var fileManager = (FileManager)FileManager.Instance; + var fileContent = fileManager.GetFileContent(this); + + if (fileContent == null) + { + //If can't get file content then just exit the function, so it will load again next time. + return; + } + + if (!fileContent.CanSeek) + { + var tmp = fileManager.GetSeekableStream(fileContent); + fileContent.Close(); + fileContent = tmp; + } + + _sha1Hash = fileManager.GetHash(fileContent); + + fileContent.Close(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FileManager.cs b/DNN Platform/Library/Services/FileSystem/FileManager.cs new file mode 100644 index 00000000000..fa17cf39827 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileManager.cs @@ -0,0 +1,1712 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Content.Workflow; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; + +using ICSharpCode.SharpZipLib.Zip; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Exposes methods to manage files. + /// + public class FileManager : ComponentBase, IFileManager + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(FileManager)); + + #region Properties + + private IDictionary _contentTypes; + + protected IDictionary ContentTypes + { + get + { + if (_contentTypes == null) + { + _contentTypes = new Dictionary(); + _contentTypes.Add("txt", "text/plain"); + _contentTypes.Add("htm", "text/html"); + _contentTypes.Add("html", "text/html"); + _contentTypes.Add("rtf", "text/richtext"); + _contentTypes.Add("jpg", "image/jpeg"); + _contentTypes.Add("jpeg", "image/jpeg"); + _contentTypes.Add("gif", "image/gif"); + _contentTypes.Add("bmp", "image/bmp"); + _contentTypes.Add("png", "image/png"); + _contentTypes.Add("ico", "image/x-icon"); + _contentTypes.Add("mp3", "audio/mpeg"); + _contentTypes.Add("wma", "audio/x-ms-wma"); + _contentTypes.Add("mpg", "video/mpeg"); + _contentTypes.Add("mpeg", "video/mpeg"); + _contentTypes.Add("avi", "video/avi"); + _contentTypes.Add("mp4", "video/mp4"); + _contentTypes.Add("wmv", "video/x-ms-wmv"); + _contentTypes.Add("pdf", "application/pdf"); + _contentTypes.Add("doc", "application/msword"); + _contentTypes.Add("dot", "application/msword"); + _contentTypes.Add("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + _contentTypes.Add("dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"); + _contentTypes.Add("csv", "text/csv"); + _contentTypes.Add("xls", "application/x-msexcel"); + _contentTypes.Add("xlt", "application/x-msexcel"); + _contentTypes.Add("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + _contentTypes.Add("xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"); + _contentTypes.Add("ppt", "application/vnd.ms-powerpoint"); + _contentTypes.Add("pps", "application/vnd.ms-powerpoint"); + _contentTypes.Add("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + _contentTypes.Add("ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"); + } + + return _contentTypes; + } + } + #endregion + + #region Constants + + private const int BufferSize = 4096; + + #endregion + + #region Constructor + + internal FileManager() + { + } + + #endregion + + #region Private Methods + + private void AddFileToFolderProvider(Stream fileContent, string fileName, IFolderInfo destinationFolder, FolderProvider provider) + { + try + { + if (!fileContent.CanSeek) + { + using (var seekableStream = GetSeekableStream(fileContent)) + { + provider.AddFile(destinationFolder, fileName, seekableStream); + } + } + else + { + provider.AddFile(destinationFolder, fileName, fileContent); + } + } + catch (Exception ex) + { + Logger.Error(ex); + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception."), ex); + } + } + + private void DeleteFileFromFolderProvider(IFileInfo file, FolderProvider provider) + { + try + { + // We can't delete the file until the fileContent resource has been released + provider.DeleteFile(file); + } + catch (Exception ex) + { + Logger.Error(ex); + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception."), ex); + } + } + + #endregion + + #region Public Methods + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// A IFileInfo as specified by the parameters. + public virtual IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent) + { + + return AddFile(folder, fileName, fileContent, true); + } + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exits. + /// A IFileInfo as specified by the parameters. + public virtual IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite) + { + return AddFile(folder, fileName, fileContent, overwrite, false, GetContentType(Path.GetExtension(fileName))); + } + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exists. + /// Indicates if permissions have to be met. + /// The content type of the file. + /// Thrown when folder, fileName or fileContent are null. + /// Thrown when the underlying system throw an exception. + /// Thrown when the extension of the specified file is not allowed. + /// Thrown when the portal has no space available to store the specified file. + /// Thrown when permissions are not met. + /// A IFileInfo as specified by the parameters. + public virtual IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite, bool checkPermissions, string contentType) + { + return AddFile(folder, fileName, fileContent, overwrite, checkPermissions, contentType, GetCurrentUserID()); + } + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exists. + /// Indicates if permissions have to be met. + /// The content type of the file. + /// ID of the user that creates the file + /// Thrown when folder, fileName or fileContent are null. + /// Thrown when the underlying system throw an exception. + /// Thrown when the extension of the specified file is not allowed. + /// Thrown when the portal has no space available to store the specified file. + /// Thrown when permissions are not met. + /// A IFileInfo as specified by the parameters. + public virtual IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite, bool checkPermissions, string contentType, int createdByUserID) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + + if (checkPermissions && !FolderPermissionControllerWrapper.Instance.CanAddFolder(folder)) + { + throw new PermissionsNotMetException(Localization.Localization.GetExceptionMessage("AddFilePermissionsNotMet", "Permissions are not met. The file has not been added.")); + } + + if (!IsAllowedExtension(fileName)) + { + throw new InvalidFileExtensionException(string.Format(Localization.Localization.GetExceptionMessage("AddFileExtensionNotAllowed", "The extension '{0}' is not allowed. The file has not been added."), Path.GetExtension(fileName))); + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + bool fileExists = folderProvider.FileExists(folder, fileName); + bool needToWriteFile = fileContent != null && (overwrite || !fileExists); + bool usingSeekableStream = false; + + if (fileContent != null && !needToWriteFile && FileExists(folder, fileName)) + { + return GetFile(folder, fileName); + } + + var oldFile = fileExists ? GetFile(folder, fileName, true) : null; + + var now = DateTime.Now; + var extension = Path.GetExtension(fileName); + var file = new FileInfo + { + PortalId = folder.PortalID, + FileName = fileName, + Extension = (!String.IsNullOrEmpty(extension)) ? extension.Replace(".", "") : String.Empty, + Width = Null.NullInteger, + Height = Null.NullInteger, + ContentType = contentType, + Folder = folder.FolderPath, + FolderId = folder.FolderID, + LastModificationTime = now, + StartDate = now, + EndDate = Null.NullDate, + EnablePublishPeriod = false, + ContentItemID = oldFile != null ? oldFile.ContentItemID : Null.NullInteger + }; + + try + { + ContentWorkflow folderWorkflow = null; + + var contentFileName = fileName; + + if (needToWriteFile) + { + if (!fileContent.CanSeek) + { + fileContent = GetSeekableStream(fileContent); + usingSeekableStream = true; + } + + // Retrieve Metadata + file.Size = (int)fileContent.Length; + file.SHA1Hash = GetHash(fileContent); + fileContent.Position = 0; + + file.Width = 0; + file.Height = 0; + + if (IsImageFile(file)) + { + try + { + using (var image = GetImageFromStream(fileContent)) + { + file.Width = image.Width; + file.Height = image.Height; + } + } + catch + { + file.ContentType = "application/octet-stream"; + } + finally + { + fileContent.Position = 0; + } + } + + if (!PortalControllerWrapper.Instance.HasSpaceAvailable(folder.PortalID, file.Size)) + { + throw new NoSpaceAvailableException( + Localization.Localization.GetExceptionMessage("AddFileNoSpaceAvailable", + "The portal has no space available to store the specified file. The file has not been added.")); + } + + //Publish Period + if (fileExists && IsFileOutOfPublishPeriod(oldFile, folder.PortalID, createdByUserID)) + { + throw new FileLockedException( + Localization.Localization.GetExceptionMessage("FileLockedOutOfPublishPeriodError", + "File locked. The file cannot be updated because it is out of Publish Period")); + } + // Workflow + folderWorkflow = ContentWorkflowController.Instance.GetWorkflowByID(folder.WorkflowID); + if (folderWorkflow != null) + { + file.FileId = fileExists ? oldFile.FileId : Null.NullInteger; // If workflow exists, then the file already exists + + // Create Content Item if does not exists + if (file.ContentItemID == Null.NullInteger) + { + file.ContentItemID = CreateFileContentItem().ContentItemId; + } + + contentFileName = UpdateWhileApproving(folder, createdByUserID, file, fileExists, fileContent); + if (StartWorkflowWhenChange(createdByUserID, folderWorkflow, fileExists, file.ContentItemID)) + { + if (fileExists) + { + UpdateFile(file); + } + } + } + // Versioning + else if (fileExists && FileVersionController.Instance.IsFolderVersioned(folder) && oldFile.SHA1Hash != file.SHA1Hash) + { + contentFileName = FileVersionController.Instance.AddFileVersion(oldFile, createdByUserID); + } + } + else + { + file.Size = (int)folderProvider.GetFileSize(file); + } + + if (folderWorkflow == null || !fileExists) + { + file.FileId = DataProvider.Instance().AddFile(file.PortalId, + file.UniqueId, + file.VersionGuid, + file.FileName, + file.Extension, + file.Size, + file.Width, + file.Height, + file.ContentType, + file.Folder, + file.FolderId, + createdByUserID, + file.SHA1Hash, + file.LastModificationTime, + file.Title, + file.StartDate, + file.EndDate, + file.EnablePublishPeriod, + file.ContentItemID); + } + + try + { + if (needToWriteFile) + { + folderProvider.AddFile(folder, contentFileName, fileContent); + } + + var providerLastModificationTime = folderProvider.GetLastModificationTime(file); + if (file.LastModificationTime != providerLastModificationTime) + { + DataProvider.Instance().UpdateFileLastModificationTime(file.FileId, providerLastModificationTime); + } + } + catch (FileLockedException fle) + { + Logger.Error(fle); + throw; + } + catch (Exception ex) + { + Logger.Error(ex); + + if (!folderProvider.FileExists(folder, file.FileName)) + { + DataProvider.Instance().DeleteFile(file.PortalId, file.FileName, file.FolderId); + DeleteContentItem(file.ContentItemID); + } + + throw new FolderProviderException( + Localization.Localization.GetExceptionMessage("AddFileUnderlyingSystemError", + "The underlying system threw an exception. The file has not been added."), + ex); + } + + DataCache.RemoveCache("GetFileById" + file.FileId); + return GetFile(file.FileId); + } + finally + { + if (usingSeekableStream) + { + fileContent.Dispose(); + } + } + } + + /// + /// Copies the specified file into the specified folder. + /// + /// The file to copy. + /// The folder where to copy the file to. + /// Thrown when file or destinationFolder are null. + /// A IFileInfo with the information of the copied file. + public virtual IFileInfo CopyFile(IFileInfo file, IFolderInfo destinationFolder) + { + + Requires.NotNull("file", file); + Requires.NotNull("destinationFolder", destinationFolder); + + if (file.FolderMappingID == destinationFolder.FolderMappingID) + { + if (!FolderPermissionControllerWrapper.Instance.CanAddFolder(destinationFolder)) + { + throw new PermissionsNotMetException(Localization.Localization.GetExceptionMessage("CopyFilePermissionsNotMet", "Permissions are not met. The file has not been copied.")); + } + + if (!PortalControllerWrapper.Instance.HasSpaceAvailable(destinationFolder.PortalID, file.Size)) + { + throw new NoSpaceAvailableException(Localization.Localization.GetExceptionMessage("CopyFileNoSpaceAvailable", "The portal has no space available to store the specified file. The file has not been copied.")); + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + try + { + var folder = FolderManager.Instance.GetFolder(file.FolderId); + FolderProvider.Instance(folderMapping.FolderProviderType).CopyFile(folder.MappedPath, file.FileName, destinationFolder.MappedPath, folderMapping); + } + catch (Exception ex) + { + Logger.Error(ex); + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("CopyFileUnderlyingSystemError", "The underlying system throw an exception. The file has not been copied."), ex); + } + + // copy Content Item + var contentItemID = CopyContentItem(file.ContentItemID); + + var fileId = DataProvider.Instance().AddFile( + file.PortalId, + Guid.NewGuid(), + Guid.NewGuid(), + file.FileName, + file.Extension, + file.Size, + file.Width, + file.Height, + file.ContentType, + destinationFolder.FolderPath, + destinationFolder.FolderID, + GetCurrentUserID(), + file.SHA1Hash, + DateTime.Now, + file.Title, + file.StartDate, + file.EndDate, + file.EnablePublishPeriod, + contentItemID); + + return GetFile(fileId, true); + } + + using (var fileContent = GetFileContent(file)) + { + return AddFile(destinationFolder, file.FileName, fileContent, true, true, file.ContentType); + } + } + + /// + /// Deletes the specified file. + /// + /// The file to delete. + /// Thrown when file is null. + /// Thrown when the underlying system throw an exception. + public virtual void DeleteFile(IFileInfo file) + { + + Requires.NotNull("file", file); + + var lockReason = ""; + if (IsFileLocked(file, out lockReason)) + { + throw new FileLockedException(Localization.Localization.GetExceptionMessage(lockReason, "File locked. The file cannot be updated. Reason: " + lockReason)); + } + + FileVersionController.Instance.DeleteAllUnpublishedVersions(file, false); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + + try + { + FolderProvider.Instance(folderMapping.FolderProviderType).DeleteFile(file); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("DeleteFileUnderlyingSystemError", "The underlying system threw an exception. The file has not been deleted."), ex); + } + + DataProvider.Instance().DeleteFile(file.PortalId, file.FileName, file.FolderId); + DeleteContentItem(file.ContentItemID); + } + + /// + /// Deletes the specified files. + /// + /// The files to delete. + /// Thrown when files is null. + public virtual void DeleteFiles(IEnumerable files) + { + + Requires.NotNull("files", files); + + foreach (var file in files) + { + DeleteFile(file); + } + } + + /// + /// Checks the existence of the specified file in the specified folder. + /// + /// The folder where to check the existence of the file. + /// The file name to check the existence of. + /// A bool value indicating whether the file exists or not in the specified folder. + /// Thrown when folder is null. + /// Thrown when fileName is null or empty. + /// Thrown when the underlying system throw an exception. + public virtual bool FileExists(IFolderInfo folder, string fileName) + { + return FileExists(folder, fileName, false); + } + + /// + /// Checks the existence of the specified file in the specified folder. + /// + /// The folder where to check the existence of the file. + /// The file name to check the existence of. + /// Indicates if the file is retrieved from All files or from Published files + /// A bool value indicating whether the file exists or not in the specified folder. + /// Thrown when folder is null. + /// Thrown when fileName is null or empty. + /// Thrown when the underlying system throw an exception. + public virtual bool FileExists(IFolderInfo folder, string fileName, bool retrieveUnpublishedFiles) + { + + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + + var file = GetFile(folder, fileName, retrieveUnpublishedFiles); + var existsFile = file != null; + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + + try + { + existsFile = existsFile && FolderProvider.Instance(folderMapping.FolderProviderType).FileExists(folder, fileName); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception."), ex); + } + + return existsFile; + } + + /// + /// Gets the Content Type for the specified file extension. + /// + /// The file extension. + /// The Content Type for the specified extension. + public virtual string GetContentType(string extension) + { + + if (string.IsNullOrEmpty(extension)) return "application/octet-stream"; + + var key = extension.TrimStart('.').ToLowerInvariant(); + return ContentTypes.ContainsKey(key) ? ContentTypes[key] : "application/octet-stream"; + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The file identifier. + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(int fileID) + { + return GetFile(fileID, false); + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The file identifier. + /// Indicates if the file is retrieved from All files or from Published files + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(int fileID, bool retrieveUnpublishedFiles) + { + if (fileID == 0 || fileID == -1) + { + return null; + } + + var strCacheKey = "GetFileById" + fileID; + var file = DataCache.GetCache(strCacheKey); + if (file == null) + { + file = CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFileById(fileID, retrieveUnpublishedFiles)); + if (file != null) + { + var intCacheTimeout = 20 * Convert.ToInt32(GetPerformanceSetting()); + DataCache.SetCache(strCacheKey, file, TimeSpan.FromMinutes(intCacheTimeout)); + } + } + return (IFileInfo)file; + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The folder where the file is stored. + /// The name of the file. + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(IFolderInfo folder, string fileName) + { + return GetFile(folder, fileName, false); + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The folder where the file is stored. + /// The name of the file. + /// Indicates if the file is retrieved from All files or from Published files + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(IFolderInfo folder, string fileName, bool retrieveUnpublishedFiles) + { + + Requires.NotNullOrEmpty("fileName", fileName); + Requires.NotNull("folder", folder); + + return CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFile(fileName, folder.FolderID, retrieveUnpublishedFiles)); + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The portal ID or Null.NullInteger for the Host + /// Relative path to the file. + /// Host and portal settings commonly return a relative path to a file. This method uses that relative path to fetch file metadata. + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(int portalId, string relativePath) + { + return GetFile(portalId, relativePath, false); + } + + /// + /// Gets the file metadata for the specified file. + /// + /// The portal ID or Null.NullInteger for the Host + /// Relative path to the file. + /// Indicates if the file is retrieved from All files or from Published files + /// Host and portal settings commonly return a relative path to a file. This method uses that relative path to fetch file metadata. + /// The IFileInfo object with the metadata of the specified file. + public virtual IFileInfo GetFile(int portalId, string relativePath, bool retrieveUnpublishedFiles) + { + + Requires.NotNullOrEmpty("relateivePath", relativePath); + + var folderPath = ""; + var seperatorIndex = relativePath.LastIndexOf('/'); + + if (seperatorIndex > 0) + { + folderPath = relativePath.Substring(0, seperatorIndex + 1); + } + + var folderInfo = FolderManager.Instance.GetFolder(portalId, folderPath); + if (folderInfo == null) + { + return null; + } + + var fileName = relativePath.Substring(folderPath.Length); + return GetFile(folderInfo, fileName, retrieveUnpublishedFiles); + } + + /// + /// Gets the content of the specified file. + /// + /// The file to get the content from. + /// A stream with the content of the file. + /// Thrown when file is null. + /// Thrown when the underlying system throw an exception. + public virtual Stream GetFileContent(IFileInfo file) + { + Requires.NotNull("file", file); + + Stream stream = null; + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + + if (folderMapping != null) + { + try + { + stream = FolderProvider.Instance(folderMapping.FolderProviderType).GetFileStream(file); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception"), ex); + } + } + + return stream; + } + + /// + /// Gets a seekable Stream based on the specified non-seekable Stream. + /// + /// A non-seekable Stream. + /// A seekable Stream. + public virtual Stream GetSeekableStream(Stream stream) + { + + Requires.NotNull("stream", stream); + + if (stream.CanSeek) return stream; + + var folderPath = GetHostMapPath(); + string filePath; + + do + { + filePath = Path.Combine(folderPath, Path.GetRandomFileName()) + ".resx"; + } while (File.Exists(filePath)); + + var fileStream = GetAutoDeleteFileStream(filePath); + + var array = new byte[BufferSize]; + + int bytesRead; + while ((bytesRead = stream.Read(array, 0, BufferSize)) > 0) + { + fileStream.Write(array, 0, bytesRead); + } + + fileStream.Position = 0; + + return fileStream; + } + + /// + /// Gets the direct Url to the file. + /// + /// The file to get the Url. + /// The direct Url to the file. + /// Thrown when file is null. + /// Thrown when the underlying system throw an exception. + public string GetUrl(IFileInfo file) + { + + Requires.NotNull("file", file); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + + try + { + return FolderProvider.Instance(folderMapping.FolderProviderType).GetFileUrl(file); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception."), ex); + } + } + + /// + /// Moves the specified file into the specified folder. + /// + /// The file to move. + /// The folder where to move the file to. + /// Thrown when file or destinationFolder are null. + /// Thrown when the underlying system throw an exception. + /// Thrown when the extension of the specified file is not allowed. + /// Thrown when the portal has no space available to store the specified file. + /// Thrown when permissions are not met. + /// An IFileInfo with the information of the moved file. + public virtual IFileInfo MoveFile(IFileInfo file, IFolderInfo destinationFolder) + { + Requires.NotNull("file", file); + Requires.NotNull("destinationFolder", destinationFolder); + + //check whether the file is already in the dest folder. + if (file.FolderId == destinationFolder.FolderID) + { + return file; + } + + var lockReason = ""; + if (IsFileLocked(file, out lockReason)) + { + throw new FileLockedException(Localization.Localization.GetExceptionMessage(lockReason, "File locked. The file cannot be updated. Reason: " + lockReason)); + } + + //check for existing file + var existingFile = GetFile(destinationFolder, file.FileName, true); + if (existingFile != null) + { + DeleteFile(existingFile); + } + + var destinationFolderMapping = FolderMappingController.Instance.GetFolderMapping(destinationFolder.PortalID, destinationFolder.FolderMappingID); + var destinationFolderProvider = FolderProvider.Instance(destinationFolderMapping.FolderProviderType); + + var sourceFolderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + var sourceFolderProvider = FolderProvider.Instance(sourceFolderMapping.FolderProviderType); + + if (destinationFolderMapping.FolderMappingID == sourceFolderMapping.FolderMappingID && destinationFolderProvider.SupportsMoveFile) + { + //Implement Move + destinationFolderProvider.MoveFile(file, destinationFolder); + } + else + { + //Implement Copy/Delete + using (var fileContent = GetFileContent(file)) + { + if (destinationFolderMapping.MappingName == "Database") + { + destinationFolderProvider.UpdateFile(file, fileContent); + } + else + { + AddFileToFolderProvider(fileContent, file.FileName, destinationFolder, destinationFolderProvider); + } + } + DeleteFileFromFolderProvider(file, sourceFolderProvider); + } + + if (file.FolderMappingID == destinationFolder.FolderMappingID) + { + MoveVersions(file, destinationFolder, sourceFolderProvider, destinationFolderProvider); + } + else + { + FileVersionController.Instance.DeleteAllUnpublishedVersions(file, true); + } + + file.FolderId = destinationFolder.FolderID; + file.Folder = destinationFolder.FolderPath; + file = UpdateFile(file); + return file; + } + + /// + /// Renames the specified file. + /// + /// The file to rename + /// The new filename to assign to the file. + /// Thrown when file is null. + /// Thrown when the folder already contains a file with the same name. + /// An IFileInfo with the information of the renamed file. + public virtual IFileInfo RenameFile(IFileInfo file, string newFileName) + { + + Requires.NotNull("file", file); + Requires.NotNullOrEmpty("newFileName", newFileName); + + if (file.FileName == newFileName) return file; + + if (!IsAllowedExtension(newFileName)) + { + throw new InvalidFileExtensionException(string.Format(Localization.Localization.GetExceptionMessage("AddFileExtensionNotAllowed", "The extension '{0}' is not allowed. The file has not been added."), Path.GetExtension(newFileName))); + } + + var folder = FolderManager.Instance.GetFolder(file.FolderId); + + if (FileExists(folder, newFileName)) + { + throw new FileAlreadyExistsException(Localization.Localization.GetExceptionMessage("RenameFileAlreadyExists", "This folder already contains a file with the same name. The file has not been renamed.")); + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + + try + { + FolderProvider.Instance(folderMapping.FolderProviderType).RenameFile(file, newFileName); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("RenameFileUnderlyingSystemError", "The underlying system threw an exception. The file has not been renamed."), ex); + } + + file.FileName = newFileName; + if (Path.HasExtension(newFileName)) + { + file.Extension = Path.GetExtension(newFileName).Replace(".", ""); + } + return UpdateFile(file); + } + + /// + /// Sets the specified FileAttributes of the file. + /// + /// The file. + /// The file attributes to add. + public void SetAttributes(IFileInfo file, FileAttributes fileAttributes) + { + + Requires.NotNull("file", file); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + + try + { + FolderProvider.Instance(folderMapping.FolderProviderType).SetFileAttributes(file, fileAttributes); + } + catch (Exception ex) + { + Logger.Error(ex); + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("UnderlyingSystemError", "The underlying system threw an exception."), ex); + } + } + + /// + /// Extracts the files and folders contained in the specified zip file to the folder where the file belongs. + /// + /// The file to unzip. + /// Thrown when file is not a zip compressed file. + /// Thrown when file or destination folder are null. + public virtual void UnzipFile(IFileInfo file) + { + + Requires.NotNull("file", file); + + var destinationFolder = FolderManager.Instance.GetFolder(file.FolderId); + + UnzipFile(file, destinationFolder); + } + + /// + /// Extracts the files and folders contained in the specified zip file to the specified folder. + /// + /// The file to unzip. + /// The folder to unzip too + /// Thrown when file is not a zip compressed file. + /// Thrown when file or destination folder are null. + public virtual void UnzipFile(IFileInfo file, IFolderInfo destinationFolder) + { + + Requires.NotNull("file", file); + Requires.NotNull("destinationFolder", destinationFolder); + + if (file.Extension != "zip") + { + throw new ArgumentException(Localization.Localization.GetExceptionMessage("InvalidZipFile", "The file specified is not a zip compressed file.")); + } + + ExtractFiles(file, destinationFolder); + } + + /// + /// Updates the metadata of the specified file. + /// + /// The file to update. + /// Thrown when file is null. + /// A IFileInfo as the updated file. + public virtual IFileInfo UpdateFile(IFileInfo file) + { + Requires.NotNull("file", file); + + string message; + if (!ValidMetadata(file, out message)) + { + throw new InvalidMetadataValuesException(message); + } + + return UpdateFile(file, true); + } + + /// + /// Regenerates the hash and updates the metadata of the specified file. + /// + /// The file to update. + /// Stream used to regenerate the hash. + /// Thrown when file is null. + /// A IFileInfo as the updated file. + public virtual IFileInfo UpdateFile(IFileInfo file, Stream fileContent) + { + Requires.NotNull("file", file); + + if (fileContent != null) + { + if (IsImageFile(file)) + { + Image image = null; + + try + { + image = GetImageFromStream(fileContent); + + file.Width = image.Width; + file.Height = image.Height; + } + catch + { + file.ContentType = "application/octet-stream"; + } + finally + { + if (image != null) + { + image.Dispose(); + } + } + } + + file.SHA1Hash = GetHash(fileContent); + } + + // Get file size from folder provider. + try + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping != null) + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + file.Size = (int)folderProvider.GetFileSize(file); + file.LastModificationTime = folderProvider.GetLastModificationTime(file); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + + return UpdateFile(file); + } + + /// + /// Writes the content of the specified file into the specified stream. + /// + /// The file to write into the stream. + /// The stream to write to. + /// Thrown when file or stream are null. + public virtual void WriteFile(IFileInfo file, Stream stream) + { + + Requires.NotNull("file", file); + Requires.NotNull("stream", stream); + + using (var srcStream = GetFileContent(file)) + { + const int bufferSize = 4096; + var buffer = new byte[bufferSize]; + + int bytesRead; + while ((bytesRead = srcStream.Read(buffer, 0, bufferSize)) > 0) + { + stream.Write(buffer, 0, bytesRead); + } + } + } + + /// + /// Downloads the specified file. + /// + /// The file to download. + /// Indicates how to display the document once downloaded. + /// Thrown when file is null. + /// Thrown when permissions are not met. + public virtual void WriteFileToResponse(IFileInfo file, ContentDisposition contentDisposition) + { + + Requires.NotNull("file", file); + + var folder = FolderManager.Instance.GetFolder(file.FolderId); + + if (!FolderPermissionControllerWrapper.Instance.CanViewFolder(folder)) + { + throw new PermissionsNotMetException(Localization.Localization.GetExceptionMessage("WriteFileToResponsePermissionsNotMet", "Permissions are not met. The file cannot be downloaded.")); + } + + if (IsFileAutoSyncEnabled()) + { + AutoSyncFile(file); + } + + WriteFileToHttpContext(file, contentDisposition); + } + + #endregion + + #region Internal Methods + + #region ContentType Methods + internal virtual int CopyContentItem(int contentItemId) + { + if (contentItemId == Null.NullInteger) return Null.NullInteger; + + var newContentItem = CreateFileContentItem(); + + // Clone terms + var termController = new TermController(); + foreach (var term in termController.GetTermsByContent(contentItemId)) + { + termController.AddTermToContent(term, newContentItem); + } + + return newContentItem.ContentItemId; + } + + internal virtual ContentItem CreateFileContentItem() + { + var typeController = new ContentTypeController(); + var contentTypeFile = (from t in typeController.GetContentTypes() where t.ContentType == "File" select t).SingleOrDefault(); + + if (contentTypeFile == null) + { + contentTypeFile = new ContentType { ContentType = "File" }; + contentTypeFile.ContentTypeId = typeController.AddContentType(contentTypeFile); + } + + var objContent = new ContentItem + { + ContentTypeId = contentTypeFile.ContentTypeId, + Indexed = false, + }; + + objContent.ContentItemId = Util.GetContentController().AddContentItem(objContent); + + return objContent; + } + + internal virtual void DeleteContentItem(int contentItemId) + { + if (contentItemId == Null.NullInteger) return; + + Util.GetContentController().DeleteContentItem(contentItemId); + } + + #endregion + + #region File Locked + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsFileLocked(IFileInfo file, out string lockReasonKey) + { + lockReasonKey = ""; + + var allowedUser = IsHostAdminUser(file.PortalId, UserController.GetCurrentUserInfo().UserID); + if (allowedUser) + { + return false; + } + + if (file.ContentItemID != Null.NullInteger) + { + var workflowCompleted = ContentWorkflowController.Instance.IsWorkflowCompleted(file.ContentItemID); + if (!workflowCompleted) + { + lockReasonKey = "FileLockedRunningWorkflowError"; + return true; + } + } + + var outOfPublishPeriod = IsFileOutOfPublishPeriod(file); + if (outOfPublishPeriod) + { + lockReasonKey = "FileLockedOutOfPublishPeriodError"; + return true; + } + + return false; + } + + internal virtual bool IsFileOutOfPublishPeriod(IFileInfo file, int portalId, int userId) + { + if (IsHostAdminUser(portalId, userId)) + { + return false; + } + return IsFileOutOfPublishPeriod(file); + } + + internal virtual bool IsFileOutOfPublishPeriod(IFileInfo file) + { + //Publish Period locks + return (file.EnablePublishPeriod && (file.StartDate > DateTime.Today || (file.EndDate < DateTime.Today && file.EndDate != Null.NullDate))); + } + + internal virtual bool IsHostAdminUser(int portalId, int userId) + { + if (userId == Null.NullInteger) + { + return false; + } + var user = UserController.GetUserById(portalId, userId); + return user.IsSuperUser || portalId > Null.NullInteger && user.IsInRole(new PortalSettings(portalId).AdministratorRoleName); + } + + #endregion + + #region File Versions + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void MoveVersions(IFileInfo file, IFolderInfo destinationFolder, FolderProvider sourceFolderProvider, FolderProvider destinationFolderProvider) + { + var versions = FileVersionController.Instance.GetFileVersions(file).ToArray(); + if (!versions.Any()) return; + + var folder = FolderManager.Instance.GetFolder(file.FolderId); + + foreach (var version in versions) + { + // Get Version File + using (var fileContent = sourceFolderProvider.GetFileStream(folder, version.FileName)) + { + // This scenario is when the file is in the Database Folder Provider + if (fileContent == null) continue; + + AddFileToFolderProvider(fileContent, version.FileName, destinationFolder, destinationFolderProvider); + } + + var fileVersion = new FileInfo + { + FileName = version.FileName, + Folder = file.Folder, + FolderMappingID = file.FolderMappingID, + PortalId = folder.PortalID + }; + + DeleteFileFromFolderProvider(fileVersion, sourceFolderProvider); + } + } + + #endregion + + #region Workflow Methods + + private bool CanUpdateWhenApproving(IFolderInfo folder, int contentItemID, int createdByUserID) + { + if (ContentWorkflowController.Instance.IsWorkflowOnDraft(contentItemID)) + { + ////We assume User can add content to folder + return true; + } + return ContentWorkflowController.Instance.IsCurrentReviewer(folder.PortalID, createdByUserID, contentItemID); + } + + private bool StartWorkflowWhenChange(int createdByUserID, ContentWorkflow folderWorkflow, bool fileExists, int contentItemID) + { + if ((folderWorkflow.StartAfterCreating && !fileExists) || + (folderWorkflow.StartAfterEditing && fileExists)) + { + if (ContentWorkflowController.Instance.IsWorkflowCompleted(contentItemID)) + { + ContentWorkflowController.Instance.StartWorkflow(folderWorkflow.WorkflowID, contentItemID, createdByUserID); + return true; + } + } + return false; + } + private string UpdateWhileApproving(IFolderInfo folder, int createdByUserID, IFileInfo file, bool fileExists, Stream content) + { + bool workflowCompleted = ContentWorkflowController.Instance.IsWorkflowCompleted(file.ContentItemID); + + var isDatabaseMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID).MappingName == "Database"; + //Currently, first upload is always published + if (!fileExists) + { + return file.FileName; + } + if (workflowCompleted) //We assume User can add content to folder + { + return isDatabaseMapping ? FileVersionController.Instance.AddFileVersion(file, createdByUserID, false, false, content) : FileVersionController.Instance.AddFileVersion(file, createdByUserID, false); + + } + + if (CanUpdateWhenApproving(folder, file.ContentItemID, createdByUserID)) + { + //Update the Unpublished version + var versions = FileVersionController.Instance.GetFileVersions(file).ToArray(); + if (versions.Any()) + { + FileVersionController.Instance.DeleteFileVersion(file, versions.OrderByDescending(f => f.Version).FirstOrDefault().Version); + } + return isDatabaseMapping ? FileVersionController.Instance.AddFileVersion(file, createdByUserID, false, false, content) : FileVersionController.Instance.AddFileVersion(file, createdByUserID, false); + } + + throw new FileLockedException( + Localization.Localization.GetExceptionMessage("FileLockedRunningWorkflowError", + "File locked. The file cannot be updated because it has a running workflow")); + } + #endregion + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void AutoSyncFile(IFileInfo file) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + var folder = FolderManager.Instance.GetFolder(file.FolderId); + + if (folderProvider.FileExists(folder, file.FileName)) + { + var newFileSize = folderProvider.GetFileSize(file); + if (file.Size != newFileSize) + { + using (var fileContent = GetFileContent(file)) + { + UpdateFile(file, fileContent); + } + } + } + else + { + DeleteFile(file); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void ExtractFiles(IFileInfo file, IFolderInfo destinationFolder) + { + var folderManager = FolderManager.Instance; + + ZipInputStream zipInputStream = null; + + try + { + using (var fileContent = GetFileContent(file)) + { + zipInputStream = new ZipInputStream(fileContent); + + var zipEntry = zipInputStream.GetNextEntry(); + + while (zipEntry != null) + { + if (!zipEntry.IsDirectory) + { + var fileName = Path.GetFileName(zipEntry.Name); + + EnsureZipFolder(zipEntry.Name, destinationFolder); + + IFolderInfo parentFolder; + if (zipEntry.Name.IndexOf("/") == -1) + { + parentFolder = destinationFolder; + } + else + { + var folderPath = destinationFolder.FolderPath + zipEntry.Name.Substring(0, zipEntry.Name.LastIndexOf("/") + 1); + parentFolder = folderManager.GetFolder(file.PortalId, folderPath); + } + + try + { + AddFile(parentFolder, fileName, zipInputStream, true); + } + catch (PermissionsNotMetException exc) + { + Logger.Warn(exc); + } + catch (NoSpaceAvailableException exc) + { + Logger.Warn(exc); + } + catch (InvalidFileExtensionException exc) + { + Logger.Warn(exc); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + zipEntry = zipInputStream.GetNextEntry(); + } + } + } + finally + { + if (zipInputStream != null) + { + zipInputStream.Close(); + zipInputStream.Dispose(); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal void EnsureZipFolder(string fileName, IFolderInfo destinationFolder) + { + var folderManager = FolderManager.Instance; + + var folderMappingController = FolderMappingController.Instance; + var folderMapping = folderMappingController.GetFolderMapping(destinationFolder.PortalID, destinationFolder.FolderMappingID); + + if (fileName.LastIndexOf('/') == -1) + { + return; + } + + var zipFolder = fileName.Substring(0, fileName.LastIndexOf('/')); + + var folderPath = PathUtils.Instance.RemoveTrailingSlash(zipFolder); + + if (folderPath.IndexOf("/") == -1) + { + var newFolderPath = destinationFolder.FolderPath + PathUtils.Instance.FormatFolderPath(folderPath); + if (!folderManager.FolderExists(destinationFolder.PortalID, newFolderPath)) + { + folderManager.AddFolder(folderMapping, newFolderPath); + } + } + else + { + var zipFolders = folderPath.Split('/'); + + var parentFolder = destinationFolder; + + for (var i = 0; i < zipFolders.Length; i++) + { + var newFolderPath = parentFolder.FolderPath + PathUtils.Instance.FormatFolderPath(zipFolders[i]); + if (!folderManager.FolderExists(destinationFolder.PortalID, newFolderPath)) + { + folderManager.AddFolder(folderMappingController.GetFolderMapping(parentFolder.PortalID, parentFolder.FolderMappingID), newFolderPath); + } + + parentFolder = folderManager.GetFolder(destinationFolder.PortalID, newFolderPath); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual Stream GetAutoDeleteFileStream(string filePath) + { + return new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, BufferSize, FileOptions.DeleteOnClose); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual int GetCurrentUserID() + { + return UserController.GetCurrentUserInfo().UserID; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + /// SHA1 hash of the file + internal virtual string GetHash(Stream stream) + { + Requires.NotNull("stream", stream); + + var hashText = ""; + string hexValue; + + var hashData = SHA1.Create().ComputeHash(stream); + + foreach (var b in hashData) + { + hexValue = b.ToString("X").ToLower(); + //Lowercase for compatibility on case-sensitive systems + hashText += (hexValue.Length == 1 ? "0" : "") + hexValue; + } + + return hashText; + } + + /// + /// Gets the hash of a file + /// + /// The file info. + /// SHA1 hash of the file + internal virtual string GetHash(IFileInfo fileInfo) + { + using (var stream = GetFileContent(fileInfo)) + { + return GetHash(stream); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual string GetHostMapPath() + { + return TestableGlobals.Instance.HostMapPath; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual Image GetImageFromStream(Stream stream) + { + return Image.FromStream(stream); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual Globals.PerformanceSettings GetPerformanceSetting() + { + return Host.PerformanceSetting; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsAllowedExtension(string fileName) + { + var extension = Path.GetExtension(fileName); + + //regex matches a dot followed by 1 or more chars followed by a semi-colon + //regex is meant to block files like "foo.asp;.png" which can take advantage + //of a vulnerability in IIS6 which treasts such files as .asp, not .png + return !string.IsNullOrEmpty(extension) + && Host.AllowedExtensionWhitelist.IsAllowedExtension(extension) + && !Regex.IsMatch(fileName, @"\..+;"); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsFileAutoSyncEnabled() + { + return Host.EnableFileAutoSync; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsImageFile(IFileInfo file) + { + return (Globals.glbImageFileTypes + ",").IndexOf(file.Extension.ToLower().Replace(".", "") + ",") > -1; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void WriteFileToHttpContext(IFileInfo file, ContentDisposition contentDisposition) + { + var scriptTimeOut = HttpContext.Current.Server.ScriptTimeout; + + HttpContext.Current.Server.ScriptTimeout = int.MaxValue; + var objResponse = HttpContext.Current.Response; + + objResponse.ClearContent(); + objResponse.ClearHeaders(); + + switch (contentDisposition) + { + case ContentDisposition.Attachment: + objResponse.AppendHeader("content-disposition", "attachment; filename=\"" + file.FileName + "\""); + break; + case ContentDisposition.Inline: + objResponse.AppendHeader("content-disposition", "inline; filename=\"" + file.FileName + "\""); + break; + default: + throw new ArgumentOutOfRangeException("contentDisposition"); + } + + objResponse.AppendHeader("Content-Length", file.Size.ToString()); + objResponse.ContentType = GetContentType(file.Extension.Replace(".", "")); + + try + { + using (var fileContent = GetFileContent(file)) + { + WriteStream(objResponse, fileContent); + } + } + catch (Exception ex) + { + Logger.Error(ex); + + objResponse.Write("Error : " + ex.Message); + } + + objResponse.Flush(); + objResponse.End(); + + HttpContext.Current.Server.ScriptTimeout = scriptTimeOut; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void WriteStream(HttpResponse objResponse, Stream objStream) + { + var bytBuffer = new byte[10000]; + try + { + if (objResponse.IsClientConnected) + { + var intLength = objStream.Read(bytBuffer, 0, 10000); + + while (objResponse.IsClientConnected && intLength > 0) + { + objResponse.OutputStream.Write(bytBuffer, 0, intLength); + objResponse.Flush(); + + intLength = objStream.Read(bytBuffer, 0, 10000); + } + } + } + catch (Exception ex) + { + Logger.Error(ex); + objResponse.Write("Error : " + ex.Message); + } + finally + { + if (objStream != null) + { + objStream.Close(); + objStream.Dispose(); + } + } + } + + /// + /// Update file info to database. + /// + /// File info. + /// Whether to update the lazy load properties: Width, Height, Sha1Hash. + /// The file info + internal virtual IFileInfo UpdateFile(IFileInfo file, bool updateLazyload) + { + Requires.NotNull("file", file); + + DataProvider.Instance().UpdateFile(file.FileId, + file.VersionGuid, + file.FileName, + file.Extension, + file.Size, + updateLazyload ? file.Width : Null.NullInteger, + updateLazyload ? file.Height : Null.NullInteger, + file.ContentType, + file.Folder, + file.FolderId, + GetCurrentUserID(), + updateLazyload ? file.SHA1Hash : Null.NullString, + file.LastModificationTime, + file.Title, + file.StartDate, + file.EndDate, + file.EnablePublishPeriod, + file.ContentItemID); + + DataCache.RemoveCache("GetFileById" + file.FileId); + + return file; + } + + private static bool ValidMetadata(IFileInfo file, out string exceptionMessage) + { + exceptionMessage = ""; + //TODO check dynamically all required fields from MetadataInfo + + //TODO check dynamically all max lengths from MetadataInfo + //TODO Use the MaxLength from MetadataInfo + if (!string.IsNullOrEmpty(file.Title) && file.Title.Length > 256) + { + exceptionMessage = Localization.Localization.GetExceptionMessage("MaxLengthExceeded", "The maximum length of the field {0} has been exceeded", DefaultMetadataNames.Title); + return false; + } + + if (file.StartDate == null || file.StartDate == Null.NullDate) + { + exceptionMessage = Localization.Localization.GetExceptionMessage("StartDateRequired", "The Start Date is required"); + return false; + } + + if (file.StartDate < file.CreatedOnDate.Date) + { + exceptionMessage = Localization.Localization.GetExceptionMessage("StartDateMustNotBeInThePast", "The Start Date must not be in the past"); + return false; + } + + if (file.EndDate != Null.NullDate && file.StartDate > file.EndDate) + { + exceptionMessage = Localization.Localization.GetExceptionMessage("InvalidPublishPeriod", "The End Date must be after the Start Date"); + return false; + } + + return true; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FileManagerFunctions.cs b/DNN Platform/Library/Services/FileSystem/FileManagerFunctions.cs new file mode 100644 index 00000000000..d94bc9da625 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileManagerFunctions.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +namespace DotNetNuke.Services.FileSystem +{ + [Obsolete("Deprecated in DNN 6.0")] + public class FileManagerFunctions + { + [Obsolete("Deprecated in DNN 6.0")] + public static string CReplace(string strExpression, string strSearch, string strReplace, int intMode) + { + string strReturn; + int lngPosition; + string strTemp; + if (intMode == 1) + { + strReturn = ""; + strSearch = strSearch.ToUpper(); + strTemp = strExpression.ToUpper(); + lngPosition = strTemp.IndexOf(strSearch); + while (lngPosition >= 0) + { + strReturn = strReturn + strExpression.Substring(0, lngPosition) + strReplace; + strExpression = strExpression.Substring(lngPosition + strSearch.Length); + strTemp = strTemp.Substring(lngPosition + strSearch.Length); + lngPosition = strTemp.IndexOf(strSearch); + } + strReturn = strReturn + strExpression; + } + else + { + strReturn = strExpression.Replace(strSearch, strReplace); + } + return strReturn; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FileServerHandler.cs b/DNN Platform/Library/Services/FileSystem/FileServerHandler.cs new file mode 100644 index 00000000000..1b9f1590842 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileServerHandler.cs @@ -0,0 +1,263 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + public class FileServerHandler : IHttpHandler + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (FileServerHandler)); + #region IHttpHandler Members + + /// ----------------------------------------------------------------------------- + /// + /// This handler handles requests for LinkClick.aspx, but only those specifc + /// to file serving + /// + /// System.Web.HttpContext) + /// + /// + /// + /// [cpaterra] 4/19/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void ProcessRequest(HttpContext context) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + int TabId = -1; + int ModuleId = -1; + try + { + //get TabId + if (context.Request.QueryString["tabid"] != null) + { + Int32.TryParse(context.Request.QueryString["tabid"], out TabId); + } + + //get ModuleId + if (context.Request.QueryString["mid"] != null) + { + Int32.TryParse(context.Request.QueryString["mid"], out ModuleId); + } + } + catch (Exception) + { + //The TabId or ModuleId are incorrectly formatted (potential DOS) + Exceptions.Exceptions.ProcessHttpException(context.Request); + } + + //get Language + string Language = _portalSettings.DefaultLanguage; + if (context.Request.QueryString["language"] != null) + { + Language = context.Request.QueryString["language"]; + } + else + { + if (context.Request.Cookies["language"] != null) + { + Language = context.Request.Cookies["language"].Value; + } + } + if (LocaleController.Instance.IsEnabled(ref Language, _portalSettings.PortalId)) + { + Localization.Localization.SetThreadCultures(new CultureInfo(Language), _portalSettings); + Localization.Localization.SetLanguage(Language); + } + + //get the URL + string URL = ""; + bool blnClientCache = true; + bool blnForceDownload = false; + if (context.Request.QueryString["fileticket"] != null) + { + URL = "FileID=" + UrlUtils.DecryptParameter(context.Request.QueryString["fileticket"]); + } + if (context.Request.QueryString["userticket"] != null) + { + URL = "UserId=" + UrlUtils.DecryptParameter(context.Request.QueryString["userticket"]); + } + if (context.Request.QueryString["link"] != null) + { + URL = context.Request.QueryString["link"]; + if (URL.ToLowerInvariant().StartsWith("fileid=")) + { + URL = ""; //restrict direct access by FileID + } + } + if (!String.IsNullOrEmpty(URL)) + { + //update clicks, this must be done first, because the url tracker works with unmodified urls, like tabid, fileid etc + var objUrls = new UrlController(); + objUrls.UpdateUrlTracking(_portalSettings.PortalId, URL, ModuleId, -1); + TabType UrlType = Globals.GetURLType(URL); + if(UrlType == TabType.Tab) + { + //verify whether the tab is exist, otherwise throw out 404. + if(new TabController().GetTab(int.Parse(URL), _portalSettings.PortalId, false) == null) + { + Exceptions.Exceptions.ProcessHttpException(); + } + } + if (UrlType != TabType.File) + { + URL = Globals.LinkClick(URL, TabId, ModuleId, false); + } + + if (UrlType == TabType.File && URL.ToLowerInvariant().StartsWith("fileid=") == false) + { + //to handle legacy scenarios before the introduction of the FileServerHandler + var fileName = Path.GetFileName(URL); + + var folderPath = URL.Substring(0, URL.LastIndexOf(fileName)); + var folder = FolderManager.Instance.GetFolder(_portalSettings.PortalId, folderPath); + + var file = FileManager.Instance.GetFile(folder, fileName); + + URL = "FileID=" + file.FileId; + } + + //get optional parameters + if (context.Request.QueryString["clientcache"] != null) + { + blnClientCache = bool.Parse(context.Request.QueryString["clientcache"]); + } + if ((context.Request.QueryString["forcedownload"] != null) || (context.Request.QueryString["contenttype"] != null)) + { + blnForceDownload = bool.Parse(context.Request.QueryString["forcedownload"]); + } + var contentDisposition = blnForceDownload ? ContentDisposition.Attachment : ContentDisposition.Inline; + + //clear the current response + context.Response.Clear(); + var fileManager = FileManager.Instance; + try + { + switch (UrlType) + { + case TabType.File: + var download = false; + var file = fileManager.GetFile(int.Parse(UrlUtils.GetParameterValue(URL))); + if (file != null) + { + if (!file.IsEnabled) + { + if (context.Request.IsAuthenticated) + { + context.Response.Redirect(Globals.AccessDeniedURL(Localization.Localization.GetString("FileAccess.Error")), true); + } + else + { + context.Response.Redirect(Globals.AccessDeniedURL(), true); + } + } + + try + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + var directUrl = fileManager.GetUrl(file); + if (directUrl.Contains("LinkClick") || (blnForceDownload && folderMapping.FolderProviderType == "StandardFolderProvider")) + { + fileManager.WriteFileToResponse(file, contentDisposition); + download = true; + } + else + { + context.Response.Redirect(directUrl, /*endResponse*/ true); + } + } + catch (PermissionsNotMetException) + { + if (context.Request.IsAuthenticated) + { + context.Response.Redirect(Globals.AccessDeniedURL(Localization.Localization.GetString("FileAccess.Error")), true); + } + else + { + context.Response.Redirect(Globals.AccessDeniedURL(), true); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + if (!download) + { + Exceptions.Exceptions.ProcessHttpException(URL); + } + break; + case TabType.Url: + //prevent phishing by verifying that URL exists in URLs table for Portal + if (objUrls.GetUrl(_portalSettings.PortalId, URL) != null) + { + context.Response.Redirect(URL, true); + } + break; + default: + //redirect to URL + context.Response.Redirect(URL, true); + break; + } + } + catch (ThreadAbortException exc) + { + Logger.Error(exc); + } + catch (Exception) + { + Exceptions.Exceptions.ProcessHttpException(URL); + } + } + else + { + Exceptions.Exceptions.ProcessHttpException(URL); + } + } + + public bool IsReusable + { + get + { + return true; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FileVersionController.cs b/DNN Platform/Library/Services/FileSystem/FileVersionController.cs new file mode 100644 index 00000000000..ea5095e4183 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileVersionController.cs @@ -0,0 +1,287 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.FileSystem +{ + public class FileVersionController : ComponentBase, IFileVersionController + { + #region database methods + + public string AddFileVersion(IFileInfo file, int userId, bool published, bool removeOldestVersions, Stream content = null) + { + Requires.NotNull("file", file); + + byte[] fileContent = null; + + if (content != null) + { + var buffer = new byte[16 * 1024]; + using (var ms = new MemoryStream()) + { + int read; + while ((read = content.Read(buffer, 0, buffer.Length)) > 0) + { + ms.Write(buffer, 0, read); + } + + fileContent = ms.ToArray(); + } + } + + var newVersion = DataProvider.Instance() + .AddFileVersion(file.FileId, + file.UniqueId, + file.VersionGuid, + file.FileName, + file.Extension, + file.Size, + file.Width, + file.Height, + file.ContentType, + file.Folder, + file.FolderId, + userId, + file.SHA1Hash, + file.LastModificationTime, + file.Title, + file.EnablePublishPeriod, + file.StartDate, + file.EndDate, + file.ContentItemID, + published, + fileContent); + + DataCache.RemoveCache("GetFileById" + file.FileId); + + if (removeOldestVersions) + { + RemoveOldestsVersions(file); + } + + if (published) + { + RenameFile(file, GetVersionedFilename(file, file.PublishedVersion)); + return file.FileName; + } + + return GetVersionedFilename(file, newVersion); + } + + public void SetPublishedVersion(IFileInfo file, int newPublishedVersion) + { + DataProvider.Instance().SetPublishedVersion(file.FileId, newPublishedVersion); + DataCache.RemoveCache("GetFileById" + file.FileId); + + // Rename the original file to the versioned name + // Rename the new versioned name to the original file name + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping == null) return; + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + folderProvider.RenameFile(file, GetVersionedFilename(file, file.PublishedVersion)); + folderProvider.RenameFile( + new FileInfo { FileName = GetVersionedFilename(file, newPublishedVersion), Folder = file.Folder, FolderId = file.FolderId, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID }, + file.FileName); + } + + public int DeleteFileVersion(IFileInfo file, int version) + { + Requires.NotNull("file", file); + + int newVersion; + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping == null) return Null.NullInteger; + + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + if (file.PublishedVersion == version) + { + folderProvider.DeleteFile(new FileInfo { FileId = file.FileId, FileName = file.FileName, Folder = file.Folder, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID, FolderId = file.FolderId }); + newVersion = DataProvider.Instance().DeleteFileVersion(file.FileId, version); + + folderProvider.RenameFile( + new FileInfo { FileId = file.FileId, FileName = GetVersionedFilename(file, newVersion), Folder = file.Folder, FolderId = file.FolderId, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID }, + file.FileName); + } + else + { + newVersion = DataProvider.Instance().DeleteFileVersion(file.FileId, version); + folderProvider.DeleteFile(new FileInfo { FileName = GetVersionedFilename(file, version), Folder = file.Folder, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID, FolderId = file.FolderId }); + } + + DataCache.RemoveCache("GetFileById" + file.FileId); + + return newVersion; + } + + public FileVersionInfo GetFileVersion(IFileInfo file, int version) + { + Requires.NotNull("file", file); + return CBO.FillObject(DataProvider.Instance().GetFileVersion(file.FileId, version)); + } + + public void DeleteAllUnpublishedVersions(IFileInfo file, bool resetPublishedVersionNumber) + { + Requires.NotNull("file", file); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping == null) return; + + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + foreach (var version in GetFileVersions(file)) + { + folderProvider.DeleteFile(new FileInfo { FileName = version.FileName, Folder = file.Folder, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID, FolderId = file.FolderId }); + DataProvider.Instance().DeleteFileVersion(version.FileId, version.Version); + } + + if (resetPublishedVersionNumber) + { + file.PublishedVersion = 1; + DataProvider.Instance().ResetFilePublishedVersion(file.FileId); + DataCache.RemoveCache("GetFileById" + file.FileId); + } + } + + public IEnumerable GetFileVersions(IFileInfo file) + { + Requires.NotNull("file", file); + return CBO.FillCollection(DataProvider.Instance().GetFileVersions(file.FileId)); + } + + public bool IsFolderVersioned(int folderId) + { + return IsFolderVersioned(FolderManager.Instance.GetFolder(folderId)); + } + + public bool IsFolderVersioned(IFolderInfo folder) + { + return IsFileVersionEnabled(folder.PortalID) && folder.IsVersioned; + } + + public bool IsFileVersionEnabled(int portalId) + { + return PortalController.GetPortalSettingAsBoolean("FileVersionEnabled", portalId, true); + } + + public int MaxFileVersions(int portalId) + { + return PortalController.GetPortalSettingAsInteger("MaxFileVersions", portalId, 5); + } + + public IEnumerable GetFileVersionsInFolder(int folderId) + { + Requires.NotNegative("folderId", folderId); + + return CBO.FillCollection(DataProvider.Instance().GetFileVersionsInFolder(folderId)); + } + + public Stream GetVersionContent(IFileInfo file, int version) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping == null) return null; + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + var folder = FolderManager.Instance.GetFolder(file.FolderId); + return GetVersionContent(folderProvider, folder, file, version); + } + + public void RollbackFileVersion(IFileInfo file, int version, int userId) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping == null) return; + + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + var folder = FolderManager.Instance.GetFolder(file.FolderId); + using (var content = GetVersionContent(folderProvider, folder, file, version)) + { + FileManager.Instance.AddFile(folder, file.FileName, content, true, true, file.ContentType, userId); + } + + // We need to refresh the file object + file = FileManager.Instance.GetFile(file.FileId); + var fileVersion = GetFileVersion(file, version); + file.Extension = fileVersion.Extension; + file.Size = fileVersion.Size; + file.SHA1Hash = fileVersion.SHA1Hash; + file.Width = fileVersion.Width; + file.Height = fileVersion.Height; + FileManager.Instance.UpdateFile(file); + + RemoveOldestsVersions(file); + } + + #endregion + + #region helper methods + + private Stream GetVersionContent(FolderProvider provider, IFolderInfo folder, IFileInfo file, int version) + { + return provider.GetFileStream(folder, file, version); + } + + private void RemoveOldestsVersions(IFileInfo file) + { + var portalId = FolderManager.Instance.GetFolder(file.FolderId).PortalID; + var versions = GetFileVersions(file); + var maxVersions = MaxFileVersions(portalId) - 1; // The published version is not in the FileVersions collection + if (versions.Count() > maxVersions) + { + foreach (var v in versions.OrderBy(v => v.Version).Take(versions.Count() - maxVersions)) + { + DeleteFileVersion(file, v.Version); + } + } + } + + internal static string GetVersionedFilename(IFileInfo file, int version) + { + return string.Format("{0}_{1}.v.resources", file.FileId, version); + } + + private static void RenameFile(IFileInfo file, string newFileName) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(file.PortalId, file.FolderMappingID); + if (folderMapping != null) + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + folderProvider.RenameFile(file, newFileName); + } + + DataCache.RemoveCache("GetFileById" + file.FileId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FileVersionInfo.cs b/DNN Platform/Library/Services/FileSystem/FileVersionInfo.cs new file mode 100644 index 00000000000..612e6c79e55 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FileVersionInfo.cs @@ -0,0 +1,70 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Xml.Serialization; +using DotNetNuke.Entities; + +namespace DotNetNuke.Services.FileSystem +{ + [Serializable] + public class FileVersionInfo : BaseEntityInfo + { + #region "Constructors" + + public FileVersionInfo() + { + Version = 1; + } + + #endregion + + #region "Properties" + + [XmlElement("fileid")] + public int FileId { get; set; } + + [XmlElement("version")] + public int Version { get; set; } + + [XmlElement("filename")] + public string FileName { get; set; } + + [XmlElement("contenttype")] + public string ContentType { get; set; } + + [XmlElement("extension")] + public string Extension { get; set; } + + [XmlElement("size")] + public int Size { get; set; } + + [XmlElement("height")] + public int Height { get; set; } + + [XmlElement("width")] + public int Width { get; set; } + + [XmlElement("sha1hash")] + public string SHA1Hash { get; set; } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FolderController.cs b/DNN Platform/Library/Services/FileSystem/FolderController.cs new file mode 100644 index 00000000000..0d756882eb9 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderController.cs @@ -0,0 +1,316 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : FolderController + /// + /// ----------------------------------------------------------------------------- + /// + /// Business Class that provides access to the Database for the functions within the calling classes + /// Instantiates the instance of the DataProvider and returns the object, if any + /// + /// + /// + /// ----------------------------------------------------------------------------- + public class FolderController + { + #region StorageLocationTypes enum + + public enum StorageLocationTypes + { + InsecureFileSystem = 0, + SecureFileSystem = 1, + DatabaseSecure = 2 + } + + #endregion + + #region Obsolete Methods + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.AddFolder(FolderMappingInfo folderMapping, string folderPath) ")] + public int AddFolder(FolderInfo folder) + { + var tmpFolder = FolderManager.Instance.GetFolder(folder.PortalID, folder.FolderPath); + + if (tmpFolder != null && folder.FolderID == Null.NullInteger) + { + folder.FolderID = tmpFolder.FolderID; + } + + if (folder.FolderID == Null.NullInteger) + { + folder = (FolderInfo)FolderManager.Instance.AddFolder(FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID), folder.FolderPath); + } + else + { + FolderManager.Instance.UpdateFolder(folder); + } + + return folder.FolderID; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.DeleteFolder(IFolderInfo folder) ")] + public void DeleteFolder(int PortalID, string FolderPath) + { + var folder = FolderManager.Instance.GetFolder(PortalID, FolderPath); + if (folder != null) + { + FolderManager.Instance.DeleteFolder(folder); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolder(int portalID, string folderPath) ")] + public FolderInfo GetFolder(int PortalID, string FolderPath, bool ignoreCache) + { + return (FolderInfo)FolderManager.Instance.GetFolder(PortalID, FolderPath); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolder(Guid uniqueId) ")] + public FolderInfo GetFolderByUniqueID(Guid UniqueId) + { + return (FolderInfo)FolderManager.Instance.GetFolder(UniqueId); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolder(int folderID) ")] + public FolderInfo GetFolderInfo(int PortalID, int FolderID) + { + return (FolderInfo)FolderManager.Instance.GetFolder(FolderID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolders(int portalID, string permissions, int userID) ")] + public SortedList GetFoldersByPermissionsSorted(int PortalID, string Permissions, int UserID) + { + var sortedFoldersToReturn = new SortedList(); + + var sortedFolders = FolderManager.Instance.GetFolders(PortalID, Permissions, UserID); + + foreach (var folder in sortedFolders) + { + sortedFoldersToReturn.Add(folder.FolderPath, (FolderInfo)folder); + } + + return sortedFoldersToReturn; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.GetFolders(int portalID) ")] + public SortedList GetFoldersSorted(int PortalID) + { + var sortedFoldersToReturn = new SortedList(); + + var sortedFolders = FolderManager.Instance.GetFolders(PortalID); + + foreach (var folder in sortedFolders) + { + sortedFoldersToReturn.Add(folder.FolderPath, (FolderInfo)folder); + } + + return sortedFoldersToReturn; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public string GetMappedDirectory(string virtualDirectory) + { + string mappedDir = Convert.ToString(DataCache.GetCache("DirMap:" + virtualDirectory)); + try + { + if (string.IsNullOrEmpty(mappedDir) && HttpContext.Current != null) + { + mappedDir = FileSystemUtils.AddTrailingSlash(FileSystemUtils.MapPath(virtualDirectory)); + DataCache.SetCache("DirMap:" + virtualDirectory, mappedDir); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + return mappedDir; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void SetMappedDirectory(string virtualDirectory) + { + try + { + string mappedDir = FileSystemUtils.AddTrailingSlash(FileSystemUtils.MapPath(virtualDirectory)); + DataCache.SetCache("DirMap:" + virtualDirectory, mappedDir); + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void SetMappedDirectory(string virtualDirectory, HttpContext context) + { + try + { + // The logic here was updated to use the new FileSystemUtils.MapPath so that we have consistent behavior with other Overloads + string mappedDir = FileSystemUtils.AddTrailingSlash(FileSystemUtils.MapPath(virtualDirectory)); + DataCache.SetCache("DirMap:" + virtualDirectory, mappedDir); + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0.")] + public void SetMappedDirectory(PortalInfo portalInfo, HttpContext context) + { + try + { + string virtualDirectory = Common.Globals.ApplicationPath + "/" + portalInfo.HomeDirectory + "/"; + SetMappedDirectory(virtualDirectory, context); + + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 6.0. It has been replaced by FolderManager.Instance.UpdateFolder(IFolderInfo folder) ")] + public void UpdateFolder(FolderInfo objFolderInfo) + { + FolderManager.Instance.UpdateFolder(objFolderInfo); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 5.0. It has been replaced by GetFolderInfo(ByVal PortalID As Integer, ByVal FolderID As Integer) As FolderInfo ")] + public ArrayList GetFolder(int PortalID, int FolderID) + { + var arrFolders = new ArrayList(); + FolderInfo folder = GetFolderInfo(PortalID, FolderID); + if (folder != null) + { + arrFolders.Add(folder); + } + return arrFolders; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 5.0. It has been replaced by GetFolderInfo(ByVal PortalID As Integer, ByVal FolderID As Integer, ByVal ignoreCache As Boolean) ")] + public FolderInfo GetFolder(int PortalID, string FolderPath) + { + return GetFolder(PortalID, FolderPath, true); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 5.1.1. It has been replaced by GetFolders(ByVal PortalID As Integer) As SortedList ")] + public Dictionary GetFolders(int PortalID) + { + return new Dictionary(GetFoldersSorted(PortalID)); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 5.0. It has been replaced by GetFolders(ByVal PortalID As Integer) ")] + public ArrayList GetFoldersByPortal(int PortalID) + { + var arrFolders = new ArrayList(); + foreach (KeyValuePair folderPair in GetFoldersSorted(PortalID)) + { + arrFolders.Add(folderPair.Value); + } + return arrFolders; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by AddFolder(ByVal folder As FolderInfo)")] + public int AddFolder(int PortalID, string FolderPath) + { + var objFolder = new FolderInfo(); + + objFolder.UniqueId = Guid.NewGuid(); + objFolder.VersionGuid = Guid.NewGuid(); + objFolder.PortalID = PortalID; + objFolder.FolderPath = FolderPath; + objFolder.StorageLocation = (int) StorageLocationTypes.InsecureFileSystem; + objFolder.IsProtected = false; + objFolder.IsCached = false; + + return AddFolder(objFolder); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by AddFolder(ByVal folder As FolderInfo)")] + public int AddFolder(int PortalID, string FolderPath, int StorageLocation, bool IsProtected, bool IsCached) + { + var objFolder = new FolderInfo(); + + objFolder.UniqueId = Guid.NewGuid(); + objFolder.VersionGuid = Guid.NewGuid(); + objFolder.PortalID = PortalID; + objFolder.FolderPath = FolderPath; + objFolder.StorageLocation = StorageLocation; + objFolder.IsProtected = IsProtected; + objFolder.IsCached = IsCached; + + return AddFolder(objFolder); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DotNetNuke 5.5. This function has been replaced by AddFolder(ByVal folder As FolderInfo)")] + public int AddFolder(int PortalID, string FolderPath, int StorageLocation, bool IsProtected, bool IsCached, DateTime LastUpdated) + { + FolderPath = FileSystemUtils.FormatFolderPath(FolderPath); + FolderInfo folder = GetFolder(PortalID, FolderPath, true); + + folder.StorageLocation = StorageLocation; + folder.IsProtected = IsProtected; + folder.IsCached = IsCached; + folder.LastUpdated = Null.NullDate; + + DataCache.ClearFolderCache(PortalID); + + return AddFolder(folder); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FolderInfo.cs b/DNN Platform/Library/Services/FileSystem/FolderInfo.cs new file mode 100644 index 00000000000..124e25cde66 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderInfo.cs @@ -0,0 +1,346 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web; +using System.Xml.Serialization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + [XmlRoot("folder", IsNullable = false)] + [Serializable] + public class FolderInfo : BaseEntityInfo, IHydratable, IFolderInfo + { + // local property declarations + private string _displayName; + private string _displayPath; + private FolderPermissionCollection _folderPermissions; + private int _folderMappingId; + + #region Constructors + + public FolderInfo() + { + FolderID = Null.NullInteger; + UniqueId = Guid.NewGuid(); + VersionGuid = Guid.NewGuid(); + WorkflowID = Null.NullInteger; + } + + #endregion + + #region Public Properties + + [XmlElement("folderid")] + public int FolderID { get; set; } + + [XmlElement("uniqueid")] + public Guid UniqueId { get; set; } + + [XmlElement("versionguid")] + public Guid VersionGuid { get; set; } + + [XmlElement("foldername")] + public string FolderName + { + get + { + string folderName = PathUtils.Instance.RemoveTrailingSlash(FolderPath); + if (folderName.Length > 0 && folderName.LastIndexOf("/", StringComparison.Ordinal) > -1) + { + folderName = folderName.Substring(folderName.LastIndexOf("/", StringComparison.Ordinal) + 1); + } + return folderName; + } + } + + /// + /// Gets a value indicating whether the folder has any child subfolder + /// + [XmlElement("haschildren")] + public bool HasChildren + { + get + { + return FolderManager.Instance.GetFolders(this).Any(); + } + } + + [XmlElement("displayname")] + public string DisplayName + { + get + { + if (string.IsNullOrEmpty(_displayName)) + { + _displayName = FolderName; + } + return _displayName; + } + set + { + _displayName = value; + } + } + + [XmlElement("folderpath")] + public string FolderPath { get; set; } + + [XmlElement("displaypath")] + public string DisplayPath + { + get + { + if (string.IsNullOrEmpty(_displayPath)) + { + _displayPath = FolderPath; + } + return _displayPath; + } + set + { + _displayPath = value; + } + } + + [XmlElement("iscached")] + public bool IsCached { get; set; } + + [XmlElement("isprotected")] + public bool IsProtected { get; set; } + + /// + /// Gets or sets a value indicating whether file versions are active for the folder + /// + [XmlElement("isversioned")] + public bool IsVersioned { get; set; } + + /// + /// Gets or sets the path this folder is mapped on its provider file system + /// + [XmlElement("mappedpath")] + public string MappedPath { get; set; } + + /// + /// Gets or sets a reference to the active Workflow for the folder + /// + [XmlElement("workflowid")] + public int WorkflowID { get; set; } + + [XmlIgnore] + public DateTime LastUpdated { get; set; } + + /// + /// Gets or sets a reference to the parent folder + /// + [XmlElement("parentid")] + public int ParentID { get; set; } + + [XmlElement("physicalpath")] + public string PhysicalPath + { + get + { + string physicalPath; + PortalSettings portalSettings = null; + if (HttpContext.Current != null) + { + portalSettings = PortalController.GetCurrentPortalSettings(); + } + + if (PortalID == Null.NullInteger) + { + physicalPath = Globals.HostMapPath + FolderPath; + } + else + { + if (portalSettings == null || portalSettings.PortalId != PortalID) + { + //Get the PortalInfo based on the Portalid + var objPortals = new PortalController(); + PortalInfo objPortal = objPortals.GetPortal(PortalID); + + physicalPath = objPortal.HomeDirectoryMapPath + FolderPath; + } + else + { + physicalPath = portalSettings.HomeDirectoryMapPath + FolderPath; + } + } + + return physicalPath.Replace("/", "\\"); + } + } + + [XmlElement("portalid")] + public int PortalID { get; set; } + + [XmlElement("storagelocation")] + public int StorageLocation { get; set; } + + [XmlElement("folderpermissions")] + public FolderPermissionCollection FolderPermissions + { + get + { + return _folderPermissions ?? (_folderPermissions = new FolderPermissionCollection(FolderPermissionController.GetFolderPermissionsCollectionByFolder(PortalID, FolderPath))); + } + } + + public int FolderMappingID + { + get + { + if (_folderMappingId == 0) + { + switch (StorageLocation) + { + case (int)FolderController.StorageLocationTypes.InsecureFileSystem: + _folderMappingId = FolderMappingController.Instance.GetFolderMapping(PortalID, "Standard").FolderMappingID; + break; + case (int)FolderController.StorageLocationTypes.SecureFileSystem: + _folderMappingId = FolderMappingController.Instance.GetFolderMapping(PortalID, "Secure").FolderMappingID; + break; + case (int)FolderController.StorageLocationTypes.DatabaseSecure: + _folderMappingId = FolderMappingController.Instance.GetFolderMapping(PortalID, "Database").FolderMappingID; + break; + default: + _folderMappingId = FolderMappingController.Instance.GetDefaultFolderMapping(PortalID).FolderMappingID; + break; + } + } + + return _folderMappingId; + } + set + { + _folderMappingId = value; + } + } + + public bool IsStorageSecure + { + get + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(PortalID, FolderMappingID); + return FolderProvider.Instance(folderMapping.FolderProviderType).IsStorageSecure; + } + } + + #endregion + + #region IHydratable Implementation + + /// ----------------------------------------------------------------------------- + /// + /// Fills a FolderInfo from a Data Reader + /// + /// The Data Reader to use + /// + /// [cnurse] 07/14/2008 Documented + /// [vnguyen] 30/04/2010 Modified: Added VersionGuid + /// [frivola] 04/30/2013 Modified: Added WorkflowID + /// + /// ----------------------------------------------------------------------------- + public void Fill(IDataReader dr) + { + FolderID = Null.SetNullInteger(dr["FolderID"]); + UniqueId = Null.SetNullGuid(dr["UniqueId"]); + VersionGuid = Null.SetNullGuid(dr["VersionGuid"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + FolderPath = Null.SetNullString(dr["FolderPath"]); + MappedPath = Null.SetNullString(dr["MappedPath"]); + IsCached = Null.SetNullBoolean(dr["IsCached"]); + IsProtected = Null.SetNullBoolean(dr["IsProtected"]); + StorageLocation = Null.SetNullInteger(dr["StorageLocation"]); + LastUpdated = Null.SetNullDateTime(dr["LastUpdated"]); + FolderMappingID = Null.SetNullInteger(dr["FolderMappingID"]); + IsVersioned = Null.SetNullBoolean(dr["IsVersioned"]); + WorkflowID = Null.SetNullInteger(dr["WorkflowID"]); + ParentID = Null.SetNullInteger(dr["ParentID"]); + FillBaseProperties(dr); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Key ID + /// + /// An Integer + /// + /// [cnurse] 07/14/2008 Documented + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public int KeyID + { + get + { + return FolderID; + } + set + { + FolderID = value; + } + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Deprecated in DNN 7.1. Use the parameterless constructor and object initializers")] + public FolderInfo(int portalId, string folderpath, int storageLocation, bool isProtected, bool isCached, DateTime lastUpdated) + : this(Guid.NewGuid(), portalId, folderpath, storageLocation, isProtected, isCached, lastUpdated) + { + } + + [Obsolete("Deprecated in DNN 7.1. Use the parameterless constructor and object initializers")] + public FolderInfo(Guid uniqueId, int portalId, string folderpath, int storageLocation, bool isProtected, bool isCached, DateTime lastUpdated) + { + FolderID = Null.NullInteger; + UniqueId = uniqueId; + VersionGuid = Guid.NewGuid(); + WorkflowID = Null.NullInteger; + + PortalID = portalId; + FolderPath = folderpath; + StorageLocation = storageLocation; + IsProtected = isProtected; + IsCached = isCached; + LastUpdated = lastUpdated; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FolderManager.cs b/DNN Platform/Library/Services/FileSystem/FolderManager.cs new file mode 100644 index 00000000000..3e0db7e2bbc --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderManager.cs @@ -0,0 +1,1972 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net.NetworkInformation; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.FileSystem.Internal; +using DotNetNuke.Services.Log.EventLog; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Exposes methods to manage folders. + /// + public class FolderManager : ComponentBase, IFolderManager + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(FolderManager)); + + private const string DefaultUsersFoldersPath = "Users"; + + #region Constructor + + internal FolderManager() + { + } + + #endregion + + #region Public Properties + + public virtual string MyFolderName + { + get + { + return Localization.Localization.GetString("MyFolderName"); + } + } + + #endregion + + #region Private Methods + + private int AddFolderInternal(IFolderInfo folder) + { + //Check this is not a duplicate + var tmpfolder = GetFolder(folder.PortalID, folder.FolderPath); + + if (tmpfolder != null && folder.FolderID == Null.NullInteger) + { + folder.FolderID = tmpfolder.FolderID; + } + + if (folder.FolderID == Null.NullInteger) + { + var isVersioned = folder.IsVersioned; + var workflowId = folder.WorkflowID; + + // Inherit some configuration from its Parent Folder + var parentFolder = GetParentFolder(folder.PortalID, folder.FolderPath); + var parentId = Null.NullInteger; + if (parentFolder != null) + { + isVersioned = parentFolder.IsVersioned; + workflowId = parentFolder.WorkflowID; + parentId = parentFolder.FolderID; + } + + folder.FolderPath = PathUtils.Instance.FormatFolderPath(folder.FolderPath); + folder.FolderID = DataProvider.Instance().AddFolder(folder.PortalID, + folder.UniqueId, + folder.VersionGuid, + folder.FolderPath, + folder.MappedPath, + folder.StorageLocation, + folder.IsProtected, + folder.IsCached, + folder.LastUpdated, + GetCurrentUserId(), + folder.FolderMappingID, + isVersioned, + workflowId, + parentId); + + //Refetch folder for logging + folder = GetFolder(folder.PortalID, folder.FolderPath); + + AddLogEntry(folder, EventLogController.EventLogType.FOLDER_CREATED); + + if (parentFolder != null) + { + UpdateFolderInternal(parentFolder, false); + } + else + { + UpdateParentFolder(folder.PortalID, folder.FolderPath); + } + } + else + { + var parentFolder = GetParentFolder(folder.PortalID, folder.FolderPath); + if (parentFolder != null) + { + // Ensure that Parent Id is repaired + folder.ParentID = parentFolder.FolderID; + } + UpdateFolderInternal(folder, false); + } + + //Invalidate Cache + ClearFolderCache(folder.PortalID); + + return folder.FolderID; + } + + private IFolderInfo GetParentFolder(int portalId, string folderPath) + { + if (!String.IsNullOrEmpty(folderPath)) + { + var parentFolderPath = folderPath.Substring(0, folderPath.Substring(0, folderPath.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1); + return GetFolder(portalId, parentFolderPath); + } + + return null; + } + + private IEnumerable SearchFiles(IFolderInfo folder, Regex regex, bool recursive) + { + var fileCollection = CBOWrapper.Instance.FillCollection(DataProvider.Instance().GetFiles(folder.FolderID)); + + var files = (from f in fileCollection where regex.IsMatch(f.FileName) select f).Cast().ToList(); + + if (recursive) + { + foreach (var subFolder in GetFolders(folder)) + { + if (FolderPermissionControllerWrapper.Instance.CanViewFolder(subFolder)) + { + files.AddRange(SearchFiles(subFolder, regex, true)); + } + } + } + + return files; + } + + private IFolderInfo UpdateFolderInternal(IFolderInfo folder, bool clearCache) + { + Requires.NotNull("folder", folder); + + DataProvider.Instance().UpdateFolder(folder.PortalID, + folder.VersionGuid, + folder.FolderID, + PathUtils.Instance.FormatFolderPath(folder.FolderPath), + folder.StorageLocation, + folder.MappedPath, + folder.IsProtected, + folder.IsCached, + folder.LastUpdated, + GetCurrentUserId(), + folder.FolderMappingID, + folder.IsVersioned, + folder.WorkflowID, + folder.ParentID); + + if (clearCache) + { + ClearFolderCache(folder.PortalID); + } + + return folder; + } + + private static Regex WildcardToRegex(string pattern) + { + if (!pattern.Contains("*") && !pattern.Contains("?")) + { + pattern = "^" + pattern + ".*$"; + } + else + { + pattern = "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$"; + } + + return new Regex(pattern, RegexOptions.IgnoreCase); + } + + private static bool IsStandardFolderProviderType(FolderMappingInfo folderMappingInfo) + { + var compatibleTypes = new[] { "StandardFolderProvider", "SecureFolderProvider", "DatabaseFolderProvider" }; + return compatibleTypes.Contains(folderMappingInfo.FolderProviderType); + } + #endregion + + #region Public Methods + + /// + /// Creates a new folder using the provided folder path. + /// + /// The folder mapping to use. + /// The path of the new folder. + /// Thrown when folderPath or folderMapping are null. + /// Thrown when the underlying system throw an exception. + /// The added folder. + public virtual IFolderInfo AddFolder(FolderMappingInfo folderMapping, string folderPath) + { + return AddFolder(folderMapping, folderPath, folderPath); + } + + /// + /// Creates a new folder using the provided folder path and mapping. + /// + /// The folder mapping to use. + /// The path of the new folder. + /// The mapped path of the new folder. + /// Thrown when folderPath or folderMapping are null. + /// Thrown when the underlying system throw an exception. + /// The added folder. + public virtual IFolderInfo AddFolder(FolderMappingInfo folderMapping, string folderPath, string mappedPath) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNull("folderMapping", folderMapping); + + if (FolderExists(folderMapping.PortalID, folderPath)) + { + throw new FolderAlreadyExistsException(Localization.Localization.GetExceptionMessage("AddFolderAlreadyExists", "The provided folder path already exists. The folder has not been added.")); + } + + var parentFolder = GetParentFolder(folderMapping.PortalID, folderPath); + if (parentFolder != null) + { + var parentFolderMapping = FolderMappingController.Instance.GetFolderMapping(parentFolder.PortalID, parentFolder.FolderMappingID); + if (FolderProvider.Instance(parentFolderMapping.FolderProviderType).SupportsMappedPaths) + { + folderMapping = parentFolderMapping; + mappedPath = + PathUtils.Instance.FormatFolderPath(parentFolder.MappedPath + + folderPath.Replace(parentFolder.FolderPath, string.Empty)); + } + else if (!FolderProvider.Instance(folderMapping.FolderProviderType).SupportsMappedPaths) + { + mappedPath = folderPath; + } + } + + try + { + FolderProvider.Instance(folderMapping.FolderProviderType).AddFolder(folderPath, folderMapping, mappedPath); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("AddFolderUnderlyingSystemError", "The underlying system threw an exception. The folder has not been added."), ex); + } + + CreateFolderInFileSystem(PathUtils.Instance.GetPhysicalPath(folderMapping.PortalID, folderPath)); + var folderId = CreateFolderInDatabase(folderMapping.PortalID, folderPath, folderMapping.FolderMappingID, mappedPath); + + return GetFolder(folderId); + } + + /// + /// Creates a new folder in the given portal using the provided folder path. + /// The same mapping than the parent folder will be used to create this folder. So this method have to be used only to create subfolders. + /// + /// The portal identifier. + /// The path of the new folder. + /// Thrown when folderPath is null or empty. + /// The added folder. + public virtual IFolderInfo AddFolder(int portalId, string folderPath) + { + Requires.NotNullOrEmpty("folderPath", folderPath); + + folderPath = PathUtils.Instance.FormatFolderPath(folderPath); + + var parentFolderPath = folderPath.Substring(0, folderPath.Substring(0, folderPath.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1); + var parentFolder = GetFolder(portalId, parentFolderPath) ?? AddFolder(portalId, parentFolderPath); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(portalId, parentFolder.FolderMappingID); + + return AddFolder(folderMapping, folderPath); + } + + /// + /// Deletes the specified folder. + /// + /// The folder to delete. + /// Thrown when folder is null. + /// Thrown when the underlying system throw an exception. + public virtual void DeleteFolder(IFolderInfo folder) + { + Requires.NotNull("folder", folder); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + + try + { + FolderProvider.Instance(folderMapping.FolderProviderType).DeleteFolder(folder); + } + catch (Exception ex) + { + Logger.Error(ex); + + throw new FolderProviderException(Localization.Localization.GetExceptionMessage("DeleteFolderUnderlyingSystemError", "The underlying system threw an exception. The folder has not been deleted."), ex); + } + + if (DirectoryWrapper.Instance.Exists(folder.PhysicalPath)) + { + DirectoryWrapper.Instance.Delete(folder.PhysicalPath, false); + } + DeleteFolder(folder.PortalID, folder.FolderPath); + } + + /// + /// Deletes the specified folder. + /// + /// The folder identifier. + public virtual void DeleteFolder(int folderId) + { + var folder = GetFolder(folderId); + + DeleteFolder(folder); + } + + /// + /// Checks the existence of the specified folder in the specified portal. + /// + /// The portal where to check the existence of the folder. + /// The path of folder to check the existence of. + /// A bool value indicating whether the folder exists or not in the specified portal. + public virtual bool FolderExists(int portalId, string folderPath) + { + Requires.NotNull("folderPath", folderPath); + + return GetFolder(portalId, folderPath) != null; + } + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// The list of files contained in the specified folder. + public virtual IEnumerable GetFiles(IFolderInfo folder) + { + return GetFiles(folder, false); + } + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// Whether or not to include all the subfolders + /// The list of files contained in the specified folder. + public virtual IEnumerable GetFiles(IFolderInfo folder, bool recursive) + { + return GetFiles(folder, recursive, false); + } + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// Whether or not to include all the subfolders + /// Indicates if the file is retrieved from All files or from Published files + /// The list of files contained in the specified folder. + public virtual IEnumerable GetFiles(IFolderInfo folder, bool recursive, bool retrieveUnpublishedFiles) + { + Requires.NotNull("folder", folder); + + var fileCollection = CBOWrapper.Instance.FillCollection(DataProvider.Instance().GetFiles(folder.FolderID, retrieveUnpublishedFiles)); + + var files = fileCollection.Cast().ToList(); + + if (recursive) + { + foreach (var subFolder in GetFolders(folder)) + { + files.AddRange(GetFiles(subFolder, true, retrieveUnpublishedFiles)); + } + } + + return files; + } + + /// + /// Gets the list of Standard folders the specified user has the provided permissions. + /// + /// The user info + /// The permissions the folders have to met. + /// The list of Standard folders the specified user has the provided permissions. + /// This method is used to support legacy behaviours and situations where we know the file/folder is in the file system. + public virtual IEnumerable GetFileSystemFolders(UserInfo user, string permissions) + { + var userFolders = new List(); + + var portalId = user.PortalID; + + var userFolder = GetUserFolder(user); + + var defaultFolderMaping = FolderMappingController.Instance.GetDefaultFolderMapping(portalId); + + var folders = GetFolders(portalId, permissions, user.UserID).Where(f => f.FolderPath != null && f.FolderMappingID == defaultFolderMaping.FolderMappingID); + + foreach (var folder in folders) + { + if (folder.FolderPath.StartsWith(DefaultUsersFoldersPath + "/", StringComparison.InvariantCultureIgnoreCase)) + { + if (folder.FolderID == userFolder.FolderID) + { + folder.DisplayPath = MyFolderName + "/"; + folder.DisplayName = MyFolderName; + } + else if (!folder.FolderPath.StartsWith(userFolder.FolderPath, StringComparison.InvariantCultureIgnoreCase)) //Allow UserFolder children + { + continue; + } + } + + userFolders.Add(folder); + } + + return userFolders; + } + + /// + /// Gets a folder entity by providing a folder identifier. + /// + /// The identifier of the folder. + /// The folder entity or null if the folder cannot be located. + public virtual IFolderInfo GetFolder(int folderId) + { + //Try and get the folder from the portal cache + IFolderInfo folder = null; + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings != null) + { + var folders = GetFolders(portalSettings.PortalId); + folder = folders.SingleOrDefault(f => f.FolderID == folderId) ?? CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFolder(folderId)); + } + + return folder ?? (CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFolder(folderId))); + } + + /// + /// Gets a folder entity by providing a portal identifier and folder path. + /// + /// The portal where the folder exists. + /// The path of the folder. + /// The folder entity or null if the folder cannot be located. + public virtual IFolderInfo GetFolder(int portalId, string folderPath) + { + Requires.NotNull("folderPath", folderPath); + + folderPath = PathUtils.Instance.FormatFolderPath(folderPath); + + var folders = GetFolders(portalId); + return folders.SingleOrDefault(f => f.FolderPath == folderPath) ?? CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFolder(portalId, folderPath)); + } + + /// + /// Gets a folder entity by providing its unique id. + /// + /// The unique id of the folder. + /// The folder entity or null if the folder cannot be located. + public virtual IFolderInfo GetFolder(Guid uniqueId) + { + return CBOWrapper.Instance.FillObject(DataProvider.Instance().GetFolderByUniqueID(uniqueId)); + } + + /// + /// Gets the list of subfolders for the specified folder. + /// + /// The folder to get the list of subfolders. + /// The list of subfolders for the specified folder. + /// Thrown when parentFolder is null. + public virtual IEnumerable GetFolders(IFolderInfo parentFolder) + { + Requires.NotNull("parentFolder", parentFolder); + + return GetFolders(parentFolder.PortalID).Where(f => f.ParentID == parentFolder.FolderID); + } + + /// + /// Gets the sorted list of folders of the provided portal. + /// + /// The portal identifier. + /// True = Read from Cache, False = Read from DB + /// The sorted list of folders of the provided portal. + public virtual IEnumerable GetFolders(int portalId, bool useCache) + { + if (!useCache) + { + ClearFolderCache(portalId); + } + + return GetFolders(portalId); + } + + /// + /// Gets the sorted list of folders of the provided portal. + /// + /// The portal identifier. + /// The sorted list of folders of the provided portal. + public virtual IEnumerable GetFolders(int portalId) + { + var folders = new List(); + + var cacheKey = string.Format(DataCache.FolderCacheKey, portalId); + CBOWrapper.Instance.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.FolderCacheTimeOut, DataCache.FolderCachePriority, portalId), GetFoldersSortedCallBack).ForEach(folders.Add); + + return folders; + } + + /// + /// Gets the sorted list of folders that match the provided permissions in the specified portal. + /// + /// The portal identifier. + /// The permissions to match. + /// The user identifier to be used to check permissions. + /// The list of folders that match the provided permissions in the specified portal. + public virtual IEnumerable GetFolders(int portalId, string permissions, int userId) + { + var folders = new List(); + + var cacheKey = string.Format(DataCache.FolderUserCacheKey, portalId, permissions, userId); + var cacheItemArgs = new CacheItemArgs(cacheKey, DataCache.FolderUserCacheTimeOut, DataCache.FolderUserCachePriority, portalId, permissions, userId); + CBOWrapper.Instance.GetCachedObject>(cacheItemArgs, GetFoldersByPermissionSortedCallBack).ForEach(folders.Add); + + return folders; + } + + /// + /// Gets the list of folders the specified user has read permissions + /// + /// The user info + /// The list of folders the specified user has read permissions. + public virtual IEnumerable GetFolders(UserInfo user) + { + return GetFolders(user, "READ"); + } + + /// + /// Gets the list of folders the specified user has the provided permissions + /// + /// The user info + /// The permissions the folders have to met. + /// The list of folders the specified user has the provided permissions. + public virtual IEnumerable GetFolders(UserInfo user, string permissions) + { + var userFolders = new List(); + + var portalId = user.PortalID; + + var userFolder = GetUserFolder(user); + + foreach (var folder in GetFolders(portalId, permissions, user.UserID).Where(folder => folder.FolderPath != null)) + { + if (folder.FolderPath.StartsWith(DefaultUsersFoldersPath + "/", StringComparison.InvariantCultureIgnoreCase)) + { + if (folder.FolderID == userFolder.FolderID) + { + folder.DisplayPath = Localization.Localization.GetString("MyFolderName") + "/"; + folder.DisplayName = Localization.Localization.GetString("MyFolderName"); + } + else if (!folder.FolderPath.StartsWith(userFolder.FolderPath, StringComparison.InvariantCultureIgnoreCase)) //Allow UserFolder children + { + continue; + } + } + + userFolders.Add(folder); + } + + return userFolders; + } + + public virtual IFolderInfo GetUserFolder(UserInfo userInfo) + { + //always use _default portal for a super user + int portalId = userInfo.IsSuperUser ? -1 : userInfo.PortalID; + + string userFolderPath = ((PathUtils)PathUtils.Instance).GetUserFolderPathInternal(userInfo); + return GetFolder(portalId, userFolderPath) ?? AddUserFolder(userInfo); + } + + public virtual IFolderInfo MoveFolder(IFolderInfo folder, IFolderInfo destinationFolder) + { + Requires.NotNull("folder", folder); + Requires.NotNull("destinationFolder", destinationFolder); + + var newFolderPath = PathUtils.Instance.FormatFolderPath(destinationFolder.FolderPath + folder.FolderName + "/"); + + if (folder.FolderPath == destinationFolder.FolderPath) return folder; + + if(FolderExists(folder.PortalID, newFolderPath)) + { + throw new InvalidOperationException(string.Format( + Localization.Localization.GetExceptionMessage("CannotMoveFolderAlreadyExists", + "The folder with name '{0}' cannot be moved. A folder with that name already exists under the folder '{1}'.", folder.FolderName, destinationFolder.FolderName))); + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + var destinationFolderMapping = FolderMappingController.Instance.GetFolderMapping(destinationFolder.PortalID, destinationFolder.FolderMappingID); + + if(!CanMoveBetweenFolderMappings(folderMapping, destinationFolderMapping)) + { + throw new InvalidOperationException(string.Format( + Localization.Localization.GetExceptionMessage("CannotMoveFolderBetweenFolderType", + "The folder with name '{0}' cannot be moved. Move Folder operation between this two folder types is not allowed", folder.FolderName))); + } + + if (!IsMoveOperationValid(folder, destinationFolder, newFolderPath)) + { + throw new InvalidOperationException(Localization.Localization.GetExceptionMessage("MoveFolderCannotComplete", "The operation cannot be completed.")); + } + + if ((folder.FolderMappingID == destinationFolder.FolderMappingID && FolderProvider.Instance(folderMapping.FolderProviderType).SupportsMoveFolder) || + (IsStandardFolderProviderType(folderMapping) && IsStandardFolderProviderType(destinationFolderMapping))) + { + MoveFolderWithinProvider(folder, destinationFolder); + } + else + { + MoveFolderBetweenProviders(folder, newFolderPath); + } + + //Files in cache are obsolete because their physical path is not correct after moving + DeleteFilesFromCache(folder.PortalID, newFolderPath); + return GetFolder(folder.FolderID); + } + + /// + /// Renames the specified folder by setting the new provided folder name. + /// + /// The folder to rename. + /// The new name to apply to the folder. + /// Thrown when newFolderName is null or empty. + /// Thrown when folder is null. + /// Thrown when the underlying system throw an exception. + public virtual void RenameFolder(IFolderInfo folder, string newFolderName) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("newFolderName", newFolderName); + + if (folder.FolderName.Equals(newFolderName)) return; + + var newFolderPath = folder.FolderPath.Substring(0, folder.FolderPath.LastIndexOf(folder.FolderName, StringComparison.Ordinal)) + PathUtils.Instance.FormatFolderPath(newFolderName); + + if (FolderExists(folder.PortalID, newFolderPath)) + { + throw new FolderAlreadyExistsException(Localization.Localization.GetExceptionMessage("RenameFolderAlreadyExists", "The destination folder already exists. The folder has not been renamed.")); + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, GetParentFolder(folder.PortalID, folder.FolderPath).FolderMappingID); + var provider = FolderProvider.Instance(folderMapping.FolderProviderType); + + RenameFolderInFileSystem(folder, newFolderPath); + + //Update Provider + provider.RenameFolder(folder, newFolderName); + + //Update database + UpdateChildFolders(folder, newFolderPath); + } + + /// + /// Search the files contained in the specified folder, for a matching pattern + /// + /// The folder from which to retrieve the files. + /// The patter to search for + /// The list of files contained in the specified folder. + public virtual IEnumerable SearchFiles(IFolderInfo folder, string pattern, bool recursive) + { + Requires.NotNull("folder", folder); + + if (!FolderPermissionControllerWrapper.Instance.CanViewFolder(folder)) + { + throw new FolderProviderException("No permission to view the folder"); + } + + return SearchFiles(folder, WildcardToRegex(pattern), recursive); + } + + /// + /// Synchronizes the entire folder tree for the specified portal. + /// + /// The portal identifier. + /// The number of folder collisions. + public virtual int Synchronize(int portalId) + { + var folderCollisions = Synchronize(portalId, "", true, true); + + DataCache.ClearFolderCache(portalId); + + return folderCollisions; + } + + /// + /// Syncrhonizes the specified folder, its files and its subfolders. + /// + /// The portal identifier. + /// The relative path of the folder. + /// The number of folder collisions. + public virtual int Synchronize(int portalId, string relativePath) + { + return Synchronize(portalId, relativePath, true, true); + } + + /// + /// Syncrhonizes the specified folder, its files and, optionally, its subfolders. + /// + /// The portal identifier. + /// The relative path of the folder. + /// Indicates if the synchronization has to be recursive. + /// Indicates if files need to be synchronized. + /// Thrown when there are folder mappings requiring network connection but there is no network available. + /// The number of folder collisions. + public virtual int Synchronize(int portalId, string relativePath, bool isRecursive, bool syncFiles) + { + Requires.NotNull("relativePath", relativePath); + + if (AreThereFolderMappingsRequiringNetworkConnectivity(portalId, relativePath, isRecursive) && !IsNetworkAvailable()) + { + throw new NoNetworkAvailableException(Localization.Localization.GetExceptionMessage("NoNetworkAvailableError", "Network connectivity is needed but there is no network available.")); + } + + int? scriptTimeOut = null; + + try + { + if (HttpContext.Current != null) + { + scriptTimeOut = GetCurrentScriptTimeout(); + + // Synchronization could be a time-consuming process. To not get a time-out, we need to modify the request time-out value + SetScriptTimeout(int.MaxValue); + } + + var mergedTree = GetMergedTree(portalId, relativePath, isRecursive); + + // Step 1: Add Folders + for (var i = 0; i < mergedTree.Count; i++) + { + var item = mergedTree.Values[i]; + ProcessMergedTreeItemInAddMode(item, portalId); + } + + // Step 2: Delete Files and Folders + for (var i = mergedTree.Count - 1; i >= 0; i--) + { + var item = mergedTree.Values[i]; + + if (syncFiles) + { + SynchronizeFiles(item, portalId); + } + + ProcessMergedTreeItemInDeleteMode(item, portalId); + } + } + finally + { + // Restore original time-out + if (HttpContext.Current != null && scriptTimeOut != null) + { + SetScriptTimeout(scriptTimeOut.Value); + } + } + + return 0; + } + + /// + /// Updates metadata of the specified folder. + /// + /// The folder to update. + /// Thrown when folder is null. + public virtual IFolderInfo UpdateFolder(IFolderInfo folder) + { + var updatedFolder = UpdateFolderInternal(folder, true); + + AddLogEntry(updatedFolder, EventLogController.EventLogType.FOLDER_UPDATED); + + SaveFolderPermissions(updatedFolder); + + return updatedFolder; + } + + #endregion + + #region Permission Methods + + /// + /// Adds read permissions for all users to the specified folder. + /// + /// The folder to add the permission to. + /// Used as base class for FolderPermissionInfo when there is no read permission already defined. + public virtual void AddAllUserReadPermission(IFolderInfo folder, PermissionInfo permission) + { + var roleId = Int32.Parse(Globals.glbRoleAllUsers); + + var folderPermission = + (from FolderPermissionInfo p in folder.FolderPermissions + where p.PermissionKey == "READ" && p.FolderID == folder.FolderID && p.RoleID == roleId && p.UserID == Null.NullInteger + select p).SingleOrDefault(); + + if (folderPermission != null) + { + folderPermission.AllowAccess = true; + } + else + { + folderPermission = new FolderPermissionInfo(permission) + { + FolderID = folder.FolderID, + UserID = Null.NullInteger, + RoleID = roleId, + AllowAccess = true + }; + + folder.FolderPermissions.Add(folderPermission); + } + } + + /// + /// Sets folder permissions to the given folder by copying parent folder permissions. + /// + /// The folder to copy permissions to + public virtual void CopyParentFolderPermissions(IFolderInfo folder) + { + Requires.NotNull("folder", folder); + + if (String.IsNullOrEmpty(folder.FolderPath)) return; + + var parentFolderPath = folder.FolderPath.Substring(0, folder.FolderPath.Substring(0, folder.FolderPath.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1); + + foreach (FolderPermissionInfo objPermission in + FolderPermissionController.GetFolderPermissionsCollectionByFolder(folder.PortalID, parentFolderPath)) + { + var folderPermission = new FolderPermissionInfo(objPermission) + { + FolderID = folder.FolderID, + RoleID = objPermission.RoleID, + UserID = objPermission.UserID, + AllowAccess = objPermission.AllowAccess + }; + folder.FolderPermissions.Add(folderPermission, true); + } + + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + /// + /// Sets specific folder permissions for the given role to the given folder. + /// + /// The folder to set permission to + /// The id of the permission to assign + /// The role to assign the permission to + public virtual void SetFolderPermission(IFolderInfo folder, int permissionId, int roleId) + { + SetFolderPermission(folder, permissionId, roleId, Null.NullInteger); + } + + /// + /// Sets specific folder permissions for the given role/user to the given folder. + /// + /// The folder to set permission to + /// The id of the permission to assign + /// The role to assign the permission to + /// The user to assign the permission to + public virtual void SetFolderPermission(IFolderInfo folder, int permissionId, int roleId, int userId) + { + if (folder.FolderPermissions.Cast() + .Any(fpi => fpi.FolderID == folder.FolderID && fpi.PermissionID == permissionId && fpi.RoleID == roleId && fpi.UserID == userId && fpi.AllowAccess)) + { + return; + } + + var objFolderPermissionInfo = new FolderPermissionInfo + { + FolderID = folder.FolderID, + PermissionID = permissionId, + RoleID = roleId, + UserID = userId, + AllowAccess = true + }; + + folder.FolderPermissions.Add(objFolderPermissionInfo, true); + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + /// + /// Sets folder permissions for administrator role to the given folder. + /// + /// The folder to set permission to + /// The administrator role id to assign the permission to + public virtual void SetFolderPermissions(IFolderInfo folder, int administratorRoleId) + { + Requires.NotNull("folder", folder); + + foreach (PermissionInfo objPermission in PermissionController.GetPermissionsByFolder()) + { + var folderPermission = new FolderPermissionInfo(objPermission) + { + FolderID = folder.FolderID, + RoleID = administratorRoleId + }; + + folder.FolderPermissions.Add(folderPermission, true); + } + + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + #endregion + + #region Internal Methods + + internal virtual void AddLogEntry(IFolderInfo folder, EventLogController.EventLogType eventLogType) + { + var eventLogController = new EventLogController(); + eventLogController.AddLog(folder, PortalController.GetCurrentPortalSettings(), GetCurrentUserId(), "", eventLogType); + } + + internal virtual void AddLogEntry(string propertyName, string propertyValue, EventLogController.EventLogType eventLogType) + { + var eventLogController = new EventLogController(); + eventLogController.AddLog(propertyName, propertyValue, PortalController.GetCurrentPortalSettings(), GetCurrentUserId(), eventLogType); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal void DeleteFilesFromCache(int portalId, string newFolderPath) + { + var folders = GetFolders(portalId).Where(f => f.FolderPath.StartsWith(newFolderPath)); + foreach (var folderInfo in folders) + { + var fileIds = GetFiles(folderInfo).Select(f => f.FileId); + foreach (var fileId in fileIds) + { + DataCache.RemoveCache("GetFileById" + fileId); + } + } + } + + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual IFolderInfo AddUserFolder(UserInfo user) + { + //user _default portal for all super users + var portalId = user.IsSuperUser ? -1 : user.PortalID; + + var defaultFolderMapping = FolderMappingController.Instance.GetDefaultFolderMapping(portalId); + + if (!FolderExists(portalId, DefaultUsersFoldersPath)) + { + AddFolder(defaultFolderMapping, DefaultUsersFoldersPath); + } + +#pragma warning disable 612,618 + var rootFolder = PathUtils.Instance.GetUserFolderPathElement(user.UserID, PathUtils.UserFolderElement.Root); +#pragma warning restore 612,618 + + var folderPath = PathUtils.Instance.FormatFolderPath(String.Format(DefaultUsersFoldersPath + "/{0}", rootFolder)); + + if (!FolderExists(portalId, folderPath)) + { + AddFolder(defaultFolderMapping, folderPath); + } + +#pragma warning disable 612,618 + folderPath = PathUtils.Instance.FormatFolderPath(String.Concat(folderPath, PathUtils.Instance.GetUserFolderPathElement(user.UserID, PathUtils.UserFolderElement.SubFolder))); +#pragma warning restore 612,618 + + if (!FolderExists(portalId, folderPath)) + { + AddFolder(defaultFolderMapping, folderPath); + } + + folderPath = PathUtils.Instance.FormatFolderPath(String.Concat(folderPath, user.UserID.ToString(CultureInfo.InvariantCulture))); + + if (!FolderExists(portalId, folderPath)) + { + AddFolder(defaultFolderMapping, folderPath); + + var folder = GetFolder(portalId, folderPath); + + foreach (PermissionInfo permission in PermissionController.GetPermissionsByFolder()) + { + if (permission.PermissionKey.ToUpper() == "READ" || permission.PermissionKey.ToUpper() == "WRITE" || permission.PermissionKey.ToUpper() == "BROWSE") + { + var folderPermission = new FolderPermissionInfo(permission) + { + FolderID = folder.FolderID, + UserID = user.UserID, + RoleID = Null.NullInteger, + AllowAccess = true + }; + + folder.FolderPermissions.Add(folderPermission); + + if (permission.PermissionKey.ToUpper() == "READ") + { + AddAllUserReadPermission(folder, permission); + } + } + } + + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + return GetFolder(portalId, folderPath); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool AreThereFolderMappingsRequiringNetworkConnectivity(int portalId, string relativePath, bool isRecursive) + { + var folder = GetFolder(portalId, relativePath); + + if (folder != null) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + if (folderProvider.RequiresNetworkConnectivity) + { + return true; + } + } + + if (isRecursive) + { + var folderMappingsRequiringNetworkConnectivity = from fm in FolderMappingController.Instance.GetFolderMappings(portalId) + where + fm.IsEditable && + FolderProvider.Instance(fm.FolderProviderType).RequiresNetworkConnectivity + select fm; + + return folderMappingsRequiringNetworkConnectivity.Any(); + } + + return false; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal void ClearFolderProviderCachedLists(int portalId) + { + foreach (var folderMapping in FolderMappingController.Instance.GetFolderMappings(portalId)) + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + if (folderMapping.MappingName != "Standard" && folderMapping.MappingName != "Secure" && folderMapping.MappingName != "Database") + { + var type = folderProvider.GetType(); + MethodInfo method = type.GetMethod("ClearCache"); + if (method != null) + { + method.Invoke(folderProvider, new object[] { folderMapping.FolderMappingID }); + } + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void ClearFolderCache(int portalId) + { + DataCache.ClearFolderCache(portalId); + } + + internal virtual int CreateFolderInDatabase(int portalId, string folderPath, int folderMappingId) + { + return CreateFolderInDatabase(portalId, folderPath, folderMappingId, folderPath); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual int CreateFolderInDatabase(int portalId, string folderPath, int folderMappingId, string mappedPath) + { + var isProtected = PathUtils.Instance.IsDefaultProtectedPath(folderPath); + var folderMapping = FolderMappingController.Instance.GetFolderMapping(portalId, folderMappingId); + var storageLocation = (int)FolderController.StorageLocationTypes.DatabaseSecure; + if (!folderMapping.IsEditable) + { + switch (folderMapping.MappingName) + { + case "Standard": + storageLocation = (int)FolderController.StorageLocationTypes.InsecureFileSystem; + break; + case "Secure": + storageLocation = (int)FolderController.StorageLocationTypes.SecureFileSystem; + break; + default: + storageLocation = (int)FolderController.StorageLocationTypes.DatabaseSecure; + break; + } + } + var folder = new FolderInfo + { + PortalID = portalId, + FolderPath = folderPath, + MappedPath = mappedPath, + StorageLocation = storageLocation, + IsProtected = isProtected, + IsCached = false, + FolderMappingID = folderMappingId, + LastUpdated = Null.NullDate + }; + + folder.FolderID = AddFolderInternal(folder); + + if (portalId != Null.NullInteger) + { + //Set Folder Permissions to inherit from parent + CopyParentFolderPermissions(folder); + } + + return folder.FolderID; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void CreateFolderInFileSystem(string physicalPath) + { + var di = new DirectoryInfo(physicalPath); + + if (!di.Exists) + { + di.Create(); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void DeleteFolder(int portalId, string folderPath) + { + DataProvider.Instance().DeleteFolder(portalId, PathUtils.Instance.FormatFolderPath(folderPath)); + AddLogEntry("FolderPath", folderPath, EventLogController.EventLogType.FOLDER_DELETED); + UpdateParentFolder(portalId, folderPath); + DataCache.ClearFolderCache(portalId); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void DeleteFoldersFromExternalStorageLocations(Dictionary folderMappings, IEnumerable foldersToDelete) + { + foreach (var folderToDelete in foldersToDelete) + { + // Delete source folder from its storage location + var folderMapping = GetFolderMapping(folderMappings, folderToDelete.FolderMappingID); + + try + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + // IMPORTANT: We cannot delete the folder from its storage location when it contains other subfolders + if (!folderProvider.GetSubFolders(folderToDelete.MappedPath, folderMapping).Any()) + { + folderProvider.DeleteFolder(folderToDelete); + } + } + catch (Exception ex) + { + // The folders that cannot be deleted from its storage location will be handled during the next sync + Logger.Error(ex); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual int GetCurrentScriptTimeout() + { + return HttpContext.Current.Server.ScriptTimeout; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual int GetCurrentUserId() + { + return UserController.GetCurrentUserInfo().UserID; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetDatabaseFolders(int portalId, string relativePath, bool isRecursive) + { + var databaseFolders = new SortedList(new IgnoreCaseStringComparer()); + + var folder = GetFolder(portalId, relativePath); + + if (folder != null) + { + if (!isRecursive) + { + var item = new MergedTreeItem + { + FolderID = folder.FolderID, + FolderMappingID = folder.FolderMappingID, + FolderPath = folder.FolderPath, + ExistsInDatabase = true, + MappedPath = folder.MappedPath + }; + + databaseFolders.Add(relativePath, item); + } + else + { + databaseFolders = GetDatabaseFoldersRecursive(folder); + } + } + + return databaseFolders; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetDatabaseFoldersRecursive(IFolderInfo folder) + { + var result = new SortedList(new IgnoreCaseStringComparer()); + var stack = new Stack(); + + stack.Push(folder); + + while (stack.Count > 0) + { + var folderInfo = stack.Pop(); + + var item = new MergedTreeItem + { + FolderID = folderInfo.FolderID, + FolderMappingID = folderInfo.FolderMappingID, + FolderPath = folderInfo.FolderPath, + ExistsInDatabase = true, + MappedPath = folderInfo.MappedPath + }; + + if (!result.ContainsKey(item.FolderPath)) + { + result.Add(item.FolderPath, item); + } + + foreach (var subfolder in GetFolders(folderInfo)) + { + stack.Push(subfolder); + } + } + + return result; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetFileSystemFolders(int portalId, string relativePath, bool isRecursive) + { + var fileSystemFolders = new SortedList(new IgnoreCaseStringComparer()); + + var physicalPath = PathUtils.Instance.GetPhysicalPath(portalId, relativePath); + var hideFoldersEnabled = PortalController.GetPortalSettingAsBoolean("HideFoldersEnabled", portalId, true); + + if (DirectoryWrapper.Instance.Exists(physicalPath)) + { + if (((FileWrapper.Instance.GetAttributes(physicalPath) & FileAttributes.Hidden) == FileAttributes.Hidden || physicalPath.StartsWith("_")) && hideFoldersEnabled) + { + return fileSystemFolders; + } + + if (!isRecursive) + { + var item = new MergedTreeItem + { + FolderID = -1, + FolderMappingID = -1, + FolderPath = relativePath, + ExistsInFileSystem = true, + MappedPath = String.Empty + }; + + fileSystemFolders.Add(relativePath, item); + } + else + { + fileSystemFolders = GetFileSystemFoldersRecursive(portalId, physicalPath); + } + } + + return fileSystemFolders; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetFileSystemFoldersRecursive(int portalId, string physicalPath) + { + var result = new SortedList(new IgnoreCaseStringComparer()); + var stack = new Stack(); + + stack.Push(physicalPath); + + var hideFoldersEnabled = PortalController.GetPortalSettingAsBoolean("HideFoldersEnabled", portalId, true); + + while (stack.Count > 0) + { + var dir = stack.Pop(); + + try + { + var item = new MergedTreeItem + { + FolderID = -1, + FolderMappingID = -1, + FolderPath = PathUtils.Instance.GetRelativePath(portalId, dir), + ExistsInFileSystem = true, + MappedPath = String.Empty + }; + + result.Add(item.FolderPath, item); + + foreach (var dn in DirectoryWrapper.Instance.GetDirectories(dir)) + { + if (((FileWrapper.Instance.GetAttributes(dn) & FileAttributes.Hidden) == FileAttributes.Hidden || dn.StartsWith("_")) && hideFoldersEnabled) + { + continue; + } + + stack.Push(dn); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + return result; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual FolderMappingInfo GetFolderMapping(Dictionary folderMappings, int folderMappingId) + { + if (!folderMappings.ContainsKey(folderMappingId)) + { + folderMappings.Add(folderMappingId, FolderMappingController.Instance.GetFolderMapping(folderMappingId)); + } + + return folderMappings[folderMappingId]; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetFolderMappingFoldersRecursive(FolderMappingInfo folderMapping, IFolderInfo folder) + { + var result = new SortedList(new IgnoreCaseStringComparer()); + var stack = new Stack(); + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + var baseMappedPath = folder.MappedPath; + var baseFolderPath = folder.FolderPath; + + stack.Push(baseMappedPath); + + while (stack.Count > 0) + { + var mappedPath = stack.Pop(); + var relativePath = (String.IsNullOrEmpty(mappedPath)) + ? String.Empty + : (String.IsNullOrEmpty(baseMappedPath)) + ? mappedPath + : mappedPath.Replace(baseMappedPath, ""); + + var folderPath = baseFolderPath + relativePath; + + try + { + if (folderProvider.FolderExists(mappedPath, folderMapping)) + { + var item = new MergedTreeItem + { + FolderID = -1, + FolderMappingID = folderMapping.FolderMappingID, + FolderPath = folderPath, + ExistsInFolderMapping = true, + MappedPath = mappedPath + }; + + if (!result.ContainsKey(item.FolderPath)) + { + result.Add(item.FolderPath, item); + } + + foreach (var subfolderPath in folderProvider.GetSubFolders(mappedPath, folderMapping)) + { + if (folderMapping.SyncAllSubFolders || folderProvider.FolderExists(subfolderPath, folderMapping)) + { + stack.Push(subfolderPath); + } + } + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + return result; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual object GetFoldersByPermissionSortedCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + var permissions = (string)cacheItemArgs.ParamList[1]; + var userId = (int)cacheItemArgs.ParamList[2]; + return CBOWrapper.Instance.FillCollection(DataProvider.Instance().GetFoldersByPortalAndPermissions(portalId, permissions, userId)); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual object GetFoldersSortedCallBack(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + return CBOWrapper.Instance.FillCollection(DataProvider.Instance().GetFoldersByPortal(portalId)); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList GetMergedTree(int portalId, string relativePath, bool isRecursive) + { + var fileSystemFolders = GetFileSystemFolders(portalId, relativePath, isRecursive); + var databaseFolders = GetDatabaseFolders(portalId, relativePath, isRecursive); + + var mergedTree = MergeFolderLists(fileSystemFolders, databaseFolders); + var mappedFolders = new SortedList(); + + //Some providers cache the list of objects for performance + ClearFolderProviderCachedLists(portalId); + + foreach (var mergedItem in mergedTree.Values) + { + if (mergedItem.FolderMappingID == Null.NullInteger) continue; + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(portalId, mergedItem.FolderMappingID); + + //Add any folders from non-core providers + if (folderMapping.MappingName != "Standard" && folderMapping.MappingName != "Secure" && folderMapping.MappingName != "Database") + { + if (!isRecursive) + { + mergedItem.ExistsInFolderMapping = true; + } + else + { + var folder = GetFolder(portalId, mergedItem.FolderPath); + mappedFolders = MergeFolderLists(mappedFolders, GetFolderMappingFoldersRecursive(folderMapping, folder)); + } + } + else + { + mergedItem.ExistsInFolderMapping = folderMapping.MappingName == "Database" ? mergedItem.ExistsInDatabase : mergedItem.ExistsInFileSystem; + } + } + + mergedTree = MergeFolderLists(mergedTree, mappedFolders); + + // Update ExistsInFolderMapping if the Parent Does Not ExistsInFolderMapping + var margedTreeItems = mergedTree.Values; + foreach (var mergedItem in margedTreeItems.Where(m => m.ExistsInFolderMapping + && margedTreeItems.Any(mt2 => !mt2.ExistsInFolderMapping && m.FolderPath.StartsWith(mt2.FolderPath)))) + { + mergedItem.ExistsInFolderMapping = false; + } + + return mergedTree; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsFolderMappingEditable(FolderMappingInfo folderMapping) + { + return folderMapping.IsEditable; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsMoveOperationValid(IFolderInfo folderToMove, IFolderInfo destinationFolder, string newFolderPath) + { + //FolderMapping cases + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folderToMove.PortalID, folderToMove.FolderMappingID); + if (folderToMove.FolderMappingID == destinationFolder.FolderMappingID && FolderProvider.Instance(folderMapping.FolderProviderType).SupportsMappedPaths) + { + //Root mapped folder cannot be move, when folder mappings are equal + if (folderToMove.MappedPath == string.Empty) + { + return false; + } + + //Destination folder cannot be a child mapped folder from the folder to move + if (destinationFolder.MappedPath.StartsWith(folderToMove.MappedPath)) + { + return false; + } + } + + return IsMoveOperationValid(folderToMove, newFolderPath); + } + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsMoveOperationValid(IFolderInfo folderToMove, string newFolderPath) + { + // Root folder cannot be moved + if (folderToMove.FolderPath == string.Empty) + { + return false; + } + + // newParentFolder cannot be a child of folderToMove + if (newFolderPath.StartsWith(folderToMove.FolderPath)) + { + return false; + } + + return true; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool IsNetworkAvailable() + { + return NetworkInterface.GetIsNetworkAvailable(); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual SortedList MergeFolderLists(SortedList list1, SortedList list2) + { + foreach (var item in list2.Values) + { + if (list1.ContainsKey(item.FolderPath)) + { + var existingItem = list1[item.FolderPath]; + if (existingItem.FolderID < 0) + { + existingItem.FolderID = item.FolderID; + } + if (existingItem.FolderMappingID < 0) + { + existingItem.FolderMappingID = item.FolderMappingID; + } + if (String.IsNullOrEmpty(existingItem.MappedPath)) + { + existingItem.MappedPath = item.MappedPath; + } + + existingItem.ExistsInFileSystem = existingItem.ExistsInFileSystem || item.ExistsInFileSystem; + existingItem.ExistsInDatabase = existingItem.ExistsInDatabase || item.ExistsInDatabase; + existingItem.ExistsInFolderMapping = existingItem.ExistsInFolderMapping || item.ExistsInFolderMapping; + } + else + { + list1.Add(item.FolderPath, item); + } + } + + return list1; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void MoveDirectory(string source, string target) + { + var stack = new Stack(); + stack.Push(new MoveFoldersInfo(source, target)); + + // ReSharper disable AssignNullToNotNullAttribute + while (stack.Count > 0) + { + var folders = stack.Pop(); + Directory.CreateDirectory(folders.Target); + foreach (var file in Directory.GetFiles(folders.Source, "*.*")) + { + var targetFile = Path.Combine(folders.Target, Path.GetFileName(file)); + if (File.Exists(targetFile)) File.Delete(targetFile); + File.Move(file, targetFile); + } + + foreach (var folder in Directory.GetDirectories(folders.Source)) + { + stack.Push(new MoveFoldersInfo(folder, Path.Combine(folders.Target, Path.GetFileName(folder)))); + } + } + // ReSharper restore AssignNullToNotNullAttribute + Directory.Delete(source, true); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void MoveFolderWithinProvider(IFolderInfo folder, IFolderInfo destinationFolder) + { + var newFolderPath = destinationFolder.FolderPath + folder.FolderName + "/"; + RenameFolderInFileSystem(folder, newFolderPath); + + //Update provider + var newMappedPath = destinationFolder.MappedPath + folder.FolderName + "/"; + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + var provider = FolderProvider.Instance(folderMapping.FolderProviderType); + provider.MoveFolder(folder.MappedPath, newMappedPath, folderMapping); + + //Update database + UpdateChildFolders(folder, Path.Combine(destinationFolder.FolderPath, folder.FolderName)); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void MoveFolderBetweenProviders(IFolderInfo folder, string newFolderPath) + { + RenameFolderInFileSystem(folder, newFolderPath); + + var folderInfos = GetFolders(folder.PortalID).Where(f => f.FolderPath != string.Empty && f.FolderPath.StartsWith(folder.FolderPath)).ToArray(); + var tmpFolderPath = folder.FolderPath; + + foreach (var folderInfo in folderInfos) + { + var folderPath = newFolderPath + folderInfo.FolderPath.Substring(tmpFolderPath.Length); + + var parentFolder = GetParentFolder(folder.PortalID, folderPath); + folderInfo.ParentID = parentFolder.FolderID; + folderInfo.FolderPath = folderPath; + UpdateFolderInternal(folderInfo, true); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void OverwriteFolder(IFolderInfo sourceFolder, IFolderInfo destinationFolder, Dictionary folderMappings, SortedList foldersToDelete) + { + var fileManager = FileManager.Instance; + var files = GetFiles(sourceFolder, true); + + foreach (var file in files) + { + fileManager.MoveFile(file, destinationFolder); + } + + // Delete source folder in database + DeleteFolder(sourceFolder.PortalID, sourceFolder.FolderPath); + + var folderMapping = GetFolderMapping(folderMappings, sourceFolder.FolderMappingID); + + if (IsFolderMappingEditable(folderMapping)) + { + foldersToDelete.Add(sourceFolder.FolderPath, sourceFolder); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void ProcessMergedTreeItemInAddMode(MergedTreeItem item, int portalId) + { + if (item.ExistsInFileSystem) + { + if (!item.ExistsInDatabase) + { + if (!item.ExistsInFolderMapping) + { + CreateFolderInDatabase(portalId, item.FolderPath, FolderMappingController.Instance.GetDefaultFolderMapping(portalId).FolderMappingID); + } + else + { + CreateFolderInDatabase(portalId, item.FolderPath, item.FolderMappingID); + } + } + } + else + { + if (item.ExistsInDatabase) + { + if (item.ExistsInFolderMapping) + { + CreateFolderInFileSystem(PathUtils.Instance.GetPhysicalPath(portalId, item.FolderPath)); + } + } + else // by exclusion it exists in the Folder Mapping + { + CreateFolderInFileSystem(PathUtils.Instance.GetPhysicalPath(portalId, item.FolderPath)); + CreateFolderInDatabase(portalId, item.FolderPath, item.FolderMappingID, item.MappedPath); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void ProcessMergedTreeItemInDeleteMode(MergedTreeItem item, int portalId) + { + if (item.ExistsInFileSystem) + { + if (item.ExistsInDatabase) + { + if (item.FolderPath == "") return; // Do not process root folder + + if (!item.ExistsInFolderMapping) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(portalId, item.FolderMappingID); + + if (folderMapping.IsEditable) + { + DirectoryWrapper.Instance.Delete(PathUtils.Instance.GetPhysicalPath(portalId, item.FolderPath), false); + DeleteFolder(portalId, item.FolderPath); + } + } + } + } + else + { + if (item.ExistsInDatabase && !item.ExistsInFolderMapping) + { + DeleteFolder(portalId, item.FolderPath); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void RemoveOrphanedFiles(IFolderInfo folder) + { + var files = GetFiles(folder, false, true); + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folder.FolderMappingID); + + if (folderMapping != null) + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + + foreach (var file in files) + { + try + { + if (!folderProvider.FileExists(folder, file.FileName)) + { + FileManager.Instance.DeleteFile(file); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void RenameFolderInFileSystem(IFolderInfo folder, string newFolderPath) + { + var source = folder.PhysicalPath; + + var di = new DirectoryInfo(source); + if (!di.Exists) return; + + var target = PathUtils.Instance.GetPhysicalPath(folder.PortalID, newFolderPath); + MoveDirectory(source, target); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void SaveFolderPermissions(IFolderInfo folder) + { + FolderPermissionController.SaveFolderPermissions((FolderInfo)folder); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void SetScriptTimeout(int timeout) + { + HttpContext.Current.Server.ScriptTimeout = timeout; + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void SynchronizeFiles(MergedTreeItem item, int portalId) + { + var folder = GetFolder(portalId, item.FolderPath); + + if (folder == null) + { + return; + } + + var folderMapping = FolderMappingController.Instance.GetFolderMapping(portalId, folder.FolderMappingID); + + if (folderMapping == null) + { + return; + } + + try + { + var folderProvider = FolderProvider.Instance(folderMapping.FolderProviderType); + var fileManager = FileManager.Instance; + + if (folderProvider.FolderExists(folder.MappedPath, folderMapping)) + { + var files = folderProvider.GetFiles(folder); + + files = files.Except(FileVersionController.Instance.GetFileVersionsInFolder(folder.FolderID).Select(f => f.FileName)).ToArray(); + + foreach (var fileName in files) + { + try + { + var file = fileManager.GetFile(folder, fileName, true); + + if (file == null) + { + fileManager.AddFile(folder, fileName, null, false); + } + else if (!folderProvider.IsInSync(file)) + { + fileManager.UpdateFile(file, null); + } + } + catch (InvalidFileExtensionException ex) + { + Logger.Info(ex.Message); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + } + + RemoveOrphanedFiles(folder); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void UpdateParentFolder(int portalId, string folderPath) + { + if (!String.IsNullOrEmpty(folderPath)) + { + var parentFolderPath = folderPath.Substring(0, folderPath.Substring(0, folderPath.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1); + var objFolder = GetFolder(portalId, parentFolderPath); + if (objFolder != null) + { + //UpdateFolder(objFolder); + UpdateFolderInternal(objFolder, false); + } + } + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual void UpdateChildFolders(IFolderInfo folder, string newFolderPath) + { + var originalFolderPath = folder.FolderPath; + + var folderInfos = GetFolders(folder.PortalID).Where(f => f.FolderPath != string.Empty && f.FolderPath.StartsWith(originalFolderPath)).ToArray(); + + foreach (var folderInfo in folderInfos) + { + var folderMapping = FolderMappingController.Instance.GetFolderMapping(folder.PortalID, folderInfo.FolderMappingID); + var provider = FolderProvider.Instance(folderMapping.FolderProviderType); + + var folderPath = newFolderPath + (newFolderPath.EndsWith("/") ? "" : "/") + folderInfo.FolderPath.Substring(originalFolderPath.Length); + + var parentFolder = GetParentFolder(folder.PortalID, folderPath); + folderInfo.ParentID = parentFolder.FolderID; + folderInfo.FolderPath = folderPath; + + var parentProvider = FolderProvider.Instance(FolderMappingController.Instance.GetFolderMapping(parentFolder.PortalID, parentFolder.FolderMappingID).FolderProviderType); + if (parentProvider.SupportsMappedPaths || !provider.SupportsMappedPaths) + { + if (provider.SupportsMappedPaths) + { + var mappedPath = parentFolder.FolderPath == "" ? "" : folderPath.Replace(parentFolder.FolderPath, string.Empty); + folderInfo.MappedPath = PathUtils.Instance.FormatFolderPath(parentFolder.MappedPath + mappedPath); + } + else + { + folderInfo.MappedPath = folderPath; + } + } + + UpdateFolderInternal(folderInfo, false); + } + ClearFolderCache(folder.PortalID); + } + + /// This member is reserved for internal use and is not intended to be used directly from your code. + internal virtual bool CanMoveBetweenFolderMappings(FolderMappingInfo sourceFolderMapping, FolderMappingInfo destinationFolderMapping) + { + //If Folder Mappings are exactly the same + if (sourceFolderMapping.FolderMappingID == destinationFolderMapping.FolderMappingID) + { + return true; + } + + return IsStandardFolderProviderType(sourceFolderMapping) && IsStandardFolderProviderType(destinationFolderMapping); + } + #endregion + + #region Internal Classes + + /// + /// This class and its members are reserved for internal use and are not intended to be used in your code. + /// + internal class MergedTreeItem + { + public bool ExistsInFileSystem { get; set; } + public bool ExistsInDatabase { get; set; } + public bool ExistsInFolderMapping { get; set; } + public int FolderID { get; set; } + public int FolderMappingID { get; set; } + public string FolderPath { get; set; } + public string MappedPath { get; set; } + } + + /// + /// This class and its members are reserved for internal use and are not intended to be used in your code. + /// + internal class IgnoreCaseStringComparer : IComparer + { + public int Compare(string x, string y) + { + return String.Compare(x.ToLowerInvariant(), y.ToLowerInvariant(), StringComparison.Ordinal); + } + } + + /// + /// This class and its members are reserved for internal use and are not intended to be used in your code. + /// + internal class MoveFoldersInfo + { + public string Source { get; private set; } + public string Target { get; private set; } + + public MoveFoldersInfo(string source, string target) + { + Source = source; + Target = target; + } + } + + #endregion + + #region Obsolete Methods + + /// + /// Moves the specified folder and its contents to a new location. + /// + /// The folder to move. + /// The new folder path. + /// The moved folder. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 7.1. It has been replaced by FolderManager.Instance.MoveFolder(IFolderInfo folder, IFolderInfo destinationFolder) ")] + public virtual IFolderInfo MoveFolder(IFolderInfo folder, string newFolderPath) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("newFolderPath", newFolderPath); + + var parentFolderPath = newFolderPath.Substring(0, newFolderPath.Substring(0, newFolderPath.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1); + return MoveFolder(folder, GetFolder(folder.PortalID, parentFolderPath)); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingController.cs b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingController.cs new file mode 100644 index 00000000000..4600cbd55ff --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingController.cs @@ -0,0 +1,257 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.FileSystem.Internal; + +namespace DotNetNuke.Services.FileSystem +{ + public class FolderMappingController : ComponentBase, IFolderMappingController + { + #region Constructor + + internal FolderMappingController() + { + } + + #endregion + + #region Private Variables + + private static readonly DataProvider dataProvider = DataProvider.Instance(); + private const string CacheKeyPrefix = "GetFolderMappingSettings"; + + #endregion + + #region Public Methods + + public FolderMappingInfo GetDefaultFolderMapping(int portalID) + { + return Config.GetSection("folder") != null ? + GetFolderMappings(portalID).Find(fm => fm.FolderProviderType == Config.GetDefaultProvider("folder").Name) : + GetFolderMapping(portalID, "Standard"); + } + + public int AddFolderMapping(FolderMappingInfo objFolderMapping) + { + objFolderMapping.FolderMappingID = dataProvider.AddFolderMapping(objFolderMapping.PortalID, + objFolderMapping.MappingName, + objFolderMapping.FolderProviderType, + UserController.GetCurrentUserInfo().UserID); + + UpdateFolderMappingSettings(objFolderMapping); + + ClearFolderMappingCache(objFolderMapping.PortalID); + + return objFolderMapping.FolderMappingID; + } + + public void DeleteFolderMapping(int portalID, int folderMappingID) + { + var folderManager = FolderManager.Instance; + var folders = folderManager.GetFolders(portalID); + + var folderMappingFolders = folders.Where(f => f.FolderMappingID == folderMappingID); + + if (folderMappingFolders.Count() > 0) + { + // Delete files in folders with the provided mapping (only in the database) + foreach (var file in folderMappingFolders.Select>(folderManager.GetFiles).SelectMany(files => files)) + { + dataProvider.DeleteFile(portalID, file.FileName, file.FolderId); + } + + // Remove the folders with the provided mapping that doesn't have child folders with other mapping (only in the database and filesystem) + var folders1 = folders; // copy the variable to not access a modified closure + var removableFolders = folders.Where(f => f.FolderMappingID == folderMappingID && !folders1.Any(f2 => f2.FolderID != f.FolderID && + f2.FolderPath.StartsWith(f.FolderPath) && f2.FolderMappingID != folderMappingID)); + + if (removableFolders.Count() > 0) + { + foreach (var removableFolder in removableFolders.OrderByDescending(rf => rf.FolderPath)) + { + DirectoryWrapper.Instance.Delete(removableFolder.PhysicalPath, false); + dataProvider.DeleteFolder(portalID, removableFolder.FolderPath); + } + } + + // Update the rest of folders with the provided mapping to use the standard mapping + folders = folderManager.GetFolders(portalID, false); // re-fetch the folders + + folderMappingFolders = folders.Where(f => f.FolderMappingID == folderMappingID); + + if (folderMappingFolders.Count() > 0) + { + var defaultFolderMapping = GetDefaultFolderMapping(portalID); + + foreach (var folderMappingFolder in folderMappingFolders) + { + folderMappingFolder.FolderMappingID = defaultFolderMapping.FolderMappingID; + folderManager.UpdateFolder(folderMappingFolder); + } + } + } + + dataProvider.DeleteFolderMapping(folderMappingID); + ClearFolderMappingCache(portalID); + ClearFolderMappingSettingsCache(folderMappingID); + } + + public void UpdateFolderMapping(FolderMappingInfo objFolderMapping) + { + dataProvider.UpdateFolderMapping(objFolderMapping.FolderMappingID, + objFolderMapping.MappingName, + objFolderMapping.Priority, + UserController.GetCurrentUserInfo().UserID); + + ClearFolderMappingCache(objFolderMapping.PortalID); + UpdateFolderMappingSettings(objFolderMapping); + } + + public FolderMappingInfo GetFolderMapping(int folderMappingID) + { + return CBO.FillObject(dataProvider.GetFolderMapping(folderMappingID)); + } + + public FolderMappingInfo GetFolderMapping(int portalId, int folderMappingID) + { + return GetFolderMappings(portalId).SingleOrDefault(fm => fm.FolderMappingID == folderMappingID); + } + + public FolderMappingInfo GetFolderMapping(int portalId, string mappingName) + { + return GetFolderMappings(portalId).SingleOrDefault(fm => fm.MappingName == mappingName); + } + + public List GetFolderMappings(int portalId) + { + var cacheKey = String.Format(DataCache.FolderMappingCacheKey, portalId); + return CBO.GetCachedObject>(new CacheItemArgs(cacheKey, + DataCache.FolderMappingCacheTimeOut, + DataCache.FolderMappingCachePriority), + (c) => CBO.FillCollection(dataProvider.GetFolderMappings(portalId))); + } + + public void AddDefaultFolderTypes(int portalID) + { + dataProvider.AddDefaultFolderTypes(portalID); + } + + public Hashtable GetFolderMappingSettings(int folderMappingID) + { + var strCacheKey = CacheKeyPrefix + folderMappingID; + var objSettings = (Hashtable)DataCache.GetCache(strCacheKey); + if (objSettings == null) + { + objSettings = new Hashtable(); + IDataReader dr = null; + try + { + dr = dataProvider.GetFolderMappingSettings(folderMappingID); + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + objSettings[dr.GetString(0)] = dr.GetString(1); + } + else + { + objSettings[dr.GetString(0)] = string.Empty; + } + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + var intCacheTimeout = 20 * Convert.ToInt32(Host.PerformanceSetting); + DataCache.SetCache(strCacheKey, objSettings, TimeSpan.FromMinutes(intCacheTimeout)); + } + return objSettings; + } + + #endregion + + #region Private Methods + + private static void UpdateFolderMappingSettings(FolderMappingInfo objFolderMapping) + { + foreach (string sKey in objFolderMapping.FolderMappingSettings.Keys) + { + UpdateFolderMappingSetting(objFolderMapping.FolderMappingID, sKey, Convert.ToString(objFolderMapping.FolderMappingSettings[sKey])); + } + + ClearFolderMappingSettingsCache(objFolderMapping.FolderMappingID); + } + + private static void UpdateFolderMappingSetting(int folderMappingID, string settingName, string settingValue) + { + IDataReader dr = null; + try + { + dr = dataProvider.GetFolderMappingSetting(folderMappingID, settingName); + if (dr.Read()) + { + dataProvider.UpdateFolderMappingSetting(folderMappingID, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + } + else + { + dataProvider.AddFolderMappingSetting(folderMappingID, settingName, settingValue, UserController.GetCurrentUserInfo().UserID); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + finally + { + // Ensure DataReader is closed + CBO.CloseDataReader(dr, true); + } + } + + private static void ClearFolderMappingCache(int portalId) + { + var cacheKey = String.Format(DataCache.FolderMappingCacheKey, portalId); + DataCache.RemoveCache(cacheKey); + } + + private static void ClearFolderMappingSettingsCache(int folderMappingID) + { + DataCache.RemoveCache(CacheKeyPrefix + folderMappingID); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingInfo.cs b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingInfo.cs new file mode 100644 index 00000000000..0ba90974d83 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingInfo.cs @@ -0,0 +1,157 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Services.FileSystem.Internal; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Represents the FolderMapping object and holds the Properties of that object + /// + [Serializable] + public class FolderMappingInfo : IHydratable + { + private Hashtable _folderMappingSettings; + + #region "Public Properties" + + public int FolderMappingID { get; set; } + public int PortalID { get; set; } + public string MappingName { get; set; } + public string FolderProviderType { get; set; } + public int Priority { get; set; } + + public Hashtable FolderMappingSettings + { + get + { + if (_folderMappingSettings == null) + { + if (FolderMappingID == Null.NullInteger) + { + _folderMappingSettings = new Hashtable(); + } + else + { + _folderMappingSettings = FolderMappingController.Instance.GetFolderMappingSettings(FolderMappingID); + } + } + return _folderMappingSettings; + } + } + + private string _imageUrl; + public string ImageUrl + { + get + { + if (string.IsNullOrEmpty(_imageUrl)) + { + _imageUrl = FolderProvider.Instance(FolderProviderType).GetFolderProviderIconPath(); + } + + return _imageUrl; + } + } + + public bool IsEditable + { + get + { + return !DefaultFolderProviders.GetDefaultProviders().Contains(FolderProviderType); + } + } + + public bool SyncAllSubFolders + { + get + { + if(FolderMappingSettings.ContainsKey("SyncAllSubFolders")) + { + return bool.Parse(FolderMappingSettings["SyncAllSubFolders"].ToString()); + } + + return true; + } + set + { + FolderMappingSettings["SyncAllSubFolders"] = value; + } + } + + #endregion + + #region "Constructors" + + public FolderMappingInfo() + { + FolderMappingID = Null.NullInteger; + PortalID = Null.NullInteger; + } + + public FolderMappingInfo(int portalID, string mappingName, string folderProviderType) + { + FolderMappingID = Null.NullInteger; + PortalID = portalID; + MappingName = mappingName; + FolderProviderType = folderProviderType; + } + + #endregion + + #region "IHydratable Implementation" + + /// + /// Fills a FolderInfo from a Data Reader + /// + /// The Data Reader to use + public void Fill(IDataReader dr) + { + FolderMappingID = Null.SetNullInteger(dr["FolderMappingID"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + MappingName = Null.SetNullString(dr["MappingName"]); + FolderProviderType = Null.SetNullString(dr["FolderProviderType"]); + Priority = Null.SetNullInteger(dr["Priority"]); + } + + /// + /// Gets and sets the Key ID + /// + public int KeyID + { + get + { + return FolderMappingID; + } + set + { + FolderMappingID = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingSettingsControlBase.cs b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingSettingsControlBase.cs new file mode 100644 index 00000000000..82901815a37 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderMappings/FolderMappingSettingsControlBase.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.Collections; + +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Services.FileSystem +{ + public abstract class FolderMappingSettingsControlBase : PortalModuleBase + { + /// + /// Use this method to load the provider's concrete settings. + /// + /// The Hashtable containing the folder mapping settings. + /// + /// public override void LoadSettings(Hashtable folderMappingSettings) + /// { + /// if (folderMappingSettings.ContainsKey("AccessKeyId")) + /// { + /// tbSettingValue.Text = folderMappingSettings["SettingName"].ToString(); + /// } + /// } + /// + public abstract void LoadSettings(Hashtable folderMappingSettings); + + /// + /// Use this method to update the provider's concrete settings for the specified folder mapping. + /// + /// The folder mapping identifier. + /// + /// Because this method is executed after adding / updating the folder mapping, if there are validation errors, + /// please throw an exception, as can be seen in the provided example. + /// + /// + /// public override void UpdateSettings(int folderMappingID) + /// { + /// Page.Validate(); + /// + /// if (Page.IsValid) + /// { + /// var folderMappingController = FolderMappingController.Instance; + /// var folderMapping = folderMappingController.GetFolderMapping(folderMappingID); + /// + /// folderMapping.FolderMappingSettings["SettingName"] = tbSettingValue.Text; + /// + /// folderMappingController.UpdateFolderMapping(folderMapping); + /// } + /// else + /// { + /// throw new Exception(); + /// } + /// } + /// + public abstract void UpdateSettings(int folderMappingID); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/FolderMappings/IFolderMappingController.cs b/DNN Platform/Library/Services/FileSystem/FolderMappings/IFolderMappingController.cs new file mode 100644 index 00000000000..65652ff785e --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderMappings/IFolderMappingController.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.Collections; +using System.Collections.Generic; + +namespace DotNetNuke.Services.FileSystem +{ + public interface IFolderMappingController + { + void AddDefaultFolderTypes(int portalId); + int AddFolderMapping(FolderMappingInfo objFolderMapping); + void DeleteFolderMapping(int portalId, int folderMappingId); + FolderMappingInfo GetDefaultFolderMapping(int portalId); + FolderMappingInfo GetFolderMapping(int folderMappingId); + FolderMappingInfo GetFolderMapping(int portalId, int folderMappingId); + FolderMappingInfo GetFolderMapping(int portalId, string mappingName); + List GetFolderMappings(int portalId); + Hashtable GetFolderMappingSettings(int folderMappingId); + void UpdateFolderMapping(FolderMappingInfo objFolderMapping); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/FolderProvider.cs b/DNN Platform/Library/Services/FileSystem/FolderProvider.cs new file mode 100644 index 00000000000..9c0e98ff9d3 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/FolderProvider.cs @@ -0,0 +1,424 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Base class that provides common functionallity to work with files and folders. + /// + public abstract class FolderProvider + { + #region Constants + + private const string SettingsControlId = "Settings.ascx"; + + #endregion + + #region Private Variables + + private string _providerName; + + #endregion + + #region Static Provider Methods + + /// + /// Get the list of all the folder providers. + /// + public static Dictionary GetProviderList() + { + var providerList = ComponentFactory.GetComponents(); + + foreach (var key in providerList.Keys) + { + providerList[key]._providerName = key; + } + + return providerList; + } + + /// + /// Gets an instance of a specific FolderProvider of a given name. + /// + public static FolderProvider Instance(string friendlyName) + { + var provider = ComponentFactory.GetComponent(friendlyName); + + provider._providerName = friendlyName; + + return provider; + } + + #endregion + + #region Properties + + /// + /// Gets a value indicating if the provider ensures the files/folders it manages are secure from outside access. + /// + /// + /// Some providers (e.g. Standard) store their files/folders in a way that allows for anonymous access that bypasses DotNetNuke. + /// These providers cannot guarantee that files are only accessed by authorized users and must return false. + /// + public virtual bool IsStorageSecure + { + get + { + return false; + } + } + + /// + /// Gets a value indicating if the provider requires network connectivity to do its tasks. + /// + public virtual bool RequiresNetworkConnectivity + { + get + { + return true; + } + } + + /// + /// Indicates if the folder provider supports mapped paths when creating new folders + /// + /// + /// If this method is not overrided it returns false + /// + public virtual bool SupportsMappedPaths + { + get + { + return false; + } + } + + /// + /// Gets a value indicating whether the provider supports the MoveFile method. If a provider supports the MoveFile method, the + /// folder manager does nt have to implement move by copying the file and then deleting the original. + /// + public virtual bool SupportsMoveFile + { + get { return false; } + } + + /// + /// Gets a value indicating whether the provider supports the MoveFolder method. If a provider supports the MoveFolder method, the + /// folder manager does not have to implement move by copying the folder and then deleting the original. + /// + public virtual bool SupportsMoveFolder + { + get { return false; } + } + + #endregion + + #region Private Methods + + private static void AddFolderAndMoveFiles(string folderPath, string newFolderPath, FolderMappingInfo folderMapping) + { + var folderProvider = Instance(folderMapping.FolderProviderType); + + if (!folderProvider.FolderExists(newFolderPath, folderMapping)) + { + folderProvider.AddFolder(newFolderPath, folderMapping); + } + + var folder = new FolderInfo { FolderPath = folderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.PortalID }; + var newFolder = new FolderInfo { FolderPath = newFolderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.PortalID }; + + MoveFiles(folder, newFolder, folderMapping); + } + + private static void MoveFiles(IFolderInfo folder, IFolderInfo newFolder, FolderMappingInfo folderMapping) + { + var folderProvider = Instance(folderMapping.FolderProviderType); + var files = folderProvider.GetFiles(folder); + + foreach (var file in files) + { + using (var fileContent = folderProvider.GetFileStream(folder, file)) + { + if (!fileContent.CanSeek) + { + using (var seekableStream = FileManager.Instance.GetSeekableStream(fileContent)) + { + folderProvider.AddFile(newFolder, file, seekableStream); + } + } + else + { + folderProvider.AddFile(newFolder, file, fileContent); + } + } + folderProvider.DeleteFile(new FileInfo { FileName = file, Folder = folder.FolderPath, FolderMappingID = folderMapping.FolderMappingID, PortalId = folderMapping.PortalID }); + } + } + + #endregion + + #region Virtual Methods + + public virtual void AddFolder(string folderPath, FolderMappingInfo folderMapping, string mappedPath) + { + AddFolder(folderPath, folderMapping); + } + + /// + /// Copies the specified file to the destination folder. + /// + public virtual void CopyFile(string folderPath, string fileName, string newFolderPath, FolderMappingInfo folderMapping) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNullOrEmpty("fileName", fileName); + Requires.NotNull("newFolderPath", newFolderPath); + Requires.NotNull("folderMapping", folderMapping); + + if (folderPath == newFolderPath) return; + + var sourceFolder = new FolderInfo { FolderPath = folderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.PortalID }; + var destinationFolder = new FolderInfo { FolderPath = newFolderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.PortalID }; + + using (var fileContent = GetFileStream(sourceFolder, fileName)) + { + if (!fileContent.CanSeek) + { + using (var seekableStream = FileManager.Instance.GetSeekableStream(fileContent)) + { + AddFile(destinationFolder, fileName, seekableStream); + } + } + else + { + AddFile(destinationFolder, fileName, fileContent); + } + } + } + + /// + /// Gets a file Stream of the specified file. + /// + public virtual Stream GetFileStream(IFolderInfo folder, IFileInfo file, int version) + { + return GetFileStream(folder, FileVersionController.GetVersionedFilename(file, version)); + } + + /// + /// Gets the virtual path of the control file used to display and update specific folder mapping settings. By default, the control name is Settings.ascx. + /// + /// + /// If the folder provider has special settings, this method returns the virtual path of the control that allows to display and set those settings. + /// + /// + /// The returned control must inherit from FolderMappingSettingsControlBase. + /// + public virtual string GetSettingsControlVirtualPath() + { + var provider = Config.GetProvider("folder", _providerName); + + if (provider != null) + { + var virtualPath = provider.Attributes["providerPath"] + SettingsControlId; + + if (File.Exists(System.Web.HttpContext.Current.Server.MapPath(virtualPath))) + { + return virtualPath; + } + } + + return string.Empty; + } + + /// + /// Moves a file to a new folder + /// + /// + public virtual void MoveFile(IFileInfo file, IFolderInfo destinationFolder) + { + throw new NotImplementedException("This provider does not implement MoveFile"); + } + + /// + /// Moves the folder and files at the specified folder path to the new folder path. + /// + public virtual void MoveFolder(string folderPath, string newFolderPath, FolderMappingInfo folderMapping) + { + Requires.NotNullOrEmpty("folderPath", folderPath); + Requires.NotNullOrEmpty("newFolderPath", newFolderPath); + Requires.NotNull("folderMapping", folderMapping); + + var folderProvider = Instance(folderMapping.FolderProviderType); + + AddFolderAndMoveFiles(folderPath, newFolderPath, folderMapping); + + var folder = FolderManager.Instance.GetFolder(folderMapping.PortalID, folderPath); + var folderManager = new FolderManager(); + var subFolders = folderManager.GetFolderMappingFoldersRecursive(folderMapping, folder).Skip(1).Reverse(); + + foreach (var subFolderPath in subFolders.Select(s => s.Key)) + { + var newSubFolderPath = newFolderPath + subFolderPath.Substring(folderPath.Length); + AddFolderAndMoveFiles(subFolderPath, newSubFolderPath, folderMapping); + + folderProvider.DeleteFolder(new FolderInfo { FolderPath = subFolderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.FolderMappingID }); + } + + folderProvider.DeleteFolder(new FolderInfo { FolderPath = folderPath, FolderMappingID = folderMapping.FolderMappingID, PortalID = folderMapping.PortalID }); + } + + #endregion + + #region Abstract Methods + + /// + /// Adds a new file to the specified folder. + /// + /// + /// Do not close content Stream. + /// + public abstract void AddFile(IFolderInfo folder, string fileName, Stream content); + + /// + /// Adds a new folder to a specified parent folder. + /// + public abstract void AddFolder(string folderPath, FolderMappingInfo folderMapping); + + /// + /// Deletes the specified file. + /// + public abstract void DeleteFile(IFileInfo file); + + /// + /// Deletes the specified folder. + /// + public abstract void DeleteFolder(IFolderInfo folder); + + /// + /// Checks the existence of the specified file in the underlying system. + /// + public abstract bool FileExists(IFolderInfo folder, string fileName); + + /// + /// Checks the existence of the specified folder in the underlying system. + /// + public abstract bool FolderExists(string folderPath, FolderMappingInfo folderMapping); + + /// + /// Gets the file attributes of the specified file. + /// + /// + /// Because some Providers don't support file attributes, this methods returns a nullable type to allow them to return null. + /// + public abstract FileAttributes? GetFileAttributes(IFileInfo file); + + /// + /// Gets the list of file names contained in the specified folder. + /// + public abstract string[] GetFiles(IFolderInfo folder); + + /// + /// Gets the file length. + /// + public abstract long GetFileSize(IFileInfo file); + + /// + /// Gets a file Stream of the specified file. + /// + public abstract Stream GetFileStream(IFileInfo file); + + /// + /// Gets a file Stream of the specified file. + /// + public abstract Stream GetFileStream(IFolderInfo folder, string fileName); + + /// + /// Gets the direct Url to the file. + /// + public abstract string GetFileUrl(IFileInfo file); + + /// + /// Gets the URL of the image to display in FileManager tree. + /// + public abstract string GetFolderProviderIconPath(); + + /// + /// Gets the time when the specified file was last modified. + /// + public abstract DateTime GetLastModificationTime(IFileInfo file); + + /// + /// Gets the list of subfolders for the specified folder. + /// + public abstract IEnumerable GetSubFolders(string folderPath, FolderMappingInfo folderMapping); + + /// + /// Indicates if the specified file is synchronized. + /// + public abstract bool IsInSync(IFileInfo file); + + /// + /// Renames the specified file using the new filename. + /// + public abstract void RenameFile(IFileInfo file, string newFileName); + + /// + /// Renames the specified folder using the new foldername. + /// + public abstract void RenameFolder(IFolderInfo folder, string newFolderName); + + /// + /// Sets the specified attributes to the specified file. + /// + public abstract void SetFileAttributes(IFileInfo file, FileAttributes fileAttributes); + + /// + /// Gets a value indicating if the underlying system supports file attributes. + /// + public abstract bool SupportsFileAttributes(); + + /// + /// Updates the content of the specified file. It creates it if it doesn't exist. + /// + /// + /// Do not close content Stream. + /// + public abstract void UpdateFile(IFileInfo file, Stream content); + + /// + /// Updates the content of the specified file. It creates it if it doesn't exist. + /// + /// + /// Do not close content Stream. + /// + public abstract void UpdateFile(IFolderInfo folder, string fileName, Stream content); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/IFileInfo.cs b/DNN Platform/Library/Services/FileSystem/IFileInfo.cs new file mode 100644 index 00000000000..eb76b0bdc55 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/IFileInfo.cs @@ -0,0 +1,104 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.IO; + +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Services.FileSystem +{ + public interface IFileInfo + { + string ContentType { get; set; } + string Extension { get; set; } + int FileId { get; set; } + string FileName { get; set; } + string Folder { get; set; } + int FolderId { get; set; } + int Height { get; set; } + bool IsCached { get; set; } + string PhysicalPath { get; } + int PortalId { get; set; } + string RelativePath { get; } + string SHA1Hash { get; set; } + int Size { get; set; } + int StorageLocation { get; set; } + Guid UniqueId { get; set; } + Guid VersionGuid { get; set; } + int Width { get; set; } + FileAttributes? FileAttributes { get; } + bool SupportsFileAttributes { get; } + DateTime LastModificationTime { get; set; } + int FolderMappingID { get; set; } + + /// + /// Gets or sets a metadata field with an optional title associated to the file + /// + string Title { get; set; } + + /// + /// Gets or sets a value indicating whether publish period is enabled for the file + /// + bool EnablePublishPeriod { get; set; } + + /// + /// Gets or sets the date on which the file starts to be published + /// + DateTime StartDate { get; set; } + + /// + /// Gets or sets the date on which the file ends to be published + /// + DateTime EndDate { get; set; } + + /// + /// Gets a value indicating whether the file is enabled, + /// considering if the publish period is active and if the current date is within the publish period + /// + bool IsEnabled { get; } + + /// + /// Gets or sets a reference to ContentItem, to use in Workflows + /// + int ContentItemID { get; set; } + + /// + /// Gets or sets the published version number of the file + /// + int PublishedVersion { get; set; } + + #region Supoort for BaseEntityInfo on inherited classes + + int CreatedByUserID { get; } + + DateTime CreatedOnDate { get; } + + int LastModifiedByUserID { get; } + + DateTime LastModifiedOnDate { get; } + + UserInfo CreatedByUser(int portalId); + + UserInfo LastModifiedByUser(int portalId); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/IFileManager.cs b/DNN Platform/Library/Services/FileSystem/IFileManager.cs new file mode 100644 index 00000000000..b9fc4cdb33a --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/IFileManager.cs @@ -0,0 +1,258 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.IO; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Do not implement. This interface is meant for reference and unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IFileManager + { + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// A IFileInfo as specified by the parameters. + IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent); + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exits. + /// A IFileInfo as specified by the parameters. + IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite); + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exists. + /// Indicates if permissions have to be met. + /// The content type of the file. + /// A IFileInfo as specified by the parameters. + IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite, bool checkPermissions, string contentType); + + /// + /// Adds a file to the specified folder. + /// + /// The folder where to add the file. + /// The name of the file. + /// The content of the file. + /// Indicates if the file has to be over-written if it exists. + /// Indicates if permissions have to be met. + /// The content type of the file. + /// ID of the user that creates the file + /// A IFileInfo as specified by the parameters. + IFileInfo AddFile(IFolderInfo folder, string fileName, Stream fileContent, bool overwrite, bool checkPermissions, string contentType, int createdByUserID); + + /// + /// Copies the specified file into the specified folder. + /// + /// The file to copy. + /// The folder where to copy the file to. + /// A IFileInfo with the information of the copied file. + IFileInfo CopyFile(IFileInfo file, IFolderInfo destinationFolder); + + /// + /// Deletes the specified file. + /// + /// The file to delete. + void DeleteFile(IFileInfo file); + + /// + /// Deletes the specified files. + /// + /// The files to delete. + void DeleteFiles(IEnumerable files); + + /// + /// Checks the existence of the specified file in the specified folder. + /// + /// The folder where to check the existence of the file. + /// The file name to check the existence of. + /// A boolean value indicating whether the file exists or not in the specified folder. + bool FileExists(IFolderInfo folder, string fileName); + + /// + /// Checks the existence of the specified file in the specified folder. + /// + /// The folder where to check the existence of the file. + /// The file name to check the existence of. + /// Indicates if the file is retrieved from All files or from Published files + /// A boolean value indicating whether the file exists or not in the specified folder. + bool FileExists(IFolderInfo folder, string fileName, bool retrieveUnpublishedFiles); + + /// + /// Gets the Content Type for the specified file extension. + /// + /// The file extension. + /// The Content Type for the specified extension. + string GetContentType(string extension); + + /// + /// Gets the file metadata for the specified file. + /// + /// The file identifier. + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(int fileID); + + /// + /// Gets the file metadata for the specified file. + /// + /// The file identifier. + /// Indicates if the file is retrieved from All files or from Published files + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(int fileID, bool retrieveUnpublishedFiles); + + /// + /// Gets the file metadata for the specified file. + /// + /// The folder where the file is stored. + /// The name of the file. + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(IFolderInfo folder, string fileName); + + /// + /// Gets the file metadata for the specified file. + /// + /// The folder where the file is stored. + /// The name of the file. + /// Indicates if the file is retrieved from All files or from Published files + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(IFolderInfo folder, string fileName, bool retrieveUnpublishedFiles); + + /// + /// Gets the file metadata for the specified file. + /// + /// The portal ID or Null.NullInteger for the Host + /// Relative path to the file. + /// Host and portal settings commonly return a relative path to a file. This method uses that relative path to fetch file metadata. + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(int portalId, string relativePath); + + /// + /// Gets the file metadata for the specified file. + /// + /// The portal ID or Null.NullInteger for the Host + /// Relative path to the file. + /// Indicates if the file is retrieved from All files or from Published files + /// Host and portal settings commonly return a relative path to a file. This method uses that relative path to fetch file metadata. + /// The IFileInfo object with the metadata of the specified file. + IFileInfo GetFile(int portalId, string relativePath, bool retrieveUnpublishedFiles); + + /// + /// Gets the content of the specified file. + /// + /// The file to get the content from. + /// A stream with the content of the file. + Stream GetFileContent(IFileInfo file); + + /// + /// Gets a seekable Stream based on the specified non-seekable Stream. + /// + /// A non-seekable Stream. + /// A seekable Stream. + Stream GetSeekableStream(Stream stream); + + /// + /// Gets the direct Url to the file. + /// + /// The file to get the Url. + /// The direct Url to the file. + string GetUrl(IFileInfo file); + + /// + /// Moves the specified file into the specified folder. + /// + /// The file to move. + /// The folder where to move the file to. + /// An IFileInfo with the information of the moved file. + IFileInfo MoveFile(IFileInfo file, IFolderInfo destinationFolder); + + /// + /// Renames the specified file. + /// + /// The file to rename + /// The new filename to assign to the file. + /// An IFileInfo with the information of the renamed file. + IFileInfo RenameFile(IFileInfo file, string newFileName); + + /// + /// Sets the specified FileAttributes of the file. + /// + /// The file. + /// The file attributes to add. + void SetAttributes(IFileInfo file, FileAttributes fileAttributes); + + /// + /// Extracts the files and folders contained in the specified zip file to the folder where the file belongs. + /// + /// The file to unzip. + void UnzipFile(IFileInfo file); + + /// + /// Extracts the files and folders contained in the specified zip file to the specified folder. + /// + /// The file to unzip. + /// The folder to unzip too + void UnzipFile(IFileInfo file, IFolderInfo destinationFolder); + + /// + /// Updates the metadata of the specified file. + /// + /// The file to update. + /// A IFileInfo as the updated file. + IFileInfo UpdateFile(IFileInfo file); + + /// + /// Regenerates the hash and updates the metadata of the specified file. + /// + /// The file to update. + /// Stream used to regenerate the hash. + /// A IFileInfo as the updated file. + IFileInfo UpdateFile(IFileInfo file, Stream fileContent); + + /// + /// Writes the content of the specified file into the specified stream. + /// + /// The file to write into the stream. + /// The stream to write to. + void WriteFile(IFileInfo file, Stream stream); + + /// + /// Downloads the specified file. + /// + /// The file to download. + /// Indicates how to display the document once downloaded. + void WriteFileToResponse(IFileInfo file, ContentDisposition contentDisposition); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/IFileVersionController.cs b/DNN Platform/Library/Services/FileSystem/IFileVersionController.cs new file mode 100644 index 00000000000..a2d4d9f858c --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/IFileVersionController.cs @@ -0,0 +1,135 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System.Collections.Generic; +using System.IO; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Do not implement. This interface is meant for reference and unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IFileVersionController + { + /// + /// Add a new version of the file + /// + /// The file to add a version to + /// The user who is performing the operation + /// Indicates if the new version should be the published version + /// Remove the oldest versions if # > MaxVersions + /// Version content + /// The name of the file where the content should be stored + string AddFileVersion(IFileInfo file, int userId, bool published = true, bool removeOldestVersions = true, Stream content = null); + + /// + /// Changes the published version of a file + /// + /// The file to change its published version + /// the version to change to + void SetPublishedVersion(IFileInfo file, int version); + + /// + /// Deletes a version of a file. + /// If the version to delete is the published version, the previous version gets published + /// + /// The file to delete the version from + /// The number of the version to delete + /// The new published version + int DeleteFileVersion(IFileInfo file, int version); + + /// + /// Gets the physical file with a specific version of a file + /// + /// The file to get the version from + /// The number of the version to retrieve + /// The version of the file + FileVersionInfo GetFileVersion(IFileInfo file, int version); + + /// + /// Deletes all the unpublished versions of a file + /// + /// The file with versions + /// If True reset to 1 the PublishedVersion Property of the FileInfo + void DeleteAllUnpublishedVersions(IFileInfo file, bool resetPublishedVersionNumber); + + /// + /// Returns all the versions of a file + /// + /// The file with versions + /// Collection of file versions + IEnumerable GetFileVersions(IFileInfo file); + + /// + /// This method returns true if FileVersion is enabled in the Folder, false otherwise + /// + /// Folder Id + /// true if FileVersion is enabled in the Folder, false otherwise + bool IsFolderVersioned(int folderId); + + /// + /// This method returns true if FileVersion is enabled in the Folder, false otherwise + /// + /// FolderInfo object + /// true if FileVersion is enabled in the Folder, false otherwise + bool IsFolderVersioned(IFolderInfo folder); + + /// + /// This method returns true if FileVersion is enabled in the portal, false otherwise + /// + /// Portal Id + /// true if FileVersion is enabled in the portal, false otherwise + bool IsFileVersionEnabled(int portalId); + + /// + /// This method returns the max number of versions for a portal + /// + /// Portal Id + /// Max file versions + int MaxFileVersions(int portalId); + + /// + /// Rollbacks a file to the specified version + /// + /// The file to perform the rollback + /// The version to rollback to + /// The user who is performing the operation + void RollbackFileVersion(IFileInfo file, int version, int userId); + + /// + /// Get the content of a specific version file + /// + /// The file to get the version + /// The version to obtain the content + /// The Stream with the file content + Stream GetVersionContent(IFileInfo file, int version); + + /// + /// Get all the non-published versions in a Folder + /// + /// Folder Id + /// Collection of file versions + IEnumerable GetFileVersionsInFolder(int folderId); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/IFolderInfo.cs b/DNN Platform/Library/Services/FileSystem/IFolderInfo.cs new file mode 100644 index 00000000000..a48cb1ece9d --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/IFolderInfo.cs @@ -0,0 +1,88 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Permissions; + +namespace DotNetNuke.Services.FileSystem +{ + public interface IFolderInfo + { + string DisplayName { get; set; } + string DisplayPath { get; set; } + int FolderID { get; set; } + string FolderName { get; } + string FolderPath { get; set; } + FolderPermissionCollection FolderPermissions { get; } + bool IsCached { get; set; } + bool IsProtected { get; set; } + DateTime LastUpdated { get; set; } + string PhysicalPath { get; } + int PortalID { get; set; } + int StorageLocation { get; set; } + Guid UniqueId { get; set; } + Guid VersionGuid { get; set; } + int FolderMappingID { get; set; } + bool IsStorageSecure { get; } + + /// + /// Gets or sets a value indicating whether file versions are active for the folder + /// + bool IsVersioned { get; set; } + + /// + /// Gets or sets a reference to the active Workflow for the folder + /// + int WorkflowID { get; set; } + + /// + /// Gets or sets a reference to the parent folder + /// + int ParentID { get; set; } + + /// + /// Gets or sets the path this folder is mapped on its provider file system + /// + string MappedPath { get; set; } + + /// + /// Gets a value indicating whether the folder has any child subfolder + /// + bool HasChildren { get; } + + #region Supoort for BaseEntityInfo on inherited classes + + int CreatedByUserID { get; } + + DateTime CreatedOnDate { get; } + + int LastModifiedByUserID { get; } + + DateTime LastModifiedOnDate { get; } + + UserInfo CreatedByUser(int portalId); + + UserInfo LastModifiedByUser(int portalId); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/IFolderManager.cs b/DNN Platform/Library/Services/FileSystem/IFolderManager.cs new file mode 100644 index 00000000000..faeedfc0567 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/IFolderManager.cs @@ -0,0 +1,302 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Permissions; + +namespace DotNetNuke.Services.FileSystem +{ + /// + /// Do not implement. This interface is meant for reference and unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IFolderManager + { + /// + /// Adds read permissions for all users to the specified folder. + /// + /// The folder to add the permission to. + /// Used as base class for FolderPermissionInfo when there is no read permission already defined. + void AddAllUserReadPermission(IFolderInfo folder, PermissionInfo permission); + + /// + /// Creates a new folder using the provided folder path and mapping. + /// + /// The folder mapping to use. + /// The path of the new folder. + /// The added folder. + IFolderInfo AddFolder(FolderMappingInfo folderMapping, string folderPath); + + /// + /// Creates a new folder using the provided folder path and mapping. + /// + /// The folder mapping to use. + /// The path of the new folder. + /// The path of the new folder in the provider. + /// The added folder. + IFolderInfo AddFolder(FolderMappingInfo folderMapping, string folderPath, string mappedPath); + + /// + /// Creates a new folder in the given portal using the provided folder path. + /// The same mapping than the parent folder will be used to create this folder. So this method have to be used only to create subfolders. + /// + /// The portal identifier. + /// The path of the new folder. + /// The added folder. + IFolderInfo AddFolder(int portalId, string folderPath); + + /// + /// Sets folder permissions to the given folder by copying parent folder permissions. + /// + /// The folder to copy permissions to + void CopyParentFolderPermissions(IFolderInfo folder); + + /// + /// Deletes the specified folder. + /// + /// The folder to delete. + void DeleteFolder(IFolderInfo folder); + + /// + /// Deletes the specified folder. + /// + /// The folder identifier. + void DeleteFolder(int folderId); + + /// + /// Checks the existence of the specified folder in the specified portal. + /// + /// The portal where to check the existence of the folder. + /// The path of folder to check the existence of. + /// A boolean value indicating whether the folder exists or not in the specified portal. + bool FolderExists(int portalId, string folderPath); + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// The list of files contained in the specified folder. + IEnumerable GetFiles(IFolderInfo folder); + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// Whether or not to include all the subfolders + /// The list of files contained in the specified folder. + IEnumerable GetFiles(IFolderInfo folder, bool recursive); + + /// + /// Gets the files contained in the specified folder. + /// + /// The folder from which to retrieve the files. + /// Whether or not to include all the subfolders + /// Indicates if the file is retrieved from All files or from Published files + /// The list of files contained in the specified folder. + IEnumerable GetFiles(IFolderInfo folder, bool recursive, bool retrieveUnpublishedFiles); + + /// + /// Search the files contained in the specified folder, for a matching pattern + /// + /// The folder from which to retrieve the files. + /// The patter to search for + /// Whether or not to include all the subfolders + /// The list of files contained in the specified folder. + IEnumerable SearchFiles(IFolderInfo folder, string pattern, bool recursive = false); + + /// + /// Gets the list of Standard folders the specified user has the provided permissions. + /// + /// The user info + /// The permissions the folders have to met. + /// The list of Standard folders the specified user has the provided permissions. + /// This method is used to support legacy behaviours and situations where we know the file/folder is in the file system. + IEnumerable GetFileSystemFolders(UserInfo user, string permissions); + + /// + /// Gets a folder entity by providing a portal identifier and folder identifier. + /// + /// The identifier of the folder. + /// The folder entity or null if the folder cannot be located. + IFolderInfo GetFolder(int folderId); + + /// + /// Gets a folder entity by providing a portal identifier and folder path. + /// + /// The portal where the folder exists. + /// The path of the folder. + /// The folder entity or null if the folder cannot be located. + IFolderInfo GetFolder(int portalId, string folderPath); + + /// + /// Gets a folder entity by providing its unique id. + /// + /// The unique id of the folder. + /// The folder entity or null if the folder cannot be located. + IFolderInfo GetFolder(Guid uniqueId); + + /// + /// Get the users folder + /// + /// the user + /// FolderInfo for the users folder + IFolderInfo GetUserFolder(UserInfo userInfo); + + /// + /// Gets the list of subfolders for the specified folder. + /// + /// The folder to get the list of subfolders. + /// The list of subfolders for the specified folder. + IEnumerable GetFolders(IFolderInfo parentFolder); + + /// + /// Gets the sorted list of folders of the provided portal. + /// + /// The portal identifier. + /// The sorted list of folders of the provided portal. + IEnumerable GetFolders(int portalId); + + /// + /// Gets the sorted list of folders of the provided portal. + /// + /// The portal identifier. + /// True = Read from Cache, False = Read from DB + /// The sorted list of folders of the provided portal. + IEnumerable GetFolders(int portalId, bool useCache); + + /// + /// Gets the sorted list of folders that match the provided permissions in the specified portal. + /// + /// The portal identifier. + /// The permissions to match. + /// The user identifier to be used to check permissions. + /// The list of folders that match the provided permissions in the specified portal. + IEnumerable GetFolders(int portalId, string permissions, int userId); + + /// + /// Gets the list of folders the specified user has read permissions. + /// + /// The user info + /// The list of folders the specified user has read permissions. + IEnumerable GetFolders(UserInfo user); + + /// + /// Gets the list of folders the specified user has the provided permissions. + /// + /// The user info + /// The permissions the folders have to met. + /// The list of folders the specified user has the provided permissions. + IEnumerable GetFolders(UserInfo user, string permissions); + + /// + /// Gets the alias name of the personal User Folder + /// + string MyFolderName { get; } + + /// + /// Moves the specified folder and its contents to a new location. + /// + /// The folder to move. + /// The destination folder. + /// The moved folder. + IFolderInfo MoveFolder(IFolderInfo folder, IFolderInfo destinationFolder); + + /// + /// Renames the specified folder by setting the new provided folder name. + /// + /// The folder to rename. + /// The new name to apply to the folder. + void RenameFolder(IFolderInfo folder, string newFolderName); + + /// + /// Sets specific folder permissions for the given role to the given folder. + /// + /// The folder to set permission to + /// The id of the permission to assign + /// The role to assign the permission to + void SetFolderPermission(IFolderInfo folder, int permissionId, int roleId); + + /// + /// Sets specific folder permissions for the given role/user to the given folder. + /// + /// The folder to set permission to + /// The id of the permission to assign + /// The role to assign the permission to + /// The user to assign the permission to + void SetFolderPermission(IFolderInfo folder, int permissionId, int roleId, int userId); + + /// + /// Sets folder permissions for administrator role to the given folder. + /// + /// The folder to set permission to + /// The administrator role id to assign the permission to + void SetFolderPermissions(IFolderInfo folder, int administratorRoleId); + + /// + /// Synchronizes the entire folder tree for the specified portal. + /// + /// The portal identifier. + /// The number of folder collisions. + int Synchronize(int portalId); + + /// + /// Synchronizes the specified folder, its files and its subfolders. + /// + /// The portal identifier. + /// The relative path of the folder. + /// The number of folder collisions. + int Synchronize(int portalId, string relativePath); + + /// + /// Synchronizes the specified folder, its files and, optionally, its subfolders. + /// + /// The portal identifier. + /// The relative path of the folder. + /// Indicates if the synchronization has to be recursive. + /// Indicates if files need to be synchronized. + /// The number of folder collisions. + int Synchronize(int portalId, string relativePath, bool isRecursive, bool syncFiles); + + /// + /// Updates metadata of the specified folder. + /// + /// The folder to update. + /// The updated folder + IFolderInfo UpdateFolder(IFolderInfo folder); + + #region Obsolete Methods + + /// + /// Moves the specified folder and its contents to a new location. + /// + /// The folder to move. + /// The new folder path. + /// The moved folder. + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in DNN 7.1. It has been replaced by FolderManager.Instance.MoveFolder(IFolderInfo folder, IFolderInfo destinationFolder) ")] + IFolderInfo MoveFolder(IFolderInfo folder, string newFolderPath); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Internal/DefaultFolderProviders.cs b/DNN Platform/Library/Services/FileSystem/Internal/DefaultFolderProviders.cs new file mode 100644 index 00000000000..f7d40657f25 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Internal/DefaultFolderProviders.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace DotNetNuke.Services.FileSystem.Internal +{ + /// + /// This class contains a method to return the list of names of the default folder providers. + /// + /// + /// This class is reserved for internal use and is not intended to be used directly from your code. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static class DefaultFolderProviders + { + /// + /// Returns a list with the names of the default folder providers. + /// + /// The list of names of the default folder providers. + [EditorBrowsable(EditorBrowsableState.Never)] + public static List GetDefaultProviders() + { + return new List { "StandardFolderProvider", "SecureFolderProvider", "DatabaseFolderProvider" }; + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Providers/DatabaseFolderProvider.cs b/DNN Platform/Library/Services/FileSystem/Providers/DatabaseFolderProvider.cs new file mode 100644 index 00000000000..8e4955f02da --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Providers/DatabaseFolderProvider.cs @@ -0,0 +1,304 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Services.FileSystem +// ReSharper restore CheckNamespace +{ + public class DatabaseFolderProvider : SecureFolderProvider + { + #region Private Methods + + private Stream GetFileStreamInternal(IDataReader dr) + { + byte[] bytes = null; + try + { + if (dr.Read()) + { + bytes = (byte[])dr["Content"]; + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + return bytes != null ? new MemoryStream(bytes) : null; + } + + private void UpdateFileInternal(int fileId, Stream content) + { + byte[] fileContent = null; + + if (content != null) + { + var originalPosition = content.Position; + content.Position = 0; + + var buffer = new byte[16 * 1024]; + + using (var ms = new MemoryStream()) + { + int read; + + while ((read = content.Read(buffer, 0, buffer.Length)) > 0) + { + ms.Write(buffer, 0, read); + } + + fileContent = ms.ToArray(); + } + + content.Position = originalPosition; + } + + UpdateFileContent(fileId, fileContent); + } + + #endregion + + #region Abstract Methods + + public override void AddFile(IFolderInfo folder, string fileName, Stream content) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + + UpdateFile(folder, fileName, content); + } + + public override void DeleteFile(IFileInfo file) + { + Requires.NotNull("file", file); + + ClearFileContent(file.FileId); + } + + public override bool FileExists(IFolderInfo folder, string fileName) + { + Requires.NotNull("folder", folder); + Requires.NotNull("fileName", fileName); + + return (FileManager.Instance.GetFile(folder, fileName) != null); + } + + public override bool FolderExists(string folderPath, FolderMappingInfo folderMapping) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNull("folderMapping", folderMapping); + + return (FolderManager.Instance.GetFolder(folderMapping.PortalID, folderPath) != null); + } + + public override FileAttributes? GetFileAttributes(IFileInfo file) + { + return null; + } + + public override string[] GetFiles(IFolderInfo folder) + { + Requires.NotNull("folder", folder); + + return FolderManager.Instance.GetFiles(folder).Select(file => file.FileName).ToArray(); + } + + public override long GetFileSize(IFileInfo file) + { + Requires.NotNull("file", file); + + return file.Size; + } + + public override Stream GetFileStream(IFileInfo file) + { + Requires.NotNull("file", file); + + return GetFileStreamInternal(DataProvider.Instance().GetFileContent(file.FileId)); + } + + public override Stream GetFileStream(IFolderInfo folder, string fileName) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + + var file = FileManager.Instance.GetFile(folder, fileName); + + return file != null ? GetFileStreamInternal(DataProvider.Instance().GetFileContent(file.FileId)) : null; + } + + public override Stream GetFileStream(IFolderInfo folder, IFileInfo file, int version) + { + Requires.NotNull("file", file); + + return file != null ? GetFileStreamInternal(DataProvider.Instance().GetFileVersionContent(file.FileId, version)) : null; + } + + public override string GetFileUrl(IFileInfo file) + { + Requires.NotNull("file", file); + + return TestableGlobals.Instance.LinkClick(String.Format("fileid={0}", file.FileId), Null.NullInteger, Null.NullInteger); + } + + public override string GetFolderProviderIconPath() + { + return IconControllerWrapper.Instance.IconURL("FolderDatabase", "32x32"); + } + + public override DateTime GetLastModificationTime(IFileInfo file) + { + return file.LastModificationTime; + } + + public override IEnumerable GetSubFolders(string folderPath, FolderMappingInfo folderMapping) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNull("folderMapping", folderMapping); + + var folderManager = FolderManager.Instance; + + var folder = folderManager.GetFolder(folderMapping.PortalID, folderPath); + + return folderManager.GetFolders(folder).Select(subfolder => subfolder.FolderPath); + } + + public override bool IsInSync(IFileInfo file) + { + return true; + } + + public override void MoveFile(IFileInfo file, IFolderInfo destinationFolder) + { + } + + public override void RenameFile(IFileInfo file, string newFileName) + { + } + + public override void RenameFolder(IFolderInfo folder, string newFolderName) + { + } + + public override void SetFileAttributes(IFileInfo file, FileAttributes fileAttributes) + { + } + + public override bool SupportsFileAttributes() + { + return false; + } + + public override void UpdateFile(IFileInfo file, Stream content) + { + Requires.NotNull("file", file); + + UpdateFileInternal(file.FileId, content); + } + + public override void UpdateFile(IFolderInfo folder, string fileName, Stream content) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + + var file = FileManager.Instance.GetFile(folder, fileName); + + if (file == null) return; + + UpdateFileInternal(file.FileId, content); + } + + #endregion + + #region Static Methods + + /// + /// Clears the content of the file in the database. + /// + /// The file identifier. + public static void ClearFileContent(int fileId) + { + DataProvider.Instance().ClearFileContent(fileId); + DataProvider.Instance().UpdateFileVersion(fileId, Guid.NewGuid()); + } + + /// + /// Updates the content of the file in the database. + /// + /// The file identifier. + /// The new content. + public static void UpdateFileContent(int fileId, Stream content) + { + if (content != null) + { + byte[] fileContent; + var buffer = new byte[16 * 1024]; + using (var ms = new MemoryStream()) + { + int read; + while ((read = content.Read(buffer, 0, buffer.Length)) > 0) + { + ms.Write(buffer, 0, read); + } + fileContent = ms.ToArray(); + } + + UpdateFileContent(fileId, fileContent); + } + else + { + ClearFileContent(fileId); + } + + DataProvider.Instance().UpdateFileVersion(fileId, Guid.NewGuid()); + } + + /// + /// Updates the content of the file in the database. + /// + /// The file identifier. + /// The new content. + public static void UpdateFileContent(int fileId, byte[] content) + { + if(content != null) + { + DataProvider.Instance().UpdateFileContent(fileId, content); + DataProvider.Instance().UpdateFileVersion(fileId, Guid.NewGuid()); + } + else + { + ClearFileContent(fileId); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/Providers/SecureFolderProvider.cs b/DNN Platform/Library/Services/FileSystem/Providers/SecureFolderProvider.cs new file mode 100644 index 00000000000..726d072eae0 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Providers/SecureFolderProvider.cs @@ -0,0 +1,115 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.IO; +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.FileSystem.Internal; + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Services.FileSystem +// ReSharper restore CheckNamespace +{ + public class SecureFolderProvider : StandardFolderProvider + { + #region Public Properties + + /// + /// Gets the file extension to use for protected files. + /// + public string ProtectedExtension + { + get + { + return Globals.glbProtectedExtension; + } + } + + /// + /// Gets a value indicating if the provider ensures the files/folders it manages are secure from outside access. + /// + public override bool IsStorageSecure + { + get + { + return true; + } + } + + #endregion + + #region Abstract Methods + + public override string[] GetFiles(IFolderInfo folder) + { + Requires.NotNull("folder", folder); + + var fileNames = DirectoryWrapper.Instance.GetFiles(folder.PhysicalPath); + + for (var i = 0; i < fileNames.Length; i++) + { + var fileName = Path.GetFileName(fileNames[i]); + if(!fileName.EndsWith(ProtectedExtension)) + { + FileWrapper.Instance.Move(fileNames[i], fileNames[i] + ProtectedExtension); + } + else + { + fileName = fileName.Substring(0, fileName.LastIndexOf(ProtectedExtension)); + } + + fileNames[i] = fileName; + } + + return fileNames; + } + + public override string GetFileUrl(IFileInfo file) + { + Requires.NotNull("file", file); + + return TestableGlobals.Instance.LinkClick(String.Format("fileid={0}", file.FileId), Null.NullInteger, Null.NullInteger); + } + + public override string GetFolderProviderIconPath() + { + return IconControllerWrapper.Instance.IconURL("FolderSecure", "32x32"); + } + + #endregion + + #region Protected Methods + + protected override string GetActualPath(IFileInfo file) + { + return base.GetActualPath(file) + ProtectedExtension; + } + + protected override string GetActualPath(IFolderInfo folder, string fileName) + { + return base.GetActualPath(folder, fileName) + ProtectedExtension; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/Providers/StandardFolderProvider.cs b/DNN Platform/Library/Services/FileSystem/Providers/StandardFolderProvider.cs new file mode 100644 index 00000000000..83b494d19f3 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Providers/StandardFolderProvider.cs @@ -0,0 +1,425 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.FileSystem.Internal; + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Services.FileSystem +// ReSharper restore CheckNamespace +{ + public class StandardFolderProvider : FolderProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (StandardFolderProvider)); + + #region Public Properties + + /// + /// Gets a value indicating if the provider requires network connectivity to do its tasks. + /// + public override bool RequiresNetworkConnectivity + { + get + { + return false; + } + } + + public override bool SupportsMoveFile + { + get + { + return true; + } + } + + public override bool SupportsMoveFolder + { + get { return true; } + } + + #endregion + + #region Abstract Methods + + public override void AddFile(IFolderInfo folder, string fileName, Stream content) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + Requires.NotNull("content", content); + + UpdateFile(folder, fileName, content); + } + + public override void AddFolder(string folderPath, FolderMappingInfo folderMapping) + { + } + + public override void DeleteFile(IFileInfo file) + { + Requires.NotNull("file", file); + + var path = GetActualPath(file); + + if (FileWrapper.Instance.Exists(path)) + { + FileWrapper.Instance.SetAttributes(path, FileAttributes.Normal); + FileWrapper.Instance.Delete(path); + } + } + + public override void DeleteFolder(IFolderInfo folder) + { + } + + public override bool FileExists(IFolderInfo folder, string fileName) + { + Requires.NotNull("folder", folder); + Requires.NotNull("fileName", fileName); + + return FileWrapper.Instance.Exists(GetActualPath(folder, fileName)); + } + + public override bool FolderExists(string folderPath, FolderMappingInfo folderMapping) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNull("folderMapping", folderMapping); + + return DirectoryWrapper.Instance.Exists(GetActualPath(folderMapping, folderPath)); + } + + public override FileAttributes? GetFileAttributes(IFileInfo file) + { + Requires.NotNull("file", file); + + FileAttributes? fileAttributes = null; + + try + { + fileAttributes = FileWrapper.Instance.GetAttributes(GetActualPath(file)); + } + catch (Exception ex) + { + Logger.Error(ex); + } + + return fileAttributes; + } + + public override string[] GetFiles(IFolderInfo folder) + { + Requires.NotNull("folder", folder); + + var fileNames = DirectoryWrapper.Instance.GetFiles(GetActualPath(folder)); + + for (var i = 0; i < fileNames.Length; i++) + { + fileNames[i] = Path.GetFileName(fileNames[i]); + } + + return fileNames; + } + + public override long GetFileSize(IFileInfo file) + { + Requires.NotNull("file", file); + + var physicalFile = new System.IO.FileInfo(GetActualPath(file)); + + return physicalFile.Length; + } + + public override Stream GetFileStream(IFileInfo file) + { + Requires.NotNull("file", file); + + return GetFileStreamInternal(GetActualPath(file)); + } + + public override Stream GetFileStream(IFolderInfo folder, string fileName) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + return GetFileStreamInternal(GetActualPath(folder, fileName)); + } + + public override string GetFileUrl(IFileInfo file) + { + Requires.NotNull("file", file); + + string rootFolder; + if (file.PortalId == Null.NullInteger) + { + //Host + rootFolder = Globals.HostPath; + } + else + { + //Portal + var portalSettings = GetPortalSettings(file.PortalId); + rootFolder = portalSettings.HomeDirectory; + } + //check if a filename has a character that is not valid for urls + if (Regex.IsMatch(file.FileName, @"[&()<>?*]")) + { + return Globals.LinkClick(String.Format("fileid={0}", file.FileId), Null.NullInteger, Null.NullInteger); + } + return TestableGlobals.Instance.ResolveUrl(rootFolder + file.Folder + file.FileName); + } + + public override string GetFolderProviderIconPath() + { + return IconControllerWrapper.Instance.IconURL("FolderStandard", "32x32"); + } + + public override DateTime GetLastModificationTime(IFileInfo file) + { + Requires.NotNull("file", file); + + var lastModificationTime = Null.NullDate; + + try + { + lastModificationTime = FileWrapper.Instance.GetLastWriteTime(GetActualPath(file)); + } + catch (Exception ex) + { + Logger.Error(ex); + } + + return lastModificationTime; + } + + public override IEnumerable GetSubFolders(string folderPath, FolderMappingInfo folderMapping) + { + Requires.NotNull("folderPath", folderPath); + Requires.NotNull("folderMapping", folderMapping); + + return DirectoryWrapper.Instance.GetDirectories(GetActualPath(folderMapping, folderPath)) + .Select(directory => GetRelativePath(folderMapping, directory)); + } + + public override bool IsInSync(IFileInfo file) + { + Requires.NotNull("file", file); + + return Convert.ToInt32((file.LastModificationTime - GetLastModificationTime(file)).TotalSeconds) == 0; + } + + public override void MoveFile(IFileInfo file, IFolderInfo destinationFolder) + { + Requires.NotNull("file", file); + Requires.NotNull("destinationFolder", destinationFolder); + + if (file.FolderId != destinationFolder.FolderID) + { + string oldName = GetActualPath(file); + string newName = GetActualPath(destinationFolder, file.FileName); + FileWrapper.Instance.Move(oldName, newName); + } + } + + public override void MoveFolder(string folderPath, string newFolderPath, FolderMappingInfo folderMapping) + { + // The folder has already been moved in filesystem + } + + public override void RenameFile(IFileInfo file, string newFileName) + { + Requires.NotNull("file", file); + Requires.NotNullOrEmpty("newFileName", newFileName); + + if (file.FileName != newFileName) + { + IFolderInfo folder = FolderManager.Instance.GetFolder(file.FolderId); + string oldName = GetActualPath(file); + string newName = GetActualPath(folder, newFileName); + FileWrapper.Instance.Move(oldName, newName); + } + } + + public override void RenameFolder(IFolderInfo folder, string newFolderName) + { + // The folder has already been moved in filesystem + } + + public override void SetFileAttributes(IFileInfo file, FileAttributes fileAttributes) + { + Requires.NotNull("file", file); + + FileWrapper.Instance.SetAttributes(GetActualPath(file), fileAttributes); + } + + public override bool SupportsFileAttributes() + { + return true; + } + + public override void UpdateFile(IFileInfo file, Stream content) + { + Requires.NotNull("file", file); + Requires.NotNull("content", content); + + UpdateFile(FolderManager.Instance.GetFolder(file.FolderId), file.FileName, content); + } + + public override void UpdateFile(IFolderInfo folder, string fileName, Stream content) + { + Requires.NotNull("folder", folder); + Requires.NotNullOrEmpty("fileName", fileName); + Requires.NotNull("content", content); + + var arrData = new byte[2048]; + var actualPath = GetActualPath(folder, fileName); + + if (FileWrapper.Instance.Exists(actualPath)) + { + FileWrapper.Instance.SetAttributes(actualPath, FileAttributes.Normal); + FileWrapper.Instance.Delete(actualPath); + } + + using (var outStream = FileWrapper.Instance.Create(actualPath)) + { + var originalPosition = content.Position; + content.Position = 0; + + try + { + var intLength = content.Read(arrData, 0, arrData.Length); + + while (intLength > 0) + { + outStream.Write(arrData, 0, intLength); + intLength = content.Read(arrData, 0, arrData.Length); + } + } + finally + { + content.Position = originalPosition; + } + } + } + + #endregion + + #region Internal Methods + + internal virtual string GetHash(IFileInfo file) + { + var fileManager = new FileManager(); + return fileManager.GetHash(file); + } + + internal virtual PortalSettings GetPortalSettings(int portalId) + { + return new PortalSettings(portalId); + } + + #endregion + + #region Protected Methods + + /// + /// Get actual path to an IFileInfo + /// + /// The file + /// A windows supported path to the file + protected virtual string GetActualPath(IFileInfo file) + { + return file.PhysicalPath; + } + + /// + /// Get actual path to a file in specified folder + /// + /// The folder that contains the file + /// The file name + /// A windows supported path to the file + protected virtual string GetActualPath(IFolderInfo folder, string fileName) + { + return Path.Combine(folder.PhysicalPath, fileName); + } + + /// + /// Get actual path to a folder in the specified folder mapping + /// + /// The folder mapping + /// The folder path + /// A windows supported path to the folder + protected virtual string GetActualPath(FolderMappingInfo folderMapping, string folderPath) + { + return PathUtils.Instance.GetPhysicalPath(folderMapping.PortalID, folderPath); + } + + /// + /// Get actual path to a folder + /// + /// The folder + /// A windows supported path to the folder + protected virtual string GetActualPath(IFolderInfo folder) + { + return folder.PhysicalPath; + } + + protected Stream GetFileStreamInternal(string filePath) + { + Stream stream = null; + + try + { + stream = FileWrapper.Instance.OpenRead(filePath); + } + catch (IOException iex) + { + Logger.Warn(iex.Message); + } + catch (Exception ex) + { + Logger.Error(ex); + } + + return stream; + } + + /// + /// Get the path relative to the root of the FolderMapping + /// + /// Path is relative to this + /// The path + /// A relative path + protected virtual string GetRelativePath(FolderMappingInfo folderMapping, string path) + { + return PathUtils.Instance.GetRelativePath(folderMapping.PortalID, path); + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/SynchronizeFileSystem.cs b/DNN Platform/Library/Services/FileSystem/SynchronizeFileSystem.cs new file mode 100644 index 00000000000..0c5ec4592f3 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/SynchronizeFileSystem.cs @@ -0,0 +1,88 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.FileSystem +{ + public class SynchronizeFileSystem : SchedulerClient + { + public SynchronizeFileSystem(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); //OPTIONAL + + Synchronize(); + + ScheduleHistoryItem.Succeeded = true; //REQUIRED + + ScheduleHistoryItem.AddLogNote("File System Synchronized."); //OPTIONAL + } + catch (Exception exc) + { + ScheduleHistoryItem.Succeeded = false; + + ScheduleHistoryItem.AddLogNote("File System Synchronization failed. " + exc); + + //notification that we have errored + Errored(ref exc); + + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + + private void Synchronize() + { + var folderManager = FolderManager.Instance; + + folderManager.Synchronize(Null.NullInteger); + + PortalInfo objPortal; + + var objPortals = new PortalController(); + var arrPortals = objPortals.GetPortals(); + + //Sync Portals + for (int intIndex = 0; intIndex <= arrPortals.Count - 1; intIndex++) + { + objPortal = (PortalInfo) arrPortals[intIndex]; + folderManager.Synchronize(objPortal.PortalID); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/UploadType.cs b/DNN Platform/Library/Services/FileSystem/UploadType.cs new file mode 100644 index 00000000000..32ba7d18197 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/UploadType.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.FileSystem +{ + public enum UploadType + { + File, + Container, + Skin, + Module, + LanguagePack + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/CBOWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/CBOWrapper.cs new file mode 100644 index 00000000000..f327722ee7a --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/CBOWrapper.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; + +namespace DotNetNuke.Services.FileSystem +{ + internal class CBOWrapper : ComponentBase, ICBO + { + internal CBOWrapper() + { + } + + public List FillCollection(IDataReader dr) where T : new() + { + return CBO.FillCollection(dr); + } + + public T FillObject(IDataReader dr) where T : new() + { + return CBO.FillObject(dr); + } + + public SortedList FillSortedList(string keyField, IDataReader dr) + { + return CBO.FillSortedList(keyField, dr); + } + + public T GetCachedObject(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired) + { + return CBO.GetCachedObject(cacheItemArgs, cacheItemExpired); + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/DirectoryWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/DirectoryWrapper.cs new file mode 100644 index 00000000000..ef6d3065ac7 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/DirectoryWrapper.cs @@ -0,0 +1,62 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.IO; + +using DotNetNuke.ComponentModel; + +namespace DotNetNuke.Services.FileSystem.Internal +{ + public class DirectoryWrapper : ComponentBase, IDirectory + { + public void Delete(string path, bool recursive) + { + if (Exists(path)) + { + Directory.Delete(path, recursive); + } + } + + public bool Exists(string path) + { + return Directory.Exists(path); + } + + public string[] GetDirectories(string path) + { + return Directory.GetDirectories(path); + } + + public string[] GetFiles(string path) + { + return Directory.GetFiles(path); + } + + public void Move(string sourceDirName, string destDirName) + { + Directory.Move(sourceDirName, destDirName); + } + + public void CreateDirectory(string path) + { + Directory.CreateDirectory(path); + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/FileWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/FileWrapper.cs new file mode 100644 index 00000000000..46baa86578c --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/FileWrapper.cs @@ -0,0 +1,75 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.IO; + +using DotNetNuke.ComponentModel; + +namespace DotNetNuke.Services.FileSystem.Internal +{ + public class FileWrapper : ComponentBase, IFile + { + public Stream Create(string path) + { + return File.Create(path); + } + + public void Delete(string path) + { + File.Delete(path); + } + + public bool Exists(string path) + { + return File.Exists(path); + } + + public FileAttributes GetAttributes(string path) + { + return File.GetAttributes(path); + } + + public DateTime GetLastWriteTime(string path) + { + return File.GetLastWriteTime(path); + } + + public void Move(string sourceFileName, string destFileName) + { + File.Move(sourceFileName, destFileName); + } + + public Stream OpenRead(string path) + { + return File.OpenRead(path); + } + + public byte[] ReadAllBytes(string path) + { + return File.ReadAllBytes(path); + } + + public void SetAttributes(string path, FileAttributes fileAttributes) + { + File.SetAttributes(path, fileAttributes); + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/FolderPermissionControllerWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/FolderPermissionControllerWrapper.cs new file mode 100644 index 00000000000..deae89b6577 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/FolderPermissionControllerWrapper.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using DotNetNuke.ComponentModel; +using DotNetNuke.Security.Permissions; + +namespace DotNetNuke.Services.FileSystem +{ + internal class FolderPermissionControllerWrapper : ComponentBase, IFolderPermissionController + { + internal FolderPermissionControllerWrapper() + { + } + + public bool CanAddFolder(IFolderInfo folder) + { + return FolderPermissionController.CanAddFolder((FolderInfo)folder); + } + + public bool CanAdminFolder(IFolderInfo folder) + { + return FolderPermissionController.CanAdminFolder((FolderInfo)folder); + } + + public bool CanViewFolder(IFolderInfo folder) + { + return FolderPermissionController.CanViewFolder((FolderInfo)folder); + } + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/ICBO.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/ICBO.cs new file mode 100644 index 00000000000..a4bda953d87 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/ICBO.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.FileSystem +{ + internal interface ICBO + { + List FillCollection(IDataReader dr) where T : new(); + T FillObject(IDataReader dr) where T : new(); + SortedList FillSortedList(string keyField, IDataReader dr); + T GetCachedObject(CacheItemArgs cacheItemArgs, CacheItemExpiredCallback cacheItemExpired); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IDirectory.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IDirectory.cs new file mode 100644 index 00000000000..4ee58573078 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IDirectory.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.FileSystem.Internal +{ + public interface IDirectory + { + void Delete(string path, bool recursive); + bool Exists(string path); + string[] GetDirectories(string path); + string[] GetFiles(string path); + void Move(string sourceDirName, string destDirName); + void CreateDirectory(string path); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IFile.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IFile.cs new file mode 100644 index 00000000000..509ff09dea7 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IFile.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.IO; + +namespace DotNetNuke.Services.FileSystem.Internal +{ + public interface IFile + { + Stream Create(string path); + void Delete(string path); + bool Exists(string path); + FileAttributes GetAttributes(string path); + DateTime GetLastWriteTime(string path); + void Move(string sourceFileName, string destFileName); + Stream OpenRead(string path); + byte[] ReadAllBytes(string path); + void SetAttributes(string path, FileAttributes fileAttributes); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IFolderPermissionController.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IFolderPermissionController.cs new file mode 100644 index 00000000000..c945e1911c9 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IFolderPermissionController.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.FileSystem +{ + internal interface IFolderPermissionController + { + bool CanAddFolder(IFolderInfo folder); + bool CanAdminFolder(IFolderInfo folder); + bool CanViewFolder(IFolderInfo folder); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IIconController.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IIconController.cs new file mode 100644 index 00000000000..a7041e65b16 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IIconController.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.FileSystem +{ + internal interface IIconController + { + string IconURL(string key); + + string IconURL(string key, string size); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IUserController.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IUserController.cs new file mode 100644 index 00000000000..7ff78bd5c93 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IUserController.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Services.FileSystem +{ + internal interface IUserController + { + UserInfo GetCurrentUserInfo(); + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/IconControllerWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/IconControllerWrapper.cs new file mode 100644 index 00000000000..ba1e98e2855 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/IconControllerWrapper.cs @@ -0,0 +1,44 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Icons; + +namespace DotNetNuke.Services.FileSystem +{ + internal class IconControllerWrapper : ComponentBase, IIconController + { + #region Implementation of IIconController + + public string IconURL(string key) + { + return IconController.IconURL(key); + } + + public string IconURL(string key, string size) + { + return IconController.IconURL(key, size); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/PortalControllerWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/PortalControllerWrapper.cs new file mode 100644 index 00000000000..67b0d668264 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/PortalControllerWrapper.cs @@ -0,0 +1,27 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.FileSystem +{ + internal class PortalControllerWrapper : ComponentBase {} +} diff --git a/DNN Platform/Library/Services/FileSystem/Wrappers/UserControllerWrapper.cs b/DNN Platform/Library/Services/FileSystem/Wrappers/UserControllerWrapper.cs new file mode 100644 index 00000000000..870ec9f4e37 --- /dev/null +++ b/DNN Platform/Library/Services/FileSystem/Wrappers/UserControllerWrapper.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Services.FileSystem +{ + internal class UserControllerWrapper : ComponentBase, IUserController + { + internal UserControllerWrapper() + { + } + + public UserInfo GetCurrentUserInfo() + { + return UserController.GetCurrentUserInfo(); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/CoreVersionDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/CoreVersionDependency.cs new file mode 100644 index 00000000000..24bb4641871 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/CoreVersionDependency.cs @@ -0,0 +1,72 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Application; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The CoreVersionDependency determines whether the CoreVersion is correct + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public class CoreVersionDependency : DependencyBase + { + private Version minVersion; + + public override string ErrorMessage + { + get + { + return string.Format(Util.INSTALL_Compatibility,minVersion); + } + } + + public override bool IsValid + { + get + { + bool _IsValid = true; + if (DotNetNukeContext.Current.Application.Version < minVersion) + { + _IsValid = false; + } + return _IsValid; + } + } + + public override void ReadManifest(XPathNavigator dependencyNav) + { + minVersion = new Version(dependencyNav.Value); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/DependencyBase.cs b/DNN Platform/Library/Services/Installer/Dependencies/DependencyBase.cs new file mode 100644 index 00000000000..7dcf50b2fe4 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/DependencyBase.cs @@ -0,0 +1,67 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The DependencyBase is a base class for Installer Dependencies + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public abstract class DependencyBase : IDependency + { + #region IDependency Members + + public virtual string ErrorMessage + { + get + { + return Null.NullString; + } + } + + public virtual bool IsValid + { + get + { + return true; + } + } + + public virtual void ReadManifest(XPathNavigator dependencyNav) + { + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/DependencyFactory.cs b/DNN Platform/Library/Services/Installer/Dependencies/DependencyFactory.cs new file mode 100644 index 00000000000..fb4d0a8cd02 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/DependencyFactory.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +using DotNetNuke.Common.Lists; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The DependencyFactory is a factory class that is used to instantiate the + /// appropriate Dependency + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public class DependencyFactory + { + #region "Public Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The GetDependency method instantiates (and returns) the relevant Dependency + /// + /// The manifest (XPathNavigator) for the dependency + /// + /// [cnurse] 09/02/2007 created + /// [bdukes] 03/04/2009 added case-insensitivity to type attribute, added InvalidDependency for dependencies that can't be created + /// + /// ----------------------------------------------------------------------------- + public static IDependency GetDependency(XPathNavigator dependencyNav) + { + IDependency dependency = null; + string dependencyType = Util.ReadAttribute(dependencyNav, "type"); + switch (dependencyType.ToLowerInvariant()) + { + case "coreversion": + dependency = new CoreVersionDependency(); + break; + case "package": + dependency = new PackageDependency(); + break; + case "permission": + dependency = new PermissionsDependency(); + break; + case "type": + dependency = new TypeDependency(); + break; + default: + //Dependency type is defined in the List + var listController = new ListController(); + ListEntryInfo entry = listController.GetListEntryInfo("Dependency", dependencyType); + if (entry != null && !string.IsNullOrEmpty(entry.Text)) + { + //The class for the Installer is specified in the Text property + dependency = (DependencyBase) Reflection.CreateObject(entry.Text, "Dependency_" + entry.Value); + } + break; + } + if (dependency == null) + { + //Could not create dependency, show generic error message + dependency = new InvalidDependency(Util.INSTALL_Dependencies); + } + //Read Manifest + dependency.ReadManifest(dependencyNav); + + return dependency; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/IDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/IDependency.cs new file mode 100644 index 00000000000..ec7acd77ab2 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/IDependency.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The IDependency Interface defines the contract for a Package Dependency + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public interface IDependency + { + string ErrorMessage { get; } + bool IsValid { get; } + + void ReadManifest(XPathNavigator dependencyNav); + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/InvalidDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/InvalidDependency.cs new file mode 100644 index 00000000000..a3c26d6265c --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/InvalidDependency.cs @@ -0,0 +1,63 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The InvalidDependency signifies a dependency that is always invalid, + /// taking the place of dependencies that could not be created + /// + /// + /// + /// + /// [bdukes] 03/03/2009 created + /// + /// ----------------------------------------------------------------------------- + public class InvalidDependency : DependencyBase + { + private readonly string _ErrorMessage; + + /// + /// Initializes a new instance of the class. + /// + /// The error message to display. + public InvalidDependency(string ErrorMessage) + { + _ErrorMessage = ErrorMessage; + } + + public override string ErrorMessage + { + get + { + return _ErrorMessage; + } + } + + public override bool IsValid + { + get + { + return false; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/PackageDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/PackageDependency.cs new file mode 100644 index 00000000000..ead634392ec --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/PackageDependency.cs @@ -0,0 +1,74 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageDependency determines whether the dependent package is installed + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public class PackageDependency : DependencyBase + { + private string PackageName; + + public override string ErrorMessage + { + get + { + return Util.INSTALL_Package + " - " + PackageName; + } + } + + public override bool IsValid + { + get + { + bool _IsValid = true; + + //Get Package from DataStore + PackageInfo package = PackageController.GetPackageByName(PackageName); + if (package == null) + { + _IsValid = false; + } + return _IsValid; + } + } + + public override void ReadManifest(XPathNavigator dependencyNav) + { + PackageName = dependencyNav.Value; + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/PermissionsDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/PermissionsDependency.cs new file mode 100644 index 00000000000..8e4fa064a21 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/PermissionsDependency.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The PermissionsDependency determines whether the DotNetNuke site has the + /// corretc permissions + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public class PermissionsDependency : DependencyBase + { + private string Permission = Null.NullString; + private string Permissions; + + public override string ErrorMessage + { + get + { + return Util.INSTALL_Permissions + " - " + Permission; + } + } + + public override bool IsValid + { + get + { + return SecurityPolicy.HasPermissions(Permissions, ref Permission); + } + } + + public override void ReadManifest(XPathNavigator dependencyNav) + { + Permissions = dependencyNav.Value; + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Dependencies/TypeDependency.cs b/DNN Platform/Library/Services/Installer/Dependencies/TypeDependency.cs new file mode 100644 index 00000000000..ccb02355037 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Dependencies/TypeDependency.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Installer.Dependencies +{ + /// ----------------------------------------------------------------------------- + /// + /// The TypeDependency determines whether the dependent type is installed + /// + /// + /// + /// + /// [cnurse] 09/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public class TypeDependency : DependencyBase + { + private readonly string _dependentType = String.Empty; + private string _dependentTypes; + + public override string ErrorMessage + { + get + { + return Util.INSTALL_Namespace + " - " + _dependentType; + } + } + + public override bool IsValid + { + get + { + bool isValid = true; + if (!String.IsNullOrEmpty(_dependentTypes)) + { + foreach (string dependentType in (_dependentTypes + ";").Split(';')) + { + if (!String.IsNullOrEmpty(dependentType.Trim())) + { + if (Reflection.CreateType(dependentType, true) == null) + { + isValid = false; + break; + } + } + } + } + return isValid; + } + } + + public override void ReadManifest(XPathNavigator dependencyNav) + { + _dependentTypes = dependencyNav.Value; + } + } +} diff --git a/DNN Platform/Library/Services/Installer/InstallFile.cs b/DNN Platform/Library/Services/Installer/InstallFile.cs new file mode 100644 index 00000000000..0c7dc9d336d --- /dev/null +++ b/DNN Platform/Library/Services/Installer/InstallFile.cs @@ -0,0 +1,545 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.ComponentModel; +using System.IO; +using System.Text.RegularExpressions; + +using ICSharpCode.SharpZipLib.Zip; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + /// ----------------------------------------------------------------------------- + /// + /// The InstallFile class represents a single file in an Installer Package + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class InstallFile + { + #region "Private Members" + + private readonly InstallerInfo _InstallerInfo; + private readonly string _SourceFileName; + private string _Action; + private TextEncoding _Encoding = TextEncoding.UTF8; + private string _Name; + private string _Path; + private InstallFileType _Type; + private Version _Version; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallFile instance from a ZipInputStream and a ZipEntry + /// + /// The ZipInputStream is read into a byte array (Buffer), and the ZipEntry is used to + /// set up the properties of the InstallFile class. + /// The ZipInputStream + /// The ZipEntry + /// An INstallerInfo instance + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile(ZipInputStream zip, ZipEntry entry, InstallerInfo info) + { + _InstallerInfo = info; + ReadZip(zip, entry); + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallFile instance + /// + /// The fileName of the File + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile(string fileName) + { + ParseFileName(fileName); + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallFile instance + /// + /// The fileName of the File + /// An INstallerInfo instance + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile(string fileName, InstallerInfo info) + { + ParseFileName(fileName); + _InstallerInfo = info; + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallFile instance + /// + /// The fileName of the File + /// Source file name. + /// An INstallerInfo instance + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile(string fileName, string sourceFileName, InstallerInfo info) + { + ParseFileName(fileName); + _SourceFileName = sourceFileName; + _InstallerInfo = info; + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallFile instance + /// + /// The file name of the File + /// The file path of the file + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile(string fileName, string filePath) + { + _Name = fileName; + _Path = filePath; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Action for this file + /// + /// A string + /// + /// [cnurse] 09/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public string Action + { + get + { + return _Action; + } + set + { + _Action = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the location of the backup file + /// + /// A string + /// + /// [cnurse] 08/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public string BackupFileName + { + get + { + return System.IO.Path.Combine(BackupPath, Name + ".config"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the location of the backup folder + /// + /// A string + /// + /// [cnurse] 08/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public virtual string BackupPath + { + get + { + return System.IO.Path.Combine(InstallerInfo.TempInstallFolder, System.IO.Path.Combine("Backup", Path)); + } + } + + public TextEncoding Encoding + { + get + { + return _Encoding; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the File Extension of the file + /// + /// A string + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Extension + { + get + { + string ext = System.IO.Path.GetExtension(_Name); + if (String.IsNullOrEmpty(ext)) + { + return ""; + } + else + { + return ext.Substring(1); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Full Name of the file + /// + /// A string + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string FullName + { + get + { + return System.IO.Path.Combine(_Path, _Name); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated InstallerInfo + /// + /// An InstallerInfo object + /// + /// [cnurse] 08/02/2007 created + /// + /// ----------------------------------------------------------------------------- + [Browsable(false)] + public InstallerInfo InstallerInfo + { + get + { + return _InstallerInfo; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name of the file + /// + /// A string + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Name + { + get + { + return _Name; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path of the file + /// + /// A string + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Path + { + get + { + return _Path; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the source file name + /// + /// A string + /// + /// [cnurse] 01/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public string SourceFileName + { + get + { + return _SourceFileName; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the location of the temporary file + /// + /// A string + /// + /// [cnurse] 08/02/2007 created + /// + /// ----------------------------------------------------------------------------- + public string TempFileName + { + get + { + string fileName = SourceFileName; + if (string.IsNullOrEmpty(fileName)) + { + fileName = FullName; + } + return System.IO.Path.Combine(InstallerInfo.TempInstallFolder, fileName); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Type of the file + /// + /// An InstallFileType Enumeration + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFileType Type + { + get + { + return _Type; + } + set + { + _Type = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Version of the file + /// + /// A System.Version + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public Version Version + { + get + { + return _Version; + } + } + + #endregion + + #region "Private Methods" + + private TextEncoding GetTextEncodingType(byte[] Buffer) + { + //UTF7 = No byte higher than 127 + //UTF8 = first three bytes EF BB BF + //UTF16BigEndian = first two bytes FE FF + //UTF16LittleEndian = first two bytes FF FE + + //Lets do the easy ones first + if (Buffer[0] == 255 && Buffer[1] == 254) + { + return TextEncoding.UTF16LittleEndian; + } + if (Buffer[0] == 254 && Buffer[1] == 255) + { + return TextEncoding.UTF16BigEndian; + } + if (Buffer[0] == 239 && Buffer[1] == 187 && Buffer[2] == 191) + { + return TextEncoding.UTF8; + } + + //This does a simple test to verify that there are no bytes with a value larger than 127 + //which would be invalid in UTF-7 encoding + int i; + for (i = 0; i <= 100; i++) + { + if (Buffer[i] > 127) + { + return TextEncoding.Unknown; + } + } + return TextEncoding.UTF7; + } + + /// ----------------------------------------------------------------------------- + /// + /// The ParseFileName parses the ZipEntry metadata + /// + /// A String representing the file name + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ParseFileName(string fileName) + { + int i = fileName.Replace("\\", "/").LastIndexOf("/"); + if (i < 0) + { + _Name = fileName.Substring(0, fileName.Length); + _Path = ""; + } + else + { + _Name = fileName.Substring(i + 1, fileName.Length - (i + 1)); + _Path = fileName.Substring(0, i); + } + if (string.IsNullOrEmpty(_Path) && fileName.StartsWith("[app_code]")) + { + _Name = fileName.Substring(10, fileName.Length - 10); + _Path = fileName.Substring(0, 10); + } + if (_Name.ToLower() == "manifest.xml") + { + _Type = InstallFileType.Manifest; + } + else + { + switch (Extension.ToLower()) + { + case "ascx": + _Type = InstallFileType.Ascx; + break; + case "dll": + _Type = InstallFileType.Assembly; + break; + case "dnn": + case "dnn5": + case "dnn6": + _Type = InstallFileType.Manifest; + break; + case "resx": + _Type = InstallFileType.Language; + break; + case "resources": + case "zip": + _Type = InstallFileType.Resources; + break; + default: + if (Extension.ToLower().EndsWith("dataprovider") || Extension.ToLower() == "sql") + { + _Type = InstallFileType.Script; + } + else if (_Path.StartsWith("[app_code]")) + { + _Type = InstallFileType.AppCode; + } + else + { + if (Regex.IsMatch(_Name, Util.REGEX_Version + ".txt")) + { + _Type = InstallFileType.CleanUp; + } + else + { + _Type = InstallFileType.Other; + } + } + break; + } + } + + //remove [app_code] token + _Path = _Path.Replace("[app_code]", ""); + + //remove starting "\" + if (_Path.StartsWith("\\")) + { + _Path = _Path.Substring(1); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadZip method reads the zip stream and parses the ZipEntry metadata + /// + /// A ZipStream containing the file content + /// A ZipEntry containing the file metadata + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ReadZip(ZipInputStream unzip, ZipEntry entry) + { + ParseFileName(entry.Name); + Util.WriteStream(unzip, TempFileName); + File.SetLastWriteTime(TempFileName, entry.DateTime); + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The SetVersion method sets the version of the file + /// + /// The version of the file + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void SetVersion(Version version) + { + _Version = version; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/InstallFileType.cs b/DNN Platform/Library/Services/Installer/InstallFileType.cs new file mode 100644 index 00000000000..abf528246b6 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/InstallFileType.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + [TypeConverter(typeof (EnumConverter))] + public enum InstallFileType + { + AppCode, + Ascx, + Assembly, + CleanUp, + Language, + Manifest, + Other, + Resources, + Script + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/InstallMode.cs b/DNN Platform/Library/Services/Installer/InstallMode.cs new file mode 100644 index 00000000000..71be2078f4b --- /dev/null +++ b/DNN Platform/Library/Services/Installer/InstallMode.cs @@ -0,0 +1,36 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + [TypeConverter(typeof (EnumConverter))] + public enum InstallMode + { + Install, + ManifestOnly, + UnInstall + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Installer.cs b/DNN Platform/Library/Services/Installer/Installer.cs new file mode 100644 index 00000000000..49ec666fe46 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installer.cs @@ -0,0 +1,539 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Installer.Installers; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Installer.Writers; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Web.Client.ClientResourceManagement; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + using Entities.Controllers; + + /// ----------------------------------------------------------------------------- + /// + /// The Installer class provides a single entrypoint for Package Installation + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class Installer + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Installer)); + #region Private Members + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new Installer instance from a string representing + /// the physical path to the temporary install folder and a string representing + /// the physical path to the root of the site + /// + /// The physical path to the zip file containg the package + /// The manifest filename + /// The physical path to the root of the site + /// Flag that determines whether the manifest will be loaded + /// ----------------------------------------------------------------------------- + public Installer(string tempFolder, string manifest, string physicalSitePath, bool loadManifest) + { + Packages = new SortedList(); + //Called from Interactive installer - default IgnoreWhiteList to false + InstallerInfo = new InstallerInfo(tempFolder, manifest, physicalSitePath) { IgnoreWhiteList = false }; + + if (loadManifest) + { + ReadManifest(true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new Installer instance from a Stream and a + /// string representing the physical path to the root of the site + /// + /// The Stream to use to create this InstallerInfo instance + /// The physical path to the root of the site + /// Flag that determines whether the manifest will be loaded + /// ----------------------------------------------------------------------------- + public Installer(Stream inputStream, string physicalSitePath, bool loadManifest) : this(inputStream, physicalSitePath, loadManifest, true) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new Installer instance from a Stream and a + /// string representing the physical path to the root of the site + /// + /// The Stream to use to create this InstallerInfo instance + /// The physical path to the root of the site + /// Flag that determines whether the manifest will be loaded + /// Whether delete the temp folder. + /// ----------------------------------------------------------------------------- + public Installer(Stream inputStream, string physicalSitePath, bool loadManifest, bool deleteTemp) + { + Packages = new SortedList(); + //Called from Batch installer - default IgnoreWhiteList to true + InstallerInfo = new InstallerInfo(inputStream, physicalSitePath) { IgnoreWhiteList = true }; + + if (loadManifest) + { + ReadManifest(deleteTemp); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new Installer instance from a PackageInfo object + /// + /// The PackageInfo instance + /// The physical path to the root of the site + /// ----------------------------------------------------------------------------- + public Installer(PackageInfo package, string physicalSitePath) + { + Packages = new SortedList(); + InstallerInfo = new InstallerInfo(package, physicalSitePath); + + Packages.Add(Packages.Count, new PackageInstaller(package)); + } + + public Installer(string manifest, string physicalSitePath, bool loadManifest) + { + Packages = new SortedList(); + InstallerInfo = new InstallerInfo(physicalSitePath, InstallMode.ManifestOnly); + if (loadManifest) + { + ReadManifest(new FileStream(manifest, FileMode.Open, FileAccess.Read)); + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated InstallerInfo object + /// + /// An InstallerInfo + /// ----------------------------------------------------------------------------- + public InstallerInfo InstallerInfo { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the associated InstallerInfo is valid + /// + /// True - if valid, False if not + /// ----------------------------------------------------------------------------- + public bool IsValid + { + get + { + return InstallerInfo.IsValid; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SortedList of Packages that are included in the Package Zip + /// + /// A SortedList(Of Integer, PackageInstaller) + /// ----------------------------------------------------------------------------- + public SortedList Packages { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets + /// + /// A Dictionary(Of String, PackageInstaller) + /// ----------------------------------------------------------------------------- + public string TempInstallFolder + { + get + { + return InstallerInfo.TempInstallFolder; + } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// The InstallPackages method installs the packages + /// + /// ----------------------------------------------------------------------------- + private void InstallPackages(ref bool clearClientCache) + { + //Iterate through all the Packages + for (int index = 0; index <= Packages.Count - 1; index++) + { + PackageInstaller installer = Packages.Values[index]; + //Check if package is valid + if (installer.Package.IsValid) + { + if (installer.Package.InstallerInfo.Installed || installer.Package.InstallerInfo.RepairInstall) + { + clearClientCache = true; + } + + InstallerInfo.Log.AddInfo(Util.INSTALL_Start + " - " + installer.Package.Name); + installer.Install(); + if (InstallerInfo.Log.Valid) + { + InstallerInfo.Log.AddInfo(Util.INSTALL_Success + " - " + installer.Package.Name); + } + else + { + InstallerInfo.Log.AddInfo(Util.INSTALL_Failed + " - " + installer.Package.Name); + } + } + else + { + InstallerInfo.Log.AddFailure(Util.INSTALL_Aborted + " - " + installer.Package.Name); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Logs the Install event to the Event Log + /// + /// The name of the package + /// Event Type. + /// ----------------------------------------------------------------------------- + private void LogInstallEvent(string package, string eventType) + { + try + { + var objEventLogInfo = new LogInfo(); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + + if (InstallerInfo.ManifestFile != null) + { + objEventLogInfo.LogProperties.Add(new LogDetailInfo(eventType + " " + package + ":", InstallerInfo.ManifestFile.Name.Replace(".dnn", ""))); + } + + foreach (LogEntry objLogEntry in InstallerInfo.Log.Logs) + { + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Info:", objLogEntry.Description)); + } + var objEventLog = new EventLogController(); + objEventLog.AddLog(objEventLogInfo); + } + catch (Exception exc) + { + Logger.Error(exc); + + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ProcessPackages method processes the packages nodes in the manifest + /// + /// ----------------------------------------------------------------------------- + private void ProcessPackages(XPathNavigator rootNav) + { + //Parse the package nodes + foreach (XPathNavigator nav in rootNav.Select("packages/package")) + { + int order = Packages.Count; + string name = Util.ReadAttribute(nav, "name"); + string installOrder = Util.ReadAttribute(nav, "installOrder"); + if (!string.IsNullOrEmpty(installOrder)) + { + order = int.Parse(installOrder); + } + Packages.Add(order, new PackageInstaller(nav.OuterXml, InstallerInfo)); + } + } + + private void ReadManifest(Stream stream) + { + var doc = new XPathDocument(stream); + + //Read the root node to determine what version the manifest is + XPathNavigator rootNav = doc.CreateNavigator(); + rootNav.MoveToFirstChild(); + string packageType = Null.NullString; + + if (rootNav.Name == "dotnetnuke") + { + packageType = Util.ReadAttribute(rootNav, "type"); + } + else if (rootNav.Name.ToLower() == "languagepack") + { + packageType = "LanguagePack"; + } + else + { + InstallerInfo.Log.AddFailure(Util.PACKAGE_UnRecognizable); + } + switch (packageType.ToLower()) + { + case "package": + InstallerInfo.IsLegacyMode = false; + //Parse the package nodes + ProcessPackages(rootNav); + break; + case "module": + case "languagepack": + case "skinobject": + InstallerInfo.IsLegacyMode = true; + ProcessPackages(ConvertLegacyNavigator(rootNav, InstallerInfo)); + break; + } + } + + private void UnInstallPackages(bool deleteFiles) + { + for (int index = 0; index <= Packages.Count - 1; index++) + { + PackageInstaller installer = Packages.Values[index]; + InstallerInfo.Log.AddInfo(Util.UNINSTALL_Start + " - " + installer.Package.Name); + installer.DeleteFiles = deleteFiles; + installer.UnInstall(); + if (InstallerInfo.Log.HasWarnings) + { + InstallerInfo.Log.AddWarning(Util.UNINSTALL_Warnings + " - " + installer.Package.Name); + } + else + { + InstallerInfo.Log.AddInfo(Util.UNINSTALL_Success + " - " + installer.Package.Name); + } + } + } + + public static XPathNavigator ConvertLegacyNavigator(XPathNavigator rootNav, InstallerInfo info) + { + XPathNavigator nav = null; + + var packageType = Null.NullString; + if (rootNav.Name == "dotnetnuke") + { + packageType = Util.ReadAttribute(rootNav, "type"); + } + else if (rootNav.Name.ToLower() == "languagepack") + { + packageType = "LanguagePack"; + } + + XPathDocument legacyDoc; + string legacyManifest; + switch (packageType.ToLower()) + { + case "module": + var sb = new StringBuilder(); + var writer = XmlWriter.Create(sb, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)); + + //Write manifest start element + PackageWriterBase.WriteManifestStartElement(writer); + + //Legacy Module - Process each folder + foreach (XPathNavigator folderNav in rootNav.Select("folders/folder")) + { + var modulewriter = new ModulePackageWriter(folderNav, info); + modulewriter.WriteManifest(writer, true); + } + + //Write manifest end element + PackageWriterBase.WriteManifestEndElement(writer); + + //Close XmlWriter + writer.Close(); + + //Load manifest into XPathDocument for processing + legacyDoc = new XPathDocument(new StringReader(sb.ToString())); + + //Parse the package nodes + nav = legacyDoc.CreateNavigator().SelectSingleNode("dotnetnuke"); + break; + case "languagepack": + //Legacy Language Pack + var languageWriter = new LanguagePackWriter(rootNav, info); + info.LegacyError = languageWriter.LegacyError; + if (string.IsNullOrEmpty(info.LegacyError)) + { + legacyManifest = languageWriter.WriteManifest(false); + legacyDoc = new XPathDocument(new StringReader(legacyManifest)); + + //Parse the package nodes + nav = legacyDoc.CreateNavigator().SelectSingleNode("dotnetnuke"); + } + break; + case "skinobject": + //Legacy Skin Object + var skinControlwriter = new SkinControlPackageWriter(rootNav, info); + legacyManifest = skinControlwriter.WriteManifest(false); + legacyDoc = new XPathDocument(new StringReader(legacyManifest)); + + //Parse the package nodes + nav = legacyDoc.CreateNavigator().SelectSingleNode("dotnetnuke"); + break; + } + + return nav; + } + + #endregion + + #region Public Methods + + public void DeleteTempFolder() + { + if (!string.IsNullOrEmpty(TempInstallFolder)) + { + Directory.Delete(TempInstallFolder, true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the feature. + /// + /// ----------------------------------------------------------------------------- + public bool Install() + { + InstallerInfo.Log.StartJob(Util.INSTALL_Start); + bool bStatus = true; + try + { + bool clearClientCache = false; + InstallPackages(ref clearClientCache); + if (clearClientCache) + { + //Update the version of the client resources - so the cache is cleared + HostController.Instance.IncrementCrmVersion(true); + } + } + catch (Exception ex) + { + + InstallerInfo.Log.AddFailure(ex); + bStatus = false; + } + finally + { + //Delete Temp Folder + if (!string.IsNullOrEmpty(TempInstallFolder)) + { + Globals.DeleteFolderRecursive(TempInstallFolder); + } + InstallerInfo.Log.AddInfo(Util.FOLDER_DeletedBackup); + } + if (InstallerInfo.Log.Valid) + { + InstallerInfo.Log.EndJob(Util.INSTALL_Success); + } + else + { + InstallerInfo.Log.EndJob(Util.INSTALL_Failed); + bStatus = false; + } + + //log installation event + LogInstallEvent("Package", "Install"); + + //Clear Host Cache + DataCache.ClearHostCache(true); + + return bStatus; + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file and parses it into packages. + /// + /// ----------------------------------------------------------------------------- + public void ReadManifest(bool deleteTemp) + { + InstallerInfo.Log.StartJob(Util.DNN_Reading); + if (InstallerInfo.ManifestFile != null) + { + ReadManifest(new FileStream(InstallerInfo.ManifestFile.TempFileName, FileMode.Open, FileAccess.Read)); + } + if (InstallerInfo.Log.Valid) + { + InstallerInfo.Log.EndJob(Util.DNN_Success); + } + else if (deleteTemp) + { + //Delete Temp Folder + DeleteTempFolder(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the feature + /// + /// A flag that indicates whether the files should be + /// deleted + /// ----------------------------------------------------------------------------- + public bool UnInstall(bool deleteFiles) + { + InstallerInfo.Log.StartJob(Util.UNINSTALL_Start); + try + { + UnInstallPackages(deleteFiles); + } + catch (Exception ex) + { + + InstallerInfo.Log.AddFailure(ex); + return false; + } + if (InstallerInfo.Log.HasWarnings) + { + InstallerInfo.Log.EndJob(Util.UNINSTALL_Warnings); + } + else + { + InstallerInfo.Log.EndJob(Util.UNINSTALL_Success); + } + //log installation event + LogInstallEvent("Package", "UnInstall"); + return true; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/InstallerInfo.cs b/DNN Platform/Library/Services/Installer/InstallerInfo.cs new file mode 100644 index 00000000000..acd4c8df4b2 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/InstallerInfo.cs @@ -0,0 +1,428 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; + +using ICSharpCode.SharpZipLib.Zip; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + /// ----------------------------------------------------------------------------- + /// + /// The InstallerInfo class holds all the information associated with a + /// Installation. + /// + /// + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class InstallerInfo + { + #region Private Members + + private readonly string _PhysicalSitePath = Null.NullString; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallerInfo instance + /// + /// ----------------------------------------------------------------------------- + public InstallerInfo() + { + Initialize(); + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallerInfo instance from a + /// string representing the physical path to the root of the site + /// + /// The physical path to the root of the site + /// Install Mode. + /// ----------------------------------------------------------------------------- + public InstallerInfo(string sitePath, InstallMode mode) + { + Initialize(); + TempInstallFolder = Globals.InstallMapPath + "Temp\\" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); + _PhysicalSitePath = sitePath; + InstallMode = mode; + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallerInfo instance from a Stream and a + /// string representing the physical path to the root of the site + /// + /// The Stream to use to create this InstallerInfo instance + /// The physical path to the root of the site + /// ----------------------------------------------------------------------------- + public InstallerInfo(Stream inputStream, string sitePath) + { + Initialize(); + TempInstallFolder = Globals.InstallMapPath + "Temp\\" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); + _PhysicalSitePath = sitePath; + + //Read the Zip file into its component entries + ReadZipStream(inputStream, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallerInfo instance from a string representing + /// the physical path to the temporary install folder and a string representing + /// the physical path to the root of the site + /// + /// The physical path to the zip file containg the package + /// The manifest filename + /// The physical path to the root of the site + /// ----------------------------------------------------------------------------- + public InstallerInfo(string tempFolder, string manifest, string sitePath) + { + Initialize(); + TempInstallFolder = tempFolder; + _PhysicalSitePath = sitePath; + if (!string.IsNullOrEmpty(manifest)) + { + ManifestFile = new InstallFile(manifest, this); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallerInfo instance from a PackageInfo object + /// + /// The PackageInfo instance + /// The physical path to the root of the site + /// ----------------------------------------------------------------------------- + public InstallerInfo(PackageInfo package, string sitePath) + { + Initialize(); + _PhysicalSitePath = sitePath; + TempInstallFolder = Globals.InstallMapPath + "Temp\\" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); + InstallMode = InstallMode.UnInstall; + ManifestFile = new InstallFile(Path.Combine(TempInstallFolder, package.Name + ".dnn")); + package.AttachInstallerInfo(this); + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// ----------------------------------------------------------------------------- + public string AllowableFiles { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Files that are included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// ----------------------------------------------------------------------------- + public Dictionary Files { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the package contains Valid Files + /// + /// A Boolean + /// ----------------------------------------------------------------------------- + public bool HasValidFiles + { + get + { + bool _HasValidFiles = true; + if (Files.Values.Any(file => !Util.IsFileValid(file, AllowableFiles))) + { + _HasValidFiles = Null.NullBoolean; + } + return _HasValidFiles; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the File Extension WhiteList is ignored + /// + /// A Boolean value + /// ----------------------------------------------------------------------------- + public bool IgnoreWhiteList { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Package is installed + /// + /// A Boolean value + /// ----------------------------------------------------------------------------- + public bool Installed { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the InstallMode + /// + /// A InstallMode value + /// ----------------------------------------------------------------------------- + public InstallMode InstallMode { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Invalid File Extensions + /// + /// A String + /// + /// [cnurse] 01/12/2009 created + /// + /// ----------------------------------------------------------------------------- + public string InvalidFileExtensions + { + get + { + string _InvalidFileExtensions = Files.Values.Where(file => !Util.IsFileValid(file, AllowableFiles)) + .Aggregate(Null.NullString, (current, file) => current + (", " + file.Extension)); + if (!string.IsNullOrEmpty(_InvalidFileExtensions)) + { + _InvalidFileExtensions = _InvalidFileExtensions.Substring(2); + } + return _InvalidFileExtensions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Installer is in legacy mode + /// + /// ----------------------------------------------------------------------------- + public bool IsLegacyMode { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the InstallerInfo instance is Valid + /// + /// A Boolean value + /// ----------------------------------------------------------------------------- + public bool IsValid + { + get + { + return Log.Valid; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Logger + /// + /// A Logger + /// ----------------------------------------------------------------------------- + public string LegacyError { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Logger + /// + /// A Logger + /// ----------------------------------------------------------------------------- + public Logger Log { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Manifest File for the Package + /// + /// An InstallFile + /// ----------------------------------------------------------------------------- + public InstallFile ManifestFile { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Id of the package after installation (-1 if fail) + /// + /// An Integer + /// ----------------------------------------------------------------------------- + public int PackageID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Physical Path to the root of the Site (eg D:\Websites\DotNetNuke") + /// + /// A String + /// ----------------------------------------------------------------------------- + public string PhysicalSitePath + { + get + { + return _PhysicalSitePath; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Id of the current portal (-1 if Host) + /// + /// An Integer + /// ----------------------------------------------------------------------------- + public int PortalID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Package Install is being repaird + /// + /// A Boolean value + /// ----------------------------------------------------------------------------- + public bool RepairInstall { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the security Access Level of the user that is calling the INstaller + /// + /// A SecurityAccessLevel enumeration + /// ----------------------------------------------------------------------------- + public SecurityAccessLevel SecurityAccessLevel { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Temporary Install Folder used to unzip the archive (and to place the + /// backups of existing files) during InstallMode + /// + /// A String + /// ----------------------------------------------------------------------------- + public string TempInstallFolder { get; private set; } + + #endregion + + #region Private Methods + + private void Initialize() + { + TempInstallFolder = Null.NullString; + SecurityAccessLevel = SecurityAccessLevel.Host; + RepairInstall = Null.NullBoolean; + PortalID = Null.NullInteger; + PackageID = Null.NullInteger; + Log = new Logger(); + IsLegacyMode = Null.NullBoolean; + IgnoreWhiteList = Null.NullBoolean; + InstallMode = InstallMode.Install; + Installed = Null.NullBoolean; + Files = new Dictionary(); + } + + private void ReadZipStream(Stream inputStream, bool isEmbeddedZip) + { + Log.StartJob(Util.FILES_Reading); + var unzip = new ZipInputStream(inputStream); + ZipEntry entry = unzip.GetNextEntry(); + while (entry != null) + { + if (!entry.IsDirectory) + { + //Add file to list + var file = new InstallFile(unzip, entry, this); + if (file.Type == InstallFileType.Resources && (file.Name.ToLowerInvariant() == "containers.zip" || file.Name.ToLowerInvariant() == "skins.zip")) + { + //Temporarily save the TempInstallFolder + string tmpInstallFolder = TempInstallFolder; + + //Create Zip Stream from File + var zipStream = new FileStream(file.TempFileName, FileMode.Open, FileAccess.Read); + + //Set TempInstallFolder + TempInstallFolder = Path.Combine(TempInstallFolder, Path.GetFileNameWithoutExtension(file.Name)); + + //Extract files from zip + ReadZipStream(zipStream, true); + + //Restore TempInstallFolder + TempInstallFolder = tmpInstallFolder; + + //Delete zip file + var zipFile = new FileInfo(file.TempFileName); + zipFile.Delete(); + } + else + { + Files[file.FullName.ToLower()] = file; + if (file.Type == InstallFileType.Manifest && !isEmbeddedZip) + { + if (ManifestFile == null) + { + ManifestFile = file; + } + else + { + if (file.Extension == "dnn6" && (ManifestFile.Extension == "dnn" || ManifestFile.Extension == "dnn5")) + { + ManifestFile = file; + } + else if (file.Extension == "dnn5" && ManifestFile.Extension == "dnn") + { + ManifestFile = file; + } + else if (file.Extension == ManifestFile.Extension) + { + Log.AddFailure((Util.EXCEPTION_MultipleDnn + ManifestFile.Name + " and " + file.Name)); + } + } + } + } + Log.AddInfo(string.Format(Util.FILE_ReadSuccess, file.FullName)); + } + entry = unzip.GetNextEntry(); + } + if (ManifestFile == null) + { + Log.AddFailure(Util.EXCEPTION_MissingDnn); + } + if (Log.Valid) + { + Log.EndJob(Util.FILES_ReadingEnd); + } + else + { + Log.AddFailure(new Exception(Util.EXCEPTION_FileLoad)); + Log.EndJob(Util.FILES_ReadingEnd); + } + + //Close the Zip Input Stream as we have finished with it + inputStream.Close(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/AssemblyInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/AssemblyInstaller.cs new file mode 100644 index 00000000000..508a892bb06 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/AssemblyInstaller.cs @@ -0,0 +1,225 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The AssemblyInstaller installs Assembly Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class AssemblyInstaller : FileInstaller + { + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("assemblies") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "assemblies"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the default Path for the file - if not present in the manifest + /// + /// A String + /// + /// [cnurse] 08/10/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string DefaultPath + { + get + { + return "bin\\"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("assembly") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "assembly"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PhysicalBasePath for the assemblies + /// + /// A String + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string PhysicalBasePath + { + get + { + return PhysicalSitePath + "\\"; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "dll"; + } + } + + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteFile method deletes a single assembly. + /// + /// The InstallFile to delete + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void DeleteFile(InstallFile file) + { + //Attempt to unregister assembly this will return False if the assembly is used by another package and + //cannot be delete andtrue if it is not being used and can be deleted + if (DataProvider.Instance().UnRegisterAssembly(Package.PackageID, file.Name)) + { + Log.AddInfo(Util.ASSEMBLY_UnRegistered + " - " + file.FullName); + //Call base class version to deleteFile file from \bin + base.DeleteFile(file); + } + else + { + Log.AddInfo(Util.ASSEMBLY_InUse + " - " + file.FullName); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that determines what type of file this installer supports + /// + /// The type of file being processed + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override bool IsCorrectType(InstallFileType type) + { + return (type == InstallFileType.Assembly); + } + + /// ----------------------------------------------------------------------------- + /// + /// The InstallFile method installs a single assembly. + /// + /// The InstallFile to install + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override bool InstallFile(InstallFile file) + { + bool bSuccess = true; + if (file.Action == "UnRegister") + { + DeleteFile(file); + } + else + { + //Attempt to register assembly this will return False if the assembly exists and true if it does not or is older + int returnCode = DataProvider.Instance().RegisterAssembly(Package.PackageID, file.Name, file.Version.ToString(3)); + switch (returnCode) + { + case 0: + //Assembly Does Not Exist + Log.AddInfo(Util.ASSEMBLY_Added + " - " + file.FullName); + break; + case 1: + //Older version of Assembly Exists + Log.AddInfo(Util.ASSEMBLY_Updated + " - " + file.FullName); + break; + case 2: + case 3: + //Assembly already Registered + Log.AddInfo(Util.ASSEMBLY_Registered + " - " + file.FullName); + break; + } + + //If assembly not registered, is newer (or is the same version and we are in repair mode) + if (returnCode < 2 || (returnCode == 2 && file.InstallerInfo.RepairInstall)) + { + //Call base class version to copy file to \bin + bSuccess = base.InstallFile(file); + } + } + return bSuccess; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/AuthenticationInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/AuthenticationInstaller.cs new file mode 100644 index 00000000000..5e8300058dd --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/AuthenticationInstaller.cs @@ -0,0 +1,237 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Authentication; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationInstaller installs Authentication Service Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public class AuthenticationInstaller : ComponentInstallerBase + { + #region "Private Properties" + + private AuthenticationInfo AuthSystem; + private AuthenticationInfo TempAuthSystem; + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ashx, aspx, ascx, vb, cs, resx, css, js, resources, config, vbproj, csproj, sln, htm, html"; + } + } + + #endregion + + #region "Private Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteAuthentiation method deletes the Authentication System + /// from the data Store. + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + private void DeleteAuthentiation() + { + try + { + AuthenticationInfo authSystem = AuthenticationController.GetAuthenticationServiceByPackageID(Package.PackageID); + if (authSystem != null) + { + AuthenticationController.DeleteAuthentication(authSystem); + } + Log.AddInfo(string.Format(Util.AUTHENTICATION_UnRegistered, authSystem.AuthenticationType)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + + #region "Public Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Authentication systems this is not neccessary + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the authentication component + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + bool bAdd = Null.NullBoolean; + try + { + //Attempt to get the Authentication Service + TempAuthSystem = AuthenticationController.GetAuthenticationServiceByType(AuthSystem.AuthenticationType); + + if (TempAuthSystem == null) + { + //Enable by default + AuthSystem.IsEnabled = true; + bAdd = true; + } + else + { + AuthSystem.AuthenticationID = TempAuthSystem.AuthenticationID; + AuthSystem.IsEnabled = TempAuthSystem.IsEnabled; + } + AuthSystem.PackageID = Package.PackageID; + if (bAdd) + { + //Add new service + AuthenticationController.AddAuthentication(AuthSystem); + } + else + { + //Update service + AuthenticationController.UpdateAuthentication(AuthSystem); + } + Completed = true; + Log.AddInfo(string.Format(Util.AUTHENTICATION_Registered, AuthSystem.AuthenticationType)); + } + catch (Exception ex) + { + + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the Authentication compoent. + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + AuthSystem = new AuthenticationInfo(); + + //Get the type + AuthSystem.AuthenticationType = Util.ReadElement(manifestNav, "authenticationService/type", Log, Util.AUTHENTICATION_TypeMissing); + + //Get the SettingsSrc + AuthSystem.SettingsControlSrc = Util.ReadElement(manifestNav, "authenticationService/settingsControlSrc", Log, Util.AUTHENTICATION_SettingsSrcMissing); + + //Get the LoginSrc + AuthSystem.LoginControlSrc = Util.ReadElement(manifestNav, "authenticationService/loginControlSrc", Log, Util.AUTHENTICATION_LoginSrcMissing); + + //Get the LogoffSrc + AuthSystem.LogoffControlSrc = Util.ReadElement(manifestNav, "authenticationService/logoffControlSrc"); + + if (Log.Valid) + { + Log.AddInfo(Util.AUTHENTICATION_ReadSuccess); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp Auth System exists then we need to update the DataStore with this + if (TempAuthSystem == null) + { + //No Temp Auth System - Delete newly added system + DeleteAuthentiation(); + } + else + { + //Temp Auth System - Rollback to Temp + AuthenticationController.UpdateAuthentication(TempAuthSystem); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the authentication component + /// + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteAuthentiation(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/CleanupInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/CleanupInstaller.cs new file mode 100644 index 00000000000..46b4134e725 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/CleanupInstaller.cs @@ -0,0 +1,250 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The CleanupInstaller cleans up (removes) files from previous versions + /// + /// + /// + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public class CleanupInstaller : FileInstaller + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (CleanupInstaller)); + #region "Private Members" + + private string _FileName; + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "*"; + } + } + + #endregion + + #region "Private Methods" + + private bool ProcessCleanupFile() + { + Log.AddInfo(string.Format(Util.CLEANUP_Processing, Version.ToString(3))); + bool bSuccess = true; + try + { + string strListFile = Path.Combine(Package.InstallerInfo.TempInstallFolder, _FileName); + if (File.Exists(strListFile)) + { + FileSystemUtils.DeleteFiles(Regex.Split(FileSystemUtils.ReadFile(strListFile), Environment.NewLine)); + } + Log.AddInfo(string.Format(Util.CLEANUP_ProcessComplete, Version.ToString(3))); + } + catch (Exception ex) + { + Log.AddFailure(ex); + bSuccess = false; + } + return bSuccess; + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The CleanupFile method cleansup a single file. + /// + /// The InstallFile to clean up + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + protected bool CleanupFile(InstallFile insFile) + { + try + { + //Backup File + if (File.Exists(PhysicalBasePath + insFile.FullName)) + { + Util.BackupFile(insFile, PhysicalBasePath, Log); + } + + //Delete file + Util.DeleteFile(insFile, PhysicalBasePath, Log); + return true; + } + catch (Exception exc) + { + Logger.Error(exc); + + return false; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ProcessFile method determines what to do with parsed "file" node + /// + /// The file represented by the node + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void ProcessFile(InstallFile file, XPathNavigator nav) + { + if (file != null) + { + Files.Add(file); + } + } + + protected override InstallFile ReadManifestItem(XPathNavigator nav, bool checkFileExists) + { + return base.ReadManifestItem(nav, false); + } + + /// ----------------------------------------------------------------------------- + /// + /// The RollbackFile method rolls back the cleanup of a single file. + /// + /// The InstallFile to commit + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void RollbackFile(InstallFile installFile) + { + if (File.Exists(installFile.BackupFileName)) + { + Util.RestoreFile(installFile, PhysicalBasePath, Log); + } + } + + #endregion + + #region "Public Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Clenup this is not neccessary + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + //Do nothing + base.Commit(); + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method cleansup the files + /// + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + bool bSuccess = true; + if (string.IsNullOrEmpty(_FileName)) + { + foreach (InstallFile file in Files) + { + bSuccess = CleanupFile(file); + if (!bSuccess) + { + break; + } + } + } + else + { + bSuccess = ProcessCleanupFile(); + } + Completed = bSuccess; + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + public override void ReadManifest(XPathNavigator manifestNav) + { + _FileName = Util.ReadAttribute(manifestNav, "fileName"); + base.ReadManifest(manifestNav); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the file component + /// + /// There is no uninstall for this component + /// + /// [cnurse] 09/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Installers/ComponentInstallerBase.cs b/DNN Platform/Library/Services/Installer/Installers/ComponentInstallerBase.cs new file mode 100644 index 00000000000..7c2543829d5 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ComponentInstallerBase.cs @@ -0,0 +1,210 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ComponentInstallerBase is a base class for all Component Installers + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public abstract class ComponentInstallerBase + { + protected ComponentInstallerBase() + { + Completed = Null.NullBoolean; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public virtual string AllowableFiles + { + get + { + return Null.NullString; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Completed flag + /// + /// A Boolean value + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public bool Completed { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the InstallMode + /// + /// An InstallMode value + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallMode InstallMode + { + get + { + return Package.InstallMode; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Logger + /// + /// An Logger object + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public Logger Log + { + get + { + return Package.Log; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Package + /// + /// An PackageInfo object + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public PackageInfo Package { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Files that are included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary PackageFiles + { + get + { + return Package.Files; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Physical Path to the root of the Site (eg D:\Websites\DotNetNuke") + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string PhysicalSitePath + { + get + { + return Package.InstallerInfo.PhysicalSitePath; + } + } + + public bool Skipped { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Installer supports Manifest only installs + /// + /// A Boolean + /// + /// [cnurse] 02/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public virtual bool SupportsManifestOnlyInstall + { + get + { + return true; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Type of the component + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Type { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Version of the Component + /// + /// A System.Version + /// + /// [cnurse] 02/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public Version Version { get; set; } + + public abstract void Commit(); + + public abstract void Install(); + + public abstract void ReadManifest(XPathNavigator manifestNav); + + public abstract void Rollback(); + + public abstract void UnInstall(); + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/ConfigInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ConfigInstaller.cs new file mode 100644 index 00000000000..de586ea66c1 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ConfigInstaller.cs @@ -0,0 +1,302 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ConfigInstaller installs Config changes + /// + /// + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ConfigInstaller : ComponentInstallerBase + { + #region "Private Members" + + private string _FileName = Null.NullString; + private string _InstallConfig = Null.NullString; + private XmlDocument _TargetConfig; + private InstallFile _TargetFile; + private string _UnInstallConfig = Null.NullString; + private string _UninstallFileName = Null.NullString; + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Install config changes + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string InstallConfig + { + get + { + return _InstallConfig; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Target Config XmlDocument + /// + /// An XmlDocument + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlDocument TargetConfig + { + get + { + return _TargetConfig; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Target Config file to change + /// + /// A String + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallFile TargetFile + { + get + { + return _TargetFile; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the UnInstall config changes + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string UnInstallConfig + { + get + { + return _UnInstallConfig; + } + } + + #endregion + + #region "Public Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + try + { + //Save the XmlDocument + Config.Save(TargetConfig, TargetFile.FullName); + Log.AddInfo(Util.CONFIG_Committed + " - " + TargetFile.Name); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the config component + /// + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + if (string.IsNullOrEmpty(_FileName)) + { + //First backup the config file + Util.BackupFile(TargetFile, PhysicalSitePath, Log); + + //Create an XmlDocument for the config file + _TargetConfig = new XmlDocument(); + TargetConfig.Load(Path.Combine(PhysicalSitePath, TargetFile.FullName)); + + //Create XmlMerge instance from InstallConfig source + var merge = new XmlMerge(new StringReader(InstallConfig), Package.Version.ToString(), Package.Name); + + //Update the Config file - Note that this method does not save the file - we will save it in Commit + merge.UpdateConfig(TargetConfig); + Completed = true; + Log.AddInfo(Util.CONFIG_Updated + " - " + TargetFile.Name); + } + else + { + //Process external file + string strConfigFile = Path.Combine(Package.InstallerInfo.TempInstallFolder, _FileName); + if (File.Exists(strConfigFile)) + { + //Create XmlMerge instance from config file source + StreamReader stream = File.OpenText(strConfigFile); + var merge = new XmlMerge(stream, Package.Version.ToString(3), Package.Name + " Install"); + + //Process merge + merge.UpdateConfigs(); + + //Close stream + stream.Close(); + + Completed = true; + Log.AddInfo(Util.CONFIG_Updated); + } + } + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the config compoent. + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + _FileName = Util.ReadAttribute(manifestNav, "fileName"); + _UninstallFileName = Util.ReadAttribute(manifestNav, "unInstallFileName"); + + if (string.IsNullOrEmpty(_FileName)) + { + XPathNavigator nav = manifestNav.SelectSingleNode("config"); + + //Get the name of the target config file to update + XPathNavigator nodeNav = nav.SelectSingleNode("configFile"); + string targetFileName = nodeNav.Value; + if (!string.IsNullOrEmpty(targetFileName)) + { + _TargetFile = new InstallFile(targetFileName, "", Package.InstallerInfo); + } + //Get the Install config changes + nodeNav = nav.SelectSingleNode("install"); + _InstallConfig = nodeNav.InnerXml; + + //Get the UnInstall config changes + nodeNav = nav.SelectSingleNode("uninstall"); + _UnInstallConfig = nodeNav.InnerXml; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the file component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //Do nothing as the changes are all in memory + Log.AddInfo(Util.CONFIG_RolledBack + " - " + TargetFile.Name); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the config component + /// + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + if (string.IsNullOrEmpty(_UninstallFileName)) + { + //Create an XmlDocument for the config file + _TargetConfig = new XmlDocument(); + TargetConfig.Load(Path.Combine(PhysicalSitePath, TargetFile.FullName)); + + //Create XmlMerge instance from UnInstallConfig source + var merge = new XmlMerge(new StringReader(UnInstallConfig), Package.Version.ToString(), Package.Name); + + //Update the Config file - Note that this method does save the file + merge.UpdateConfig(TargetConfig, TargetFile.FullName); + } + else + { + //Process external file + string strConfigFile = Path.Combine(Package.InstallerInfo.TempInstallFolder, _UninstallFileName); + if (File.Exists(strConfigFile)) + { + //Create XmlMerge instance from config file source + StreamReader stream = File.OpenText(strConfigFile); + var merge = new XmlMerge(stream, Package.Version.ToString(3), Package.Name + " UnInstall"); + + //Process merge + merge.UpdateConfigs(); + + //Close stream + stream.Close(); + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/ContainerInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ContainerInstaller.cs new file mode 100644 index 00000000000..3c9056ab3e2 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ContainerInstaller.cs @@ -0,0 +1,126 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ContainerInstaller installs Container Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ContainerInstaller : SkinInstaller + { + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("containerFiles") + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "containerFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("containerFile") + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "containerFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the SkinName Node ("containerName") + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string SkinNameNodeName + { + get + { + return "containerName"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the RootName of the Skin + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string SkinRoot + { + get + { + return SkinController.RootContainer; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Type of the Skin + /// + /// A String + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string SkinType + { + get + { + return "Container"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/DashboardInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/DashboardInstaller.cs new file mode 100644 index 00000000000..e999bcbb3df --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/DashboardInstaller.cs @@ -0,0 +1,205 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Modules.Dashboard.Components; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + public class DashboardInstaller : ComponentInstallerBase + { + #region "Private Properties" + + private string ControllerClass; + private bool IsEnabled; + private string Key; + private string LocalResources; + private string Src; + private DashboardControl TempDashboardControl; + private int ViewOrder; + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 01/05/2009 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ashx, aspx, ascx, vb, cs, resx, css, js, resources, config, vbproj, csproj, sln, htm, html"; + } + } + + #endregion + + #region "Private Methods" + + private void DeleteDashboard() + { + try + { + //Attempt to get the Dashboard + DashboardControl dashboardControl = DashboardController.GetDashboardControlByPackageId(Package.PackageID); + if (dashboardControl != null) + { + DashboardController.DeleteControl(dashboardControl); + } + Log.AddInfo(dashboardControl.DashboardControlKey + " " + Util.AUTHENTICATION_UnRegistered); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + public override void Commit() + { + } + + public override void Install() + { + bool bAdd = Null.NullBoolean; + try + { + //Attempt to get the Dashboard + TempDashboardControl = DashboardController.GetDashboardControlByKey(Key); + var dashboardControl = new DashboardControl(); + + if (TempDashboardControl == null) + { + dashboardControl.IsEnabled = true; + bAdd = true; + } + else + { + dashboardControl.DashboardControlID = TempDashboardControl.DashboardControlID; + dashboardControl.IsEnabled = TempDashboardControl.IsEnabled; + } + dashboardControl.DashboardControlKey = Key; + dashboardControl.PackageID = Package.PackageID; + dashboardControl.DashboardControlSrc = Src; + dashboardControl.DashboardControlLocalResources = LocalResources; + dashboardControl.ControllerClass = ControllerClass; + dashboardControl.ViewOrder = ViewOrder; + if (bAdd) + { + //Add new Dashboard + DashboardController.AddDashboardControl(dashboardControl); + } + else + { + //Update Dashboard + DashboardController.UpdateDashboardControl(dashboardControl); + } + Completed = true; + Log.AddInfo(dashboardControl.DashboardControlKey + " " + Util.DASHBOARD_Registered); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the Authentication compoent. + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + //Get the Key + Key = Util.ReadElement(manifestNav, "dashboardControl/key", Log, Util.DASHBOARD_KeyMissing); + + //Get the Src + Src = Util.ReadElement(manifestNav, "dashboardControl/src", Log, Util.DASHBOARD_SrcMissing); + + //Get the LocalResources + LocalResources = Util.ReadElement(manifestNav, "dashboardControl/localResources", Log, Util.DASHBOARD_LocalResourcesMissing); + + //Get the ControllerClass + ControllerClass = Util.ReadElement(manifestNav, "dashboardControl/controllerClass"); + + //Get the IsEnabled Flag + IsEnabled = bool.Parse(Util.ReadElement(manifestNav, "dashboardControl/isEnabled", "true")); + + //Get the ViewOrder + ViewOrder = int.Parse(Util.ReadElement(manifestNav, "dashboardControl/viewOrder", "-1")); + + if (Log.Valid) + { + Log.AddInfo(Util.DASHBOARD_ReadSuccess); + } + } + + public override void Rollback() + { + //If Temp Dashboard exists then we need to update the DataStore with this + if (TempDashboardControl == null) + { + //No Temp Dashboard - Delete newly added system + DeleteDashboard(); + } + else + { + //Temp Dashboard - Rollback to Temp + DashboardController.UpdateDashboardControl(TempDashboardControl); + } + } + + public override void UnInstall() + { + try + { + //Attempt to get the DashboardControl + DashboardControl dashboardControl = DashboardController.GetDashboardControlByPackageId(Package.PackageID); + if (dashboardControl != null) + { + DashboardController.DeleteControl(dashboardControl); + } + Log.AddInfo(dashboardControl.DashboardControlKey + " " + Util.DASHBOARD_UnRegistered); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/FileInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/FileInstaller.cs new file mode 100644 index 00000000000..d66b6938f70 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/FileInstaller.cs @@ -0,0 +1,575 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The FileInstaller installs File Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class FileInstaller : ComponentInstallerBase + { + #region Private Members + + private readonly List _Files = new List(); + private string _BasePath; + private bool _DeleteFiles = Null.NullBoolean; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the BasePath for the files + /// + /// The Base Path is relative to the WebRoot + /// A String + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + protected string BasePath + { + get + { + return _BasePath; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("files") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string CollectionNodeName + { + get + { + return "files"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Files that are included in this component + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + protected List Files + { + get + { + return _Files; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the default Path for the file - if not present in the manifest + /// + /// A String + /// + /// [cnurse] 08/10/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string DefaultPath + { + get + { + return Null.NullString; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("file") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string ItemNodeName + { + get + { + return "file"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PhysicalBasePath for the files + /// + /// A String + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string PhysicalBasePath + { + get + { + string _PhysicalBasePath = PhysicalSitePath + "\\" + BasePath; + if (!_PhysicalBasePath.EndsWith("\\")) + { + _PhysicalBasePath += "\\"; + } + return _PhysicalBasePath.Replace("/", "\\"); + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Packages files are deleted when uninstalling the + /// package + /// + /// A Boolean value + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public bool DeleteFiles + { + get + { + return _DeleteFiles; + } + set + { + _DeleteFiles = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Installer supports Manifest only installs + /// + /// A Boolean + /// + /// [cnurse] 02/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public override bool SupportsManifestOnlyInstall + { + get + { + return Null.NullBoolean; + } + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// The CommitFile method commits a single file. + /// + /// The InstallFile to commit + /// + /// [cnurse] 08/24/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void CommitFile(InstallFile insFile) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteFile method deletes a single file. + /// + /// The InstallFile to delete + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void DeleteFile(InstallFile insFile) + { + if (DeleteFiles) + { + Util.DeleteFile(insFile, PhysicalBasePath, Log); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The InstallFile method installs a single file. + /// + /// The InstallFile to install + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual bool InstallFile(InstallFile insFile) + { + try + { + //Check the White Lists + if ((Package.InstallerInfo.IgnoreWhiteList || Util.IsFileValid(insFile, Package.InstallerInfo.AllowableFiles))) + { + //Install File + if (File.Exists(PhysicalBasePath + insFile.FullName)) + { + Util.BackupFile(insFile, PhysicalBasePath, Log); + } + + //Copy file from temp location + Util.CopyFile(insFile, PhysicalBasePath, Log); + return true; + } + else + { + Log.AddFailure(string.Format(Util.FILE_NotAllowed, insFile.FullName)); + return false; + } + } + catch (Exception ex) + { + Log.AddFailure(ex); + return false; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that determines what type of file this installer supports + /// + /// The type of file being processed + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual bool IsCorrectType(InstallFileType type) + { + return true; + } + + /// ----------------------------------------------------------------------------- + /// + /// The ProcessFile method determines what to do with parsed "file" node + /// + /// The file represented by the node + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void ProcessFile(InstallFile file, XPathNavigator nav) + { + if (file != null && IsCorrectType(file.Type)) + { + Files.Add(file); + + //Add to the + Package.InstallerInfo.Files[file.FullName.ToLower()] = file; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadCustomManifest method reads the custom manifest items (that subclasses + /// of FileInstaller may need) + /// + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void ReadCustomManifest(XPathNavigator nav) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifestItem method reads a single node + /// + /// The XPathNavigator representing the node + /// Flag that determines whether a check should be made + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual InstallFile ReadManifestItem(XPathNavigator nav, bool checkFileExists) + { + string fileName = Null.NullString; + + //Get the path + XPathNavigator pathNav = nav.SelectSingleNode("path"); + if (pathNav == null) + { + fileName = DefaultPath; + } + else + { + fileName = pathNav.Value + "\\"; + } + + //Get the name + XPathNavigator nameNav = nav.SelectSingleNode("name"); + if (nameNav != null) + { + fileName += nameNav.Value; + } + + //Get the sourceFileName + string sourceFileName = Util.ReadElement(nav, "sourceFileName"); + var file = new InstallFile(fileName, sourceFileName, Package.InstallerInfo); + if ((!string.IsNullOrEmpty(BasePath)) && (BasePath.ToLowerInvariant().StartsWith("app_code") && file.Type == InstallFileType.Other)) + { + file.Type = InstallFileType.AppCode; + } + if (file != null) + { + //Set the Version + string strVersion = XmlUtils.GetNodeValue(nav, "version"); + if (!string.IsNullOrEmpty(strVersion)) + { + file.SetVersion(new Version(strVersion)); + } + else + { + file.SetVersion(Package.Version); + } + + //Set the Action + string strAction = XmlUtils.GetAttributeValue(nav, "action"); + if (!string.IsNullOrEmpty(strAction)) + { + file.Action = strAction; + } + if (InstallMode == InstallMode.Install && checkFileExists && file.Action != "UnRegister") + { + if (File.Exists(file.TempFileName)) + { + Log.AddInfo(string.Format(Util.FILE_Found, file.Path, file.Name)); + } + else + { + Log.AddFailure(Util.FILE_NotFound + " - " + file.TempFileName); + } + } + } + return file; + } + + /// ----------------------------------------------------------------------------- + /// + /// The RollbackFile method rolls back the install of a single file. + /// + /// For new installs this removes the added file. For upgrades it restores the + /// backup file created during install + /// The InstallFile to commit + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void RollbackFile(InstallFile installFile) + { + if (File.Exists(installFile.BackupFileName)) + { + Util.RestoreFile(installFile, PhysicalBasePath, Log); + } + else + { + DeleteFile(installFile); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstallFile method unInstalls a single file. + /// + /// The InstallFile to unInstall. + /// + /// [cnurse] 01/07/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void UnInstallFile(InstallFile unInstallFile) + { + DeleteFile(unInstallFile); + } + + #endregion + + #region Public Methods + + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Files this is not neccessary + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + try + { + foreach (InstallFile file in Files) + { + CommitFile(file); + } + Completed = true; + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the file component + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + bool bSuccess = true; + foreach (InstallFile file in Files) + { + bSuccess = InstallFile(file); + if (!bSuccess) + { + break; + } + } + Completed = bSuccess; + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the file compoent. + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + XPathNavigator rootNav = manifestNav.SelectSingleNode(CollectionNodeName); + if (rootNav != null) + { + XPathNavigator baseNav = rootNav.SelectSingleNode("basePath"); + if (baseNav != null) + { + _BasePath = baseNav.Value; + } + ReadCustomManifest(rootNav); + foreach (XPathNavigator nav in rootNav.Select(ItemNodeName)) + { + ProcessFile(ReadManifestItem(nav, true), nav); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the file component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + try + { + foreach (InstallFile file in Files) + { + RollbackFile(file); + } + Completed = true; + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the file component + /// + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + try + { + foreach (InstallFile file in Files) + { + UnInstallFile(file); + } + Completed = true; + } + catch (Exception ex) + { + Log.AddFailure(Util.EXCEPTION + " - " + ex.Message); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/InstallerFactory.cs b/DNN Platform/Library/Services/Installer/Installers/InstallerFactory.cs new file mode 100644 index 00000000000..10a4223b5c4 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/InstallerFactory.cs @@ -0,0 +1,175 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Common.Lists; +using DotNetNuke.Framework; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The InstallerFactory is a factory class that is used to instantiate the + /// appropriate Component Installer + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class InstallerFactory + { + #region "Public Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The GetInstaller method instantiates the relevant Component Installer + /// + /// The type of Installer + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public static ComponentInstallerBase GetInstaller(string installerType) + { + ComponentInstallerBase installer = null; + switch (installerType) + { + case "File": + installer = new FileInstaller(); + break; + case "Assembly": + installer = new AssemblyInstaller(); + break; + case "ResourceFile": + installer = new ResourceFileInstaller(); + break; + case "AuthenticationSystem": + case "Auth_System": + installer = new AuthenticationInstaller(); + break; + case "DashboardControl": + installer = new DashboardInstaller(); + break; + case "Script": + installer = new ScriptInstaller(); + break; + case "Config": + installer = new ConfigInstaller(); + break; + case "Cleanup": + installer = new CleanupInstaller(); + break; + case "Skin": + installer = new SkinInstaller(); + break; + case "Container": + installer = new ContainerInstaller(); + break; + case "Module": + installer = new ModuleInstaller(); + break; + case "CoreLanguage": + installer = new LanguageInstaller(LanguagePackType.Core); + break; + case "ExtensionLanguage": + installer = new LanguageInstaller(LanguagePackType.Extension); + break; + case "Provider": + installer = new ProviderInstaller(); + break; + case "SkinObject": + installer = new SkinControlInstaller(); + break; + case "UrlProvider": + installer = new UrlProviderInstaller(); + break; + case "Widget": + installer = new WidgetInstaller(); + break; + default: + //Installer type is defined in the List + var listController = new ListController(); + ListEntryInfo entry = listController.GetListEntryInfo("Installer", installerType); + + if (entry != null && !string.IsNullOrEmpty(entry.Text)) + { + //The class for the Installer is specified in the Text property + installer = (ComponentInstallerBase) Reflection.CreateObject(entry.Text, "Installer_" + entry.Value); + } + break; + } + return installer; + } + + /// ----------------------------------------------------------------------------- + /// + /// The GetInstaller method instantiates the relevant Component Installer + /// + /// The manifest (XPathNavigator) for the component + /// The associated PackageInfo instance + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public static ComponentInstallerBase GetInstaller(XPathNavigator manifestNav, PackageInfo package) + { + string installerType = Util.ReadAttribute(manifestNav, "type"); + string componentVersion = Util.ReadAttribute(manifestNav, "version"); + + ComponentInstallerBase installer = GetInstaller(installerType); + if (installer != null) + { + //Set package + installer.Package = package; + + //Set type + installer.Type = installerType; + + if (!string.IsNullOrEmpty(componentVersion)) + { + installer.Version = new Version(componentVersion); + } + else + { + installer.Version = package.Version; + } + + //Read Manifest + if (package.InstallerInfo.InstallMode != InstallMode.ManifestOnly || installer.SupportsManifestOnlyInstall) + { + installer.ReadManifest(manifestNav); + } + } + return installer; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/LanguageInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/LanguageInstaller.cs new file mode 100644 index 00000000000..1f9d0485757 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/LanguageInstaller.cs @@ -0,0 +1,322 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml.XPath; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The LanguageInstaller installs Language Packs to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 01/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public class LanguageInstaller : FileInstaller + { + #region Private Members + + private readonly LanguagePackType LanguagePackType; + private LanguagePackInfo InstalledLanguagePack; + private Locale Language; + private LanguagePackInfo LanguagePack; + private Locale TempLanguage; + + #endregion + + public LanguageInstaller(LanguagePackType type) + { + LanguagePackType = type; + } + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("languageFiles") + /// + /// A String + /// + /// [cnurse] 01/29/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "languageFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("languageFile") + /// + /// A String + /// + /// [cnurse] 01/29/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "languageFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get { return "resx, xml, tdf,template"; } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteLanguage method deletes the Language + /// from the data Store. + /// + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + private void DeleteLanguage() + { + try + { + //Attempt to get the LanguagePack + LanguagePackInfo tempLanguagePack = LanguagePackController.GetLanguagePackByPackage(Package.PackageID); + + //Attempt to get the Locale + Locale language = LocaleController.Instance.GetLocale(tempLanguagePack.LanguageID); + if (tempLanguagePack != null) + { + LanguagePackController.DeleteLanguagePack(tempLanguagePack); + } + + // fix DNN-26330 Removing a language pack extension removes the language + // we should not delete language when deleting language pack, as there is just a loose relationship + //if (language != null && tempLanguagePack.PackageType == LanguagePackType.Core) + //{ + // Localization.Localization.DeleteLanguage(language); + //} + + Log.AddInfo(string.Format(Util.LANGUAGE_UnRegistered, language.Text)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// The ReadCustomManifest method reads the custom manifest items + /// + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void ReadCustomManifest(XPathNavigator nav) + { + Language = new Locale(); + LanguagePack = new LanguagePackInfo(); + + //Get the Skin name + Language.Code = Util.ReadElement(nav, "code"); + Language.Text = Util.ReadElement(nav, "displayName"); + Language.Fallback = Util.ReadElement(nav, "fallback"); + + if (LanguagePackType == LanguagePackType.Core) + { + LanguagePack.DependentPackageID = -2; + } + else + { + string packageName = Util.ReadElement(nav, "package"); + PackageInfo package = PackageController.GetPackageByName(packageName); + if (package != null) + { + LanguagePack.DependentPackageID = package.PackageID; + } + } + + //Call base class + base.ReadCustomManifest(nav); + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Modules this is not neccessary + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + if (LanguagePackType == LanguagePackType.Core || LanguagePack.DependentPackageID > 0) + { + base.Commit(); + } + else + { + Completed = true; + Skipped = true; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the language component + /// + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + if (LanguagePackType == LanguagePackType.Core || LanguagePack.DependentPackageID > 0) + { + try + { + //Attempt to get the LanguagePack + InstalledLanguagePack = LanguagePackController.GetLanguagePackByPackage(Package.PackageID); + if (InstalledLanguagePack != null) + { + LanguagePack.LanguagePackID = InstalledLanguagePack.LanguagePackID; + } + + //Attempt to get the Locale + TempLanguage = LocaleController.Instance.GetLocale(Language.Code); + if (TempLanguage != null) + { + Language.LanguageId = TempLanguage.LanguageId; + } + if (LanguagePack.PackageType == LanguagePackType.Core) + { + //Update language + Localization.Localization.SaveLanguage(Language); + } + + //Set properties for Language Pack + LanguagePack.PackageID = Package.PackageID; + LanguagePack.LanguageID = Language.LanguageId; + + //Update LanguagePack + LanguagePackController.SaveLanguagePack(LanguagePack); + + Log.AddInfo(string.Format(Util.LANGUAGE_Registered, Language.Text)); + + //install (copy the files) by calling the base class + base.Install(); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + else + { + Completed = true; + Skipped = true; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp Language exists then we need to update the DataStore with this + if (TempLanguage == null) + { + //No Temp Language - Delete newly added Language + DeleteLanguage(); + } + else + { + //Temp Language - Rollback to Temp + Localization.Localization.SaveLanguage(TempLanguage); + } + + //Call base class to prcoess files + base.Rollback(); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the language component + /// + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteLanguage(); + + //Call base class to prcoess files + base.UnInstall(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/ModuleInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ModuleInstaller.cs new file mode 100644 index 00000000000..7ab1a4338b9 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ModuleInstaller.cs @@ -0,0 +1,340 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.EventQueue; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ModuleInstaller installs Module Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ModuleInstaller : ComponentInstallerBase + { + #region Private Properties + + private DesktopModuleInfo _desktopModule; + private EventMessage _eventMessage; + private DesktopModuleInfo _installedDesktopModule; + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "cshtml, vbhtml, ashx, aspx, ascx, vb, cs, resx, css, js, resources, config, vbproj, csproj, sln, htm, html, xml, psd, svc, asmx"; + } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteModule method deletes the Module from the data Store. + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + private void DeleteModule() + { + try + { + //Attempt to get the Desktop Module + DesktopModuleInfo tempDesktopModule = DesktopModuleController.GetDesktopModuleByPackageID(Package.PackageID); + if (tempDesktopModule != null) + { + //Remove CodeSubDirectory + if ((_desktopModule != null) && (!string.IsNullOrEmpty(_desktopModule.CodeSubDirectory))) + { + Config.RemoveCodeSubDirectory(_desktopModule.CodeSubDirectory); + } + var controller = new DesktopModuleController(); + controller.DeleteDesktopModule(tempDesktopModule); + } + Log.AddInfo(string.Format(Util.MODULE_UnRegistered, tempDesktopModule.ModuleName)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Modules this is not neccessary + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + //Add CodeSubDirectory + if (!string.IsNullOrEmpty(_desktopModule.CodeSubDirectory)) + { + Config.AddCodeSubDirectory(_desktopModule.CodeSubDirectory); + } + if (_desktopModule.SupportedFeatures == Null.NullInteger) + { + //Set an Event Message so the features are loaded by reflection on restart + var oAppStartMessage = new EventMessage(); + oAppStartMessage.Priority = MessagePriority.High; + oAppStartMessage.ExpirationDate = DateTime.Now.AddYears(-1); + oAppStartMessage.SentDate = DateTime.Now; + oAppStartMessage.Body = ""; + oAppStartMessage.ProcessorType = "DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke"; + oAppStartMessage.ProcessorCommand = "UpdateSupportedFeatures"; + + //Add custom Attributes for this message + oAppStartMessage.Attributes.Add("BusinessControllerClass", _desktopModule.BusinessControllerClass); + oAppStartMessage.Attributes.Add("desktopModuleID", _desktopModule.DesktopModuleID.ToString()); + + //send it to occur on next App_Start Event + EventQueueController.SendMessage(oAppStartMessage, "Application_Start_FirstRequest"); + } + + //Add Event Message + if (_eventMessage != null) + { + if (!String.IsNullOrEmpty(_eventMessage.Attributes["UpgradeVersionsList"])) + { + _eventMessage.Attributes.Set("desktopModuleID", _desktopModule.DesktopModuleID.ToString()); + EventQueueController.SendMessage(_eventMessage, "Application_Start"); + } + } + + //Add DesktopModule to all portals + if (!_desktopModule.IsPremium) + { + DesktopModuleController.AddDesktopModuleToPortals(_desktopModule.DesktopModuleID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the Module component + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + //Attempt to get the Desktop Module + _installedDesktopModule = DesktopModuleController.GetDesktopModuleByModuleName(_desktopModule.ModuleName, Package.InstallerInfo.PortalID); + + if (_installedDesktopModule != null) + { + _desktopModule.DesktopModuleID = _installedDesktopModule.DesktopModuleID; + //save the module's category + _desktopModule.Category = _installedDesktopModule.Category; + } + + //Clear ModuleControls and Module Definitions caches in case script has modifed the contents + DataCache.RemoveCache(DataCache.ModuleDefinitionCacheKey); + DataCache.RemoveCache(DataCache.ModuleControlsCacheKey); + + //Save DesktopModule and child objects to database + _desktopModule.PackageID = Package.PackageID; + _desktopModule.DesktopModuleID = DesktopModuleController.SaveDesktopModule(_desktopModule, true, false); + + Completed = true; + Log.AddInfo(string.Format(Util.MODULE_Registered, _desktopModule.ModuleName)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the Module compoent. + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + //Load the Desktop Module from the manifest + _desktopModule = CBO.DeserializeObject(new StringReader(manifestNav.InnerXml)); + + _desktopModule.FriendlyName = Package.FriendlyName; + _desktopModule.Description = Package.Description; + _desktopModule.Version = Globals.FormatVersion(Package.Version); + _desktopModule.CompatibleVersions = Null.NullString; + _desktopModule.Dependencies = Null.NullString; + _desktopModule.Permissions = Null.NullString; + if (string.IsNullOrEmpty(_desktopModule.BusinessControllerClass)) + { + _desktopModule.SupportedFeatures = 0; + } + XPathNavigator eventMessageNav = manifestNav.SelectSingleNode("eventMessage"); + if (eventMessageNav != null) + { + _eventMessage = new EventMessage(); + _eventMessage.Priority = MessagePriority.High; + _eventMessage.ExpirationDate = DateTime.Now.AddYears(-1); + _eventMessage.SentDate = DateTime.Now; + _eventMessage.Body = ""; + _eventMessage.ProcessorType = Util.ReadElement(eventMessageNav, "processorType", Log, Util.EVENTMESSAGE_TypeMissing); + _eventMessage.ProcessorCommand = Util.ReadElement(eventMessageNav, "processorCommand", Log, Util.EVENTMESSAGE_CommandMissing); + foreach (XPathNavigator attributeNav in eventMessageNav.Select("attributes/*")) + { + var attribName = attributeNav.Name; + var attribValue = attributeNav.Value; + if (attribName == "upgradeVersionsList") + { + if (!String.IsNullOrEmpty(attribValue)) + { + string[] upgradeVersions = attribValue.Split(','); + attribValue = ""; foreach (string version in upgradeVersions) + { + Version upgradeVersion = null; + try + { + upgradeVersion = new Version(version); + } + catch (FormatException) + { + Log.AddWarning(string.Format(Util.MODULE_InvalidVersion, version)); + } + + if (upgradeVersion != null && upgradeVersion > Package.InstalledVersion && Globals.Status == Globals.UpgradeStatus.Upgrade) //To allow when upgrading to an upper version + { + attribValue += version + ","; + } + else if (upgradeVersion != null && (Globals.Status == Globals.UpgradeStatus.Install || Globals.Status == Globals.UpgradeStatus.None)) //To allow when fresh installing or installresources + { + attribValue += version + ","; + } + } + attribValue = attribValue.TrimEnd(','); + } + } + _eventMessage.Attributes.Add(attribName, attribValue); + } + } + + //Load permissions (to add) + foreach (XPathNavigator moduleDefinitionNav in manifestNav.Select("desktopModule/moduleDefinitions/moduleDefinition")) + { + string friendlyName = Util.ReadElement(moduleDefinitionNav, "friendlyName"); + foreach (XPathNavigator permissionNav in moduleDefinitionNav.Select("permissions/permission")) + { + var permission = new PermissionInfo(); + permission.PermissionCode = Util.ReadAttribute(permissionNav, "code"); + permission.PermissionKey = Util.ReadAttribute(permissionNav, "key"); + permission.PermissionName = Util.ReadAttribute(permissionNav, "name"); + ModuleDefinitionInfo moduleDefinition = _desktopModule.ModuleDefinitions[friendlyName]; + if (moduleDefinition != null) + { + moduleDefinition.Permissions.Add(permission.PermissionKey, permission); + } + } + } + if (Log.Valid) + { + Log.AddInfo(Util.MODULE_ReadSuccess); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp Module exists then we need to update the DataStore with this + if (_installedDesktopModule == null) + { + //No Temp Module - Delete newly added module + DeleteModule(); + } + else + { + //Temp Module - Rollback to Temp + DesktopModuleController.SaveDesktopModule(_installedDesktopModule, true, false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the Module component + /// + /// + /// [cnurse] 01/15/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteModule(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/PackageInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/PackageInstaller.cs new file mode 100644 index 00000000000..f871a73a396 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/PackageInstaller.cs @@ -0,0 +1,619 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Dependencies; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageInstaller class is an Installer for Packages + /// + /// + /// [cnurse] 01/16/2008 created + /// + /// ----------------------------------------------------------------------------- + public class PackageInstaller : ComponentInstallerBase + { + #region Private Members + + private readonly SortedList _componentInstallers = new SortedList(); + private PackageInfo _installedPackage; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new PackageInstaller instance + /// + /// A PackageInfo instance + /// + /// [cnurse] 01/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public PackageInstaller(PackageInfo package) + { + IsValid = true; + DeleteFiles = Null.NullBoolean; + Package = package; + if (!string.IsNullOrEmpty(package.Manifest)) + { + //Create an XPathDocument from the Xml + var doc = new XPathDocument(new StringReader(package.Manifest)); + XPathNavigator nav = doc.CreateNavigator().SelectSingleNode("package"); + ReadComponents(nav); + } + else + { + ComponentInstallerBase installer = InstallerFactory.GetInstaller(package.PackageType); + if (installer != null) + { + //Set package + installer.Package = package; + + //Set type + installer.Type = package.PackageType; + _componentInstallers.Add(0, installer); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new PackageInstaller instance + /// + /// An InstallerInfo instance + /// The manifest as a string + /// + /// [cnurse] 01/16/2008 created + /// + /// ----------------------------------------------------------------------------- + public PackageInstaller(string packageManifest, InstallerInfo info) + { + IsValid = true; + DeleteFiles = Null.NullBoolean; + Package = new PackageInfo(info); + Package.Manifest = packageManifest; + + if (!string.IsNullOrEmpty(packageManifest)) + { + //Create an XPathDocument from the Xml + var doc = new XPathDocument(new StringReader(packageManifest)); + XPathNavigator nav = doc.CreateNavigator().SelectSingleNode("package"); + ReadManifest(nav); + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Packages files are deleted when uninstalling the + /// package + /// + /// A Boolean value + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public bool DeleteFiles { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Package is Valid + /// + /// A Boolean value + /// + /// [cnurse] 01/16/2008 created + /// + /// ----------------------------------------------------------------------------- + public bool IsValid { get; private set; } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// The CheckSecurity method checks whether the user has the appropriate security + /// + /// + /// [cnurse] 09/04/2007 created + /// + /// ----------------------------------------------------------------------------- + private void CheckSecurity() + { + PackageType type = PackageController.GetPackageType(Package.PackageType); + if (type == null) + { + //This package type not registered + Log.Logs.Clear(); + Log.AddFailure(Util.SECURITY_NotRegistered + " - " + Package.PackageType); + IsValid = false; + } + else + { + if (type.SecurityAccessLevel > Package.InstallerInfo.SecurityAccessLevel) + { + Log.Logs.Clear(); + Log.AddFailure(Util.SECURITY_Installer); + IsValid = false; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadComponents method reads the components node of the manifest file. + /// + /// + /// [cnurse] 01/21/2008 created + /// + /// ----------------------------------------------------------------------------- + private void ReadComponents(XPathNavigator manifestNav) + { + foreach (XPathNavigator componentNav in manifestNav.CreateNavigator().Select("components/component")) + { + //Set default order to next value (ie the same as the size of the collection) + int order = _componentInstallers.Count; + + string type = componentNav.GetAttribute("type", ""); + if (InstallMode == InstallMode.Install) + { + string installOrder = componentNav.GetAttribute("installOrder", ""); + if (!string.IsNullOrEmpty(installOrder)) + { + order = int.Parse(installOrder); + } + } + else + { + string unInstallOrder = componentNav.GetAttribute("unInstallOrder", ""); + if (!string.IsNullOrEmpty(unInstallOrder)) + { + order = int.Parse(unInstallOrder); + } + } + if (Package.InstallerInfo != null) + { + Log.AddInfo(Util.DNN_ReadingComponent + " - " + type); + } + ComponentInstallerBase installer = InstallerFactory.GetInstaller(componentNav, Package); + if (installer == null) + { + Log.AddFailure(Util.EXCEPTION_InstallerCreate); + } + else + { + _componentInstallers.Add(order, installer); + Package.InstallerInfo.AllowableFiles += ", " + installer.AllowableFiles; + } + } + } + + private string ReadTextFromFile(string source) + { + string strText = Null.NullString; + if (Package.InstallerInfo.InstallMode != InstallMode.ManifestOnly) + { + //Load from file + strText = FileSystemUtils.ReadFile(Package.InstallerInfo.TempInstallFolder + "\\" + source); + } + return strText; + } + + /// ----------------------------------------------------------------------------- + /// + /// The ValidateVersion method checks whether the package is already installed + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ValidateVersion(string strVersion) + { + if (string.IsNullOrEmpty(strVersion)) + { + IsValid = false; + return; + } + Package.Version = new Version(strVersion); + if (_installedPackage != null) + { + Package.InstalledVersion = _installedPackage.Version; + Package.InstallerInfo.PackageID = _installedPackage.PackageID; + + if (Package.InstalledVersion > Package.Version) + { + Log.AddFailure(Util.INSTALL_Version + " - " + Package.InstalledVersion.ToString(3)); + IsValid = false; + } + else if (Package.InstalledVersion == Package.Version) + { + Package.InstallerInfo.Installed = true; + Package.InstallerInfo.PortalID = _installedPackage.PortalID; + } + } + } + + private string getSpecificFolderName(XPathNavigator manifestNav, string xpath, string elementName,string startWith) + { + string result = String.Empty; + var foldernameNav = manifestNav.Select(xpath); + + if (foldernameNav != null) + { + while(foldernameNav.MoveNext()) + { + var elementValue = Util.ReadElement(foldernameNav.Current, elementName); + if(!String.IsNullOrEmpty(elementValue) && elementValue.StartsWith(startWith)) + { + result = elementValue; + break; + } + } + } + return result; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method commits the package installation + /// + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + for (int index = 0; index <= _componentInstallers.Count - 1; index++) + { + ComponentInstallerBase compInstaller = _componentInstallers.Values[index]; + if (compInstaller.Version >= Package.InstalledVersion && compInstaller.Completed) + { + compInstaller.Commit(); + } + } + if (Log.Valid) + { + Log.AddInfo(Util.INSTALL_Committed); + } + else + { + Log.AddFailure(Util.INSTALL_Aborted); + } + Package.InstallerInfo.PackageID = Package.PackageID; + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the components of the package + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + bool isCompleted = true; + try + { + //Save the Package Information + if (_installedPackage != null) + { + Package.PackageID = _installedPackage.PackageID; + } + + //Save Package + PackageController.SavePackage(Package); + + //Iterate through all the Components + for (int index = 0; index <= _componentInstallers.Count - 1; index++) + { + ComponentInstallerBase compInstaller = _componentInstallers.Values[index]; + if ((_installedPackage == null) || (compInstaller.Version > Package.InstalledVersion) || (Package.InstallerInfo.RepairInstall)) + { + Log.AddInfo(Util.INSTALL_Start + " - " + compInstaller.Type); + compInstaller.Install(); + if (compInstaller.Completed) + { + if (compInstaller.Skipped) + { + Log.AddInfo(Util.COMPONENT_Skipped + " - " + compInstaller.Type); + } + else + { + Log.AddInfo(Util.COMPONENT_Installed + " - " + compInstaller.Type); + } + } + else + { + Log.AddFailure(Util.INSTALL_Failed + " - " + compInstaller.Type); + isCompleted = false; + break; + } + } + } + } + catch (Exception) + { + Log.AddFailure(Util.INSTALL_Aborted + " - " + Package.Name); + } + if (isCompleted) + { + //All components successfully installed so Commit any pending changes + Commit(); + } + else + { + //There has been a failure so Rollback + Rollback(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file and parses it into components. + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + //Get Name Property + Package.Name = Util.ReadAttribute(manifestNav, "name", Log, Util.EXCEPTION_NameMissing); + + //Get Type + Package.PackageType = Util.ReadAttribute(manifestNav, "type", Log, Util.EXCEPTION_TypeMissing); + + //If Skin or Container then set PortalID + if (Package.PackageType == "Skin" || Package.PackageType == "Container") + { + Package.PortalID = Package.InstallerInfo.PortalID; + } + CheckSecurity(); + if (!IsValid) + { + return; + } + + //Attempt to get the Package from the Data Store (see if its installed) + _installedPackage = PackageController.GetPackageByName(Package.PortalID, Package.Name); + + //Get IsSystem + Package.IsSystemPackage = bool.Parse(Util.ReadAttribute(manifestNav, "isSystem", false, Log, "", bool.FalseString)); + + //Get Version + string strVersion = Util.ReadAttribute(manifestNav, "version", Log, Util.EXCEPTION_VersionMissing); + ValidateVersion(strVersion); + if (!IsValid) + { + return; + } + Log.AddInfo(Util.DNN_ReadingPackage + " - " + Package.PackageType + " - " + Package.Name); + Package.FriendlyName = Util.ReadElement(manifestNav, "friendlyName", Package.Name); + Package.Description = Util.ReadElement(manifestNav, "description"); + + XPathNavigator foldernameNav = null; + Package.FolderName = String.Empty; + switch (Package.PackageType) + { + case "Module": + //In Dynamics moduels, a component:type=File can have a basePath pointing to the App_Conde folder. This is not a correct FolderName + //To ensure that FolderName is DesktopModules... + var folderNameValue = getSpecificFolderName(manifestNav, "components/component/files", "basePath", "DesktopModules"); + if (!String.IsNullOrEmpty(folderNameValue)) Package.FolderName = folderNameValue.Replace('\\', '/'); + break; + case "Auth_System": + foldernameNav = manifestNav.SelectSingleNode("components/component/files"); + if (foldernameNav != null) Package.FolderName = Util.ReadElement(foldernameNav, "basePath").Replace('\\', '/'); + break; + case "Container": + foldernameNav = manifestNav.SelectSingleNode("components/component/containerFiles"); + if (foldernameNav != null) Package.FolderName = Globals.glbContainersPath + Util.ReadElement(foldernameNav, "containerName").Replace('\\', '/'); + break; + case "Skin": + foldernameNav = manifestNav.SelectSingleNode("components/component/skinFiles"); + if (foldernameNav != null) Package.FolderName = Globals.glbSkinsPath + Util.ReadElement(foldernameNav, "skinName").Replace('\\', '/'); + break; + default: + break; + } + + //Get Icon + XPathNavigator iconFileNav = manifestNav.SelectSingleNode("iconFile"); + if (iconFileNav != null) + { + if (iconFileNav.Value != string.Empty) + { + if (iconFileNav.Value.StartsWith("~/")) + { + Package.IconFile = iconFileNav.Value; + } + else + { + Package.IconFile = (String.IsNullOrEmpty(Package.FolderName) ? "" : Package.FolderName + "/") + iconFileNav.Value; + Package.IconFile = (!Package.IconFile.StartsWith("~/")) ? "~/" + Package.IconFile : Package.IconFile; + } + } + } + //Get Author + XPathNavigator authorNav = manifestNav.SelectSingleNode("owner"); + if (authorNav != null) + { + Package.Owner = Util.ReadElement(authorNav, "name"); + Package.Organization = Util.ReadElement(authorNav, "organization"); + Package.Url = Util.ReadElement(authorNav, "url"); + Package.Email = Util.ReadElement(authorNav, "email"); + } + + //Get License + XPathNavigator licenseNav = manifestNav.SelectSingleNode("license"); + if (licenseNav != null) + { + string licenseSrc = Util.ReadAttribute(licenseNav, "src"); + if (string.IsNullOrEmpty(licenseSrc)) + { + //Load from element + Package.License = licenseNav.Value; + } + else + { + Package.License = ReadTextFromFile(licenseSrc); + } + } + if (string.IsNullOrEmpty(Package.License)) + { + //Legacy Packages have no license + Package.License = Util.PACKAGE_NoLicense; + } + + //Get Release Notes + XPathNavigator relNotesNav = manifestNav.SelectSingleNode("releaseNotes"); + if (relNotesNav != null) + { + string relNotesSrc = Util.ReadAttribute(relNotesNav, "src"); + if (string.IsNullOrEmpty(relNotesSrc)) + { + //Load from element + Package.ReleaseNotes = relNotesNav.Value; + } + else + { + Package.ReleaseNotes = ReadTextFromFile(relNotesSrc); + } + } + if (string.IsNullOrEmpty(Package.ReleaseNotes)) + { + //Legacy Packages have no Release Notes + Package.ReleaseNotes = Util.PACKAGE_NoReleaseNotes; + } + + //Parse the Dependencies + IDependency dependency = null; + foreach (XPathNavigator dependencyNav in manifestNav.CreateNavigator().Select("dependencies/dependency")) + { + dependency = DependencyFactory.GetDependency(dependencyNav); + if (!dependency.IsValid) + { + Log.AddFailure(dependency.ErrorMessage); + return; + } + } + + //Read Components + ReadComponents(manifestNav); + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method rolls back the package installation + /// + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + for (int index = 0; index <= _componentInstallers.Count - 1; index++) + { + ComponentInstallerBase compInstaller = _componentInstallers.Values[index]; + if (compInstaller.Version > Package.InstalledVersion && compInstaller.Completed) + { + Log.AddInfo(Util.COMPONENT_RollingBack + " - " + compInstaller.Type); + compInstaller.Rollback(); + Log.AddInfo(Util.COMPONENT_RolledBack + " - " + compInstaller.Type); + } + } + + //If Previously Installed Package exists then we need to update the DataStore with this + if (_installedPackage == null) + { + //No Previously Installed Package - Delete newly added Package + PackageController.DeletePackage(Package); + } + else + { + //Previously Installed Package - Rollback to Previously Installed + PackageController.SavePackage(_installedPackage); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Uninstall method uninstalls the components of the package + /// + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + //Iterate through all the Components + for (int index = 0; index <= _componentInstallers.Count - 1; index++) + { + ComponentInstallerBase compInstaller = _componentInstallers.Values[index]; + var fileInstaller = compInstaller as FileInstaller; + if (fileInstaller != null) + { + fileInstaller.DeleteFiles = DeleteFiles; + } + Log.ResetFlags(); + Log.AddInfo(Util.UNINSTALL_StartComp + " - " + compInstaller.Type); + compInstaller.UnInstall(); + Log.AddInfo(Util.COMPONENT_UnInstalled + " - " + compInstaller.Type); + if (Log.Valid) + { + Log.AddInfo(Util.UNINSTALL_SuccessComp + " - " + compInstaller.Type); + } + else + { + Log.AddWarning(Util.UNINSTALL_WarningsComp + " - " + compInstaller.Type); + } + } + + //Remove the Package information from the Data Store + PackageController.DeletePackage(Package); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/ProviderInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ProviderInstaller.cs new file mode 100644 index 00000000000..84c7b73e43f --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ProviderInstaller.cs @@ -0,0 +1,82 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml.XPath; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ProviderInstaller installs Provider Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 05/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ProviderInstaller : ComponentInstallerBase + { + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ashx, aspx, ascx, vb, cs, resx, css, js, resources, config, xml, htc, html, htm, text, vbproj, csproj, sln"; + } + } + + public override void Commit() + { + Completed = true; + } + + public override void Install() + { + Completed = true; + } + + public override void ReadManifest(XPathNavigator manifestNav) + { + } + + public override void Rollback() + { + Completed = true; + } + + public override void UnInstall() + { + Completed = true; + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/ResourceFileInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ResourceFileInstaller.cs new file mode 100644 index 00000000000..d700f411afb --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ResourceFileInstaller.cs @@ -0,0 +1,363 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +using ICSharpCode.SharpZipLib.Zip; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ResourceFileInstaller installs Resource File Components (zips) to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ResourceFileInstaller : FileInstaller + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ResourceFileInstaller)); + #region "Public Contants" + public const string DEFAULT_MANIFESTEXT = ".manifest"; + private string _Manifest; + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("resourceFiles") + /// + /// A String + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "resourceFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("resourceFile") + /// + /// A String + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "resourceFile"; + } + } + + /// ----------------------------------------------------------------------------- + protected string Manifest + { + get + { + return _Manifest; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "resources, zip"; + } + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The CommitFile method commits a single file. + /// + /// The InstallFile to commit + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void CommitFile(InstallFile insFile) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteFile method deletes a single assembly. + /// + /// The InstallFile to delete + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void DeleteFile(InstallFile file) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The InstallFile method installs a single assembly. + /// + /// The InstallFile to install + /// + /// [cnurse] 01/18/2008 created + /// [aprasad] 01/26/2011 Removed condition [If String.IsNullOrEmpty(Manifest) Then] prior to setting _Manifest + /// Since it was not able to set _Manifest for the second file onwards, same manifest file was being + /// created for all the resource files + /// + /// ----------------------------------------------------------------------------- + protected override bool InstallFile(InstallFile insFile) + { + FileStream fs = null; + ZipInputStream unzip = null; + XmlWriter writer = null; + bool retValue = true; + try + { + Log.AddInfo(Util.FILES_Expanding); + unzip = new ZipInputStream(new FileStream(insFile.TempFileName, FileMode.Open)); + + //Create a writer to create the manifest for the resource file + _Manifest = insFile.Name + ".manifest"; + if (!Directory.Exists(PhysicalBasePath)) + { + Directory.CreateDirectory(PhysicalBasePath); + } + fs = new FileStream(Path.Combine(PhysicalBasePath, Manifest), FileMode.Create, FileAccess.Write); + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.OmitXmlDeclaration = true; + settings.Indent = true; + + writer = XmlWriter.Create(fs, settings); + + //Start the new Root Element + writer.WriteStartElement("dotnetnuke"); + writer.WriteAttributeString("type", "ResourceFile"); + writer.WriteAttributeString("version", "5.0"); + + //Start files Element + writer.WriteStartElement("files"); + + ZipEntry entry = unzip.GetNextEntry(); + while (entry != null) + { + if (!entry.IsDirectory) + { + string fileName = Path.GetFileName(entry.Name); + + //Start file Element + writer.WriteStartElement("file"); + + //Write path + writer.WriteElementString("path", entry.Name.Substring(0, entry.Name.IndexOf(fileName))); + + //Write name + writer.WriteElementString("name", fileName); + + string physicalPath = Path.Combine(PhysicalBasePath, entry.Name); + if (File.Exists(physicalPath)) + { + Util.BackupFile(new InstallFile(entry.Name, Package.InstallerInfo), PhysicalBasePath, Log); + } + Util.WriteStream(unzip, physicalPath); + + //Close files Element + writer.WriteEndElement(); + + Log.AddInfo(string.Format(Util.FILE_Created, entry.Name)); + } + entry = unzip.GetNextEntry(); + } + + //Close files Element + writer.WriteEndElement(); + + Log.AddInfo(Util.FILES_CreatedResources); + } + catch (Exception exc) + { + Logger.Error(exc); + + retValue = false; + } + finally + { + if (writer != null) + { + //Close XmlWriter + writer.Close(); + } + if (fs != null) + { + //Close FileStreams + fs.Close(); + } + if (unzip != null) + { + unzip.Close(); + } + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that determines what type of file this installer supports + /// + /// The type of file being processed + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override bool IsCorrectType(InstallFileType type) + { + return (type == InstallFileType.Resources); + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifestItem method reads a single node + /// + /// The XPathNavigator representing the node + /// Flag that determines whether a check should be made + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override InstallFile ReadManifestItem(XPathNavigator nav, bool checkFileExists) + { + InstallFile insFile = base.ReadManifestItem(nav, checkFileExists); + + _Manifest = Util.ReadElement(nav, "manifest"); + + if (string.IsNullOrEmpty(_Manifest)) + { + _Manifest = insFile.FullName + DEFAULT_MANIFESTEXT; + } + + //Call base method + return base.ReadManifestItem(nav, checkFileExists); + } + + /// ----------------------------------------------------------------------------- + /// + /// The RollbackFile method rolls back the install of a single file. + /// + /// For new installs this removes the added file. For upgrades it restores the + /// backup file created during install + /// The InstallFile to commit + /// + /// [cnurse] 01/18/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void RollbackFile(InstallFile insFile) + { + var unzip = new ZipInputStream(new FileStream(insFile.InstallerInfo.TempInstallFolder + insFile.FullName, FileMode.Open)); + ZipEntry entry = unzip.GetNextEntry(); + while (entry != null) + { + if (!entry.IsDirectory) + { + //Check for Backups + if (File.Exists(insFile.BackupPath + entry.Name)) + { + //Restore File + Util.RestoreFile(new InstallFile(unzip, entry, Package.InstallerInfo), PhysicalBasePath, Log); + } + else + { + //Delete File + Util.DeleteFile(entry.Name, PhysicalBasePath, Log); + } + } + entry = unzip.GetNextEntry(); + } + } + + protected override void UnInstallFile(InstallFile unInstallFile) + { + _Manifest = unInstallFile.Name + ".manifest"; + var doc = new XPathDocument(Path.Combine(PhysicalBasePath, Manifest)); + + foreach (XPathNavigator fileNavigator in doc.CreateNavigator().Select("dotnetnuke/files/file")) + { + string path = XmlUtils.GetNodeValue(fileNavigator, "path"); + string fileName = XmlUtils.GetNodeValue(fileNavigator, "name"); + string filePath = Path.Combine(path, fileName); + try + { + if (DeleteFiles) + { + Util.DeleteFile(filePath, PhysicalBasePath, Log); + } + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + if (DeleteFiles) + { + Util.DeleteFile(Manifest, PhysicalBasePath, Log); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Installers/ScriptInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/ScriptInstaller.cs new file mode 100644 index 00000000000..e8911827af9 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/ScriptInstaller.cs @@ -0,0 +1,449 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Framework.Providers; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ScriptInstaller installs Script Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ScriptInstaller : FileInstaller + { + #region Private Members + + private readonly SortedList _installScripts = new SortedList(); + private readonly SortedList _unInstallScripts = new SortedList(); + private InstallFile _installScript; + private InstallFile _upgradeScript; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the base Install Script (if present) + /// + /// An InstallFile + /// + /// [cnurse] 05/20/2008 created + /// + /// ----------------------------------------------------------------------------- + protected InstallFile InstallScript + { + get + { + return _installScript; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the collection of Install Scripts + /// + /// A List(Of InstallFile) + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected SortedList InstallScripts + { + get + { + return _installScripts; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the collection of UnInstall Scripts + /// + /// A List(Of InstallFile) + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected SortedList UnInstallScripts + { + get + { + return _unInstallScripts; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("scripts") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "scripts"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("script") + /// + /// A String + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "script"; + } + } + + protected ProviderConfiguration ProviderConfiguration + { + get + { + return ProviderConfiguration.GetProviderConfiguration("data"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Upgrade Script (if present) + /// + /// An InstallFile + /// + /// [cnurse] 07/14/2009 created + /// + /// ----------------------------------------------------------------------------- + protected InstallFile UpgradeScript + { + get + { + return _upgradeScript; + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "*dataprovider, sql"; + } + } + + #endregion + + #region Private Methods + + private bool ExecuteSql(InstallFile scriptFile) + { + bool bSuccess = true; + + Log.AddInfo(string.Format(Util.SQL_BeginFile, scriptFile.Name)); + + //read script file for installation + string strScript = FileSystemUtils.ReadFile(PhysicalBasePath + scriptFile.FullName); + + //This check needs to be included because the unicode Byte Order mark results in an extra character at the start of the file + //The extra character - '?' - causes an error with the database. + if (strScript.StartsWith("?")) + { + strScript = strScript.Substring(1); + } + string strSQLExceptions = DataProvider.Instance().ExecuteScript(strScript); + if (!String.IsNullOrEmpty(strSQLExceptions)) + { + if (Package.InstallerInfo.IsLegacyMode) + { + Log.AddWarning(string.Format(Util.SQL_Exceptions, Environment.NewLine, strSQLExceptions)); + } + else + { + Log.AddFailure(string.Format(Util.SQL_Exceptions, Environment.NewLine, strSQLExceptions)); + bSuccess = false; + } + } + Log.AddInfo(string.Format(Util.SQL_EndFile, scriptFile.Name)); + return bSuccess; + } + + private bool IsValidScript(string fileExtension) + { + return ProviderConfiguration.DefaultProvider.ToLower() == fileExtension.ToLower() || fileExtension.ToLower() == "sql"; + } + + #endregion + + #region Protected Methods + + private bool InstallScriptFile(InstallFile scriptFile) + { + //Call base InstallFile method to copy file + bool bSuccess = InstallFile(scriptFile); + + //Process the file if it is an Install Script + var extension = Path.GetExtension(scriptFile.Name.ToLower()); + if (extension != null) + { + string fileExtension = extension.Substring(1); + if (bSuccess && IsValidScript(fileExtension)) + { + Log.AddInfo(Util.SQL_Executing + scriptFile.Name); + bSuccess = ExecuteSql(scriptFile); + } + } + return bSuccess; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that determines what type of file this installer supports + /// + /// The type of file being processed + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override bool IsCorrectType(InstallFileType type) + { + return (type == InstallFileType.Script); + } + + /// ----------------------------------------------------------------------------- + /// + /// The ProcessFile method determines what to do with parsed "file" node + /// + /// The file represented by the node + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void ProcessFile(InstallFile file, XPathNavigator nav) + { + string type = nav.GetAttribute("type", ""); + if (file != null && IsCorrectType(file.Type)) + { + if (file.Name.ToLower().StartsWith("install.")) + { + //This is the initial script when installing + _installScript = file; + } + else if (file.Name.ToLower().StartsWith("upgrade.")) + { + _upgradeScript = file; + } + else if (type.ToLower() == "install") + { + //These are the Install/Upgrade scripts + InstallScripts[file.Version] = file; + } + else + { + //These are the Uninstall scripts + UnInstallScripts[file.Version] = file; + } + } + + //Call base method to set up for file processing + base.ProcessFile(file, nav); + } + + protected override void UnInstallFile(InstallFile scriptFile) + { + //Process the file if it is an UnInstall Script + var extension = Path.GetExtension(scriptFile.Name.ToLower()); + if (extension != null && (UnInstallScripts.ContainsValue(scriptFile) )) + { + string fileExtension = extension.Substring(1); + if (scriptFile.Name.ToLower().StartsWith("uninstall.") && IsValidScript(fileExtension)) + { + //Install Script + Log.AddInfo(Util.SQL_Executing + scriptFile.Name); + ExecuteSql(scriptFile); + } + } + + //Call base method to delete file + base.UnInstallFile(scriptFile); + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Files this is not neccessary + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + base.Commit(); + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the script component + /// + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + Log.AddInfo(Util.SQL_Begin); + try + { + bool bSuccess = true; + Version installedVersion = Package.InstalledVersion; + + //First process InstallScript + if (installedVersion == new Version(0, 0, 0)) + { + if (InstallScript != null) + { + bSuccess = InstallScriptFile(InstallScript); + installedVersion = InstallScript.Version; + } + } + + //Then process remain Install/Upgrade Scripts + if (bSuccess) + { + foreach (InstallFile file in InstallScripts.Values) + { + if (file.Version > installedVersion) + { + bSuccess = InstallScriptFile(file); + if (!bSuccess) + { + break; + } + } + } + } + + //Next process UpgradeScript - this script always runs if present + if (UpgradeScript != null) + { + bSuccess = InstallScriptFile(UpgradeScript); + installedVersion = UpgradeScript.Version; + } + + //Then process uninstallScripts - these need to be copied but not executed + if (bSuccess) + { + foreach (InstallFile file in UnInstallScripts.Values) + { + bSuccess = InstallFile(file); + if (!bSuccess) + { + break; + } + } + } + Completed = bSuccess; + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + Log.AddInfo(Util.SQL_End); + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the script component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + base.Rollback(); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the script component + /// + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + Log.AddInfo(Util.SQL_BeginUnInstall); + + //Call the base method + base.UnInstall(); + + Log.AddInfo(Util.SQL_EndUnInstall); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/SkinControlInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/SkinControlInstaller.cs new file mode 100644 index 00000000000..18a3c2d17eb --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/SkinControlInstaller.cs @@ -0,0 +1,211 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinControlInstaller installs SkinControl (SkinObject) Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public class SkinControlInstaller : ComponentInstallerBase + { + #region "Private Properties" + + private SkinControlInfo InstalledSkinControl; + private SkinControlInfo SkinControl; + + #endregion + + #region "Public Properties" + + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ascx, vb, cs, js, resx, xml, vbproj, csproj, sln"; + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteSkinControl method deletes the SkinControl from the data Store. + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + private void DeleteSkinControl() + { + try + { + //Attempt to get the SkinControl + SkinControlInfo skinControl = SkinControlController.GetSkinControlByPackageID(Package.PackageID); + if (skinControl != null) + { + SkinControlController.DeleteSkinControl(skinControl); + } + Log.AddInfo(string.Format(Util.MODULE_UnRegistered, skinControl.ControlKey)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// In the case of Modules this is not neccessary + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the Module component + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + //Attempt to get the SkinControl + InstalledSkinControl = SkinControlController.GetSkinControlByKey(SkinControl.ControlKey); + + if (InstalledSkinControl != null) + { + SkinControl.SkinControlID = InstalledSkinControl.SkinControlID; + } + + //Save SkinControl + SkinControl.PackageID = Package.PackageID; + SkinControl.SkinControlID = SkinControlController.SaveSkinControl(SkinControl); + + Completed = true; + Log.AddInfo(string.Format(Util.MODULE_Registered, SkinControl.ControlKey)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the SkinControl compoent. + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + //Load the SkinControl from the manifest + SkinControl = CBO.DeserializeObject(new StringReader(manifestNav.InnerXml)); + + if (Log.Valid) + { + Log.AddInfo(Util.MODULE_ReadSuccess); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp SkinControl exists then we need to update the DataStore with this + if (InstalledSkinControl == null) + { + //No Temp SkinControl - Delete newly added SkinControl + DeleteSkinControl(); + } + else + { + //Temp SkinControl - Rollback to Temp + SkinControlController.SaveSkinControl(InstalledSkinControl); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the SkinControl component + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteSkinControl(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/SkinInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/SkinInstaller.cs new file mode 100644 index 00000000000..cdbe8fddb9e --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/SkinInstaller.cs @@ -0,0 +1,476 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinInstaller installs Skin Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + public class SkinInstaller : FileInstaller + { + #region "Private Members" + + private readonly ArrayList _SkinFiles = new ArrayList(); + + private SkinPackageInfo SkinPackage; + private SkinPackageInfo TempSkinPackage; + private string _SkinName = Null.NullString; + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("skinFiles") + /// + /// A String + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "skinFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("skinFile") + /// + /// A String + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "skinFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PhysicalBasePath for the skin files + /// + /// A String + /// + /// [cnurse] 07/25/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override string PhysicalBasePath + { + get + { + string _PhysicalBasePath = RootPath + SkinRoot + "\\" + SkinPackage.SkinName; + if (!_PhysicalBasePath.EndsWith("\\")) + { + _PhysicalBasePath += "\\"; + } + return _PhysicalBasePath.Replace("/", "\\"); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the root folder for the Skin + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected string RootPath + { + get + { + string _RootPath = Null.NullString; + if (Package.InstallerInfo.PortalID == Null.NullInteger) + { + _RootPath = Globals.HostMapPath; + } + else + { + _RootPath = PortalController.GetCurrentPortalSettings().HomeDirectoryMapPath; + } + return _RootPath; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the collection of Skin Files + /// + /// A List(Of InstallFile) + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ArrayList SkinFiles + { + get + { + return _SkinFiles; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the SkinName Node ("skinName") + /// + /// A String + /// + /// [cnurse] 08/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string SkinNameNodeName + { + get + { + return "skinName"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the RootName of the Skin + /// + /// A String + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string SkinRoot + { + get + { + return SkinController.RootSkin; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Type of the Skin + /// + /// A String + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string SkinType + { + get + { + return "Skin"; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ascx, html, htm, css, xml, js, resx, jpg, jpeg, gif, png"; + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteSkinPackage method deletes the Skin Package + /// from the data Store. + /// + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + private void DeleteSkinPackage() + { + try + { + //Attempt to get the Authentication Service + SkinPackageInfo skinPackage = SkinController.GetSkinByPackageID(Package.PackageID); + if (skinPackage != null) + { + SkinController.DeleteSkinPackage(skinPackage); + } + Log.AddInfo(string.Format(Util.SKIN_UnRegistered, skinPackage.SkinName)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The ProcessFile method determines what to do with parsed "file" node + /// + /// The file represented by the node + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void ProcessFile(InstallFile file, XPathNavigator nav) + { + switch (file.Extension) + { + case "htm": + case "html": + case "ascx": + case "css": + if (file.Path.ToLower().IndexOf(Globals.glbAboutPage.ToLower()) < 0) + { + SkinFiles.Add(PhysicalBasePath + file.FullName); + } + break; + } + + //Call base method to set up for file processing + base.ProcessFile(file, nav); + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadCustomManifest method reads the custom manifest items + /// + /// The XPathNavigator representing the node + /// + /// [cnurse] 08/22/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void ReadCustomManifest(XPathNavigator nav) + { + SkinPackage = new SkinPackageInfo(); + SkinPackage.PortalID = Package.PortalID; + + //Get the Skin name + SkinPackage.SkinName = Util.ReadElement(nav, SkinNameNodeName); + + //Call base class + base.ReadCustomManifest(nav); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstallFile method unInstalls a single file. + /// + /// The InstallFile to unInstall. + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void UnInstallFile(InstallFile unInstallFile) + { + //Uninstall file + base.UnInstallFile(unInstallFile); + + if (unInstallFile.Extension == "htm" || unInstallFile.Extension == "html") + { + //Try to remove "processed file" + string fileName = unInstallFile.FullName; + fileName = fileName.Replace(Path.GetExtension(fileName), ".ascx"); + Util.DeleteFile(fileName, PhysicalBasePath, Log); + } + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the skin component + /// + /// + /// [cnurse] 02/06/2008 created + /// + public override void Install() + { + bool bAdd = Null.NullBoolean; + try + { + //Attempt to get the Skin Package + TempSkinPackage = SkinController.GetSkinPackage(SkinPackage.PortalID, SkinPackage.SkinName, SkinType); + if (TempSkinPackage == null) + { + bAdd = true; + SkinPackage.PackageID = Package.PackageID; + } + else + { + SkinPackage.SkinPackageID = TempSkinPackage.SkinPackageID; + if (TempSkinPackage.PackageID != Package.PackageID) + { + Completed = false; + Log.AddFailure(Util.SKIN_Installed); + return; + } + else + { + SkinPackage.PackageID = TempSkinPackage.PackageID; + } + } + SkinPackage.SkinType = SkinType; + if (bAdd) + { + //Add new skin package + SkinPackage.SkinPackageID = SkinController.AddSkinPackage(SkinPackage); + } + else + { + //Update skin package + SkinController.UpdateSkinPackage(SkinPackage); + } + Log.AddInfo(string.Format(Util.SKIN_Registered, SkinPackage.SkinName)); + + //install (copy the files) by calling the base class + base.Install(); + + //process the list of skin files + if (SkinFiles.Count > 0) + { + Log.StartJob(Util.SKIN_BeginProcessing); + string strMessage = Null.NullString; + var NewSkin = new SkinFileProcessor(RootPath, SkinRoot, SkinPackage.SkinName); + foreach (string skinFile in SkinFiles) + { + strMessage += NewSkin.ProcessFile(skinFile, SkinParser.Portable); + skinFile.Replace(Globals.HostMapPath + "\\", "[G]"); + switch (Path.GetExtension(skinFile)) + { + case ".htm": + SkinController.AddSkin(SkinPackage.SkinPackageID, skinFile.Replace("htm", "ascx")); + break; + case ".html": + SkinController.AddSkin(SkinPackage.SkinPackageID, skinFile.Replace("html", "ascx")); + break; + case ".ascx": + SkinController.AddSkin(SkinPackage.SkinPackageID, skinFile); + break; + } + } + Array arrMessage = strMessage.Split(new[] {"
    "}, StringSplitOptions.None); + foreach (string strRow in arrMessage) + { + Log.AddInfo(HtmlUtils.StripTags(strRow, true)); + } + Log.EndJob(Util.SKIN_EndProcessing); + } + Completed = true; + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp Skin exists then we need to update the DataStore with this + if (TempSkinPackage == null) + { + //No Temp Skin - Delete newly added Skin + DeleteSkinPackage(); + } + else + { + //Temp Skin - Rollback to Temp + SkinController.UpdateSkinPackage(TempSkinPackage); + } + + //Call base class to prcoess files + base.Rollback(); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the skin component + /// + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteSkinPackage(); + + //Call base class to prcoess files + base.UnInstall(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/UrlProviderInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/UrlProviderInstaller.cs new file mode 100644 index 00000000000..155932c7d0b --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/UrlProviderInstaller.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.EventQueue; + +namespace DotNetNuke.Services.Installer.Installers +{ + class UrlProviderInstaller : ComponentInstallerBase + { + private ExtensionUrlProviderInfo _extensionUrlProvider; + private ExtensionUrlProviderInfo _installedExtensionUrlProvider; + private string _desktopModuleName; + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "ashx, aspx, ascx, vb, cs, resx, css, js, resources, config, vbproj, csproj, sln, htm, html"; + } + } + + #endregion + + + private void DeleteProvider() + { + try + { + //Attempt to get the Desktop Module + //Attempt to get the Desktop Module + DesktopModuleInfo desktopModule = DesktopModuleController.GetDesktopModuleByPackageID(Package.PackageID); + + ExtensionUrlProviderInfo tempUrlProvider = ExtensionUrlProviderController.GetProviders(Null.NullInteger) + .SingleOrDefault(p => p.DesktopModuleId == desktopModule.DesktopModuleID); + if (tempUrlProvider != null) + { + ExtensionUrlProviderController.DeleteProvider(tempUrlProvider); + + Log.AddInfo(string.Format(Util.URLPROVIDER_UnRegistered, tempUrlProvider.ProviderName)); + } + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// The Commit method finalises the Install and commits any pending changes. + /// + /// ----------------------------------------------------------------------------- + public override void Commit() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// The Install method installs the UrlProvider component + /// + /// ----------------------------------------------------------------------------- + public override void Install() + { + try + { + //Ensure DesktopModule Cache is cleared + DataCache.RemoveCache(String.Format(DataCache.DesktopModuleCacheKey, Null.NullInteger)); + + var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(_desktopModuleName, Null.NullInteger); + if (desktopModule != null) + { + _extensionUrlProvider.DesktopModuleId = desktopModule.DesktopModuleID; + } + + //Attempt to get the Desktop Module + _installedExtensionUrlProvider = ExtensionUrlProviderController.GetProviders(Null.NullInteger) + .SingleOrDefault(p => p.ProviderType == _extensionUrlProvider.ProviderType); + + if (_installedExtensionUrlProvider != null) + { + _extensionUrlProvider.ExtensionUrlProviderId = _installedExtensionUrlProvider.ExtensionUrlProviderId; + } + + ExtensionUrlProviderController.SaveProvider(_extensionUrlProvider); + + Completed = true; + Log.AddInfo(string.Format(Util.URLPROVIDER_Registered, _extensionUrlProvider.ProviderName)); + } + catch (Exception ex) + { + Log.AddFailure(ex); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ReadManifest method reads the manifest file for the compoent. + /// + /// ----------------------------------------------------------------------------- + public override void ReadManifest(XPathNavigator manifestNav) + { + _extensionUrlProvider = new ExtensionUrlProviderInfo + { + ProviderName = Util.ReadElement(manifestNav, "urlProvider/name", Log, Util.URLPROVIDER_NameMissing), + ProviderType = Util.ReadElement(manifestNav, "urlProvider/type", Log, Util.URLPROVIDER_TypeMissing), + SettingsControlSrc = Util.ReadElement(manifestNav, "urlProvider/settingsControlSrc"), + IsActive = true, + RedirectAllUrls = Convert.ToBoolean(Util.ReadElement(manifestNav, "urlProvider/redirectAllUrls", "false")), + ReplaceAllUrls = Convert.ToBoolean(Util.ReadElement(manifestNav, "urlProvider/replaceAllUrls", "false")), + RewriteAllUrls = Convert.ToBoolean(Util.ReadElement(manifestNav, "urlProvider/rewriteAllUrls", "false")) + }; + + _desktopModuleName = Util.ReadElement(manifestNav, "urlProvider/desktopModule"); + if (Log.Valid) + { + Log.AddInfo(Util.URLPROVIDER_ReadSuccess); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The Rollback method undoes the installation of the component in the event + /// that one of the other components fails + /// + /// ----------------------------------------------------------------------------- + public override void Rollback() + { + //If Temp Provider exists then we need to update the DataStore with this + if (_installedExtensionUrlProvider == null) + { + //No Temp Provider - Delete newly added module + DeleteProvider(); + } + else + { + //Temp Provider - Rollback to Temp + ExtensionUrlProviderController.SaveProvider(_installedExtensionUrlProvider); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstall method uninstalls the component + /// + /// ----------------------------------------------------------------------------- + public override void UnInstall() + { + DeleteProvider(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Installers/WidgetInstaller.cs b/DNN Platform/Library/Services/Installer/Installers/WidgetInstaller.cs new file mode 100644 index 00000000000..f6715ad930d --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Installers/WidgetInstaller.cs @@ -0,0 +1,112 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; + +using DotNetNuke.Common; + +#endregion + +namespace DotNetNuke.Services.Installer.Installers +{ + /// ----------------------------------------------------------------------------- + /// + /// The WidgetInstaller installs Widget Components to a DotNetNuke site + /// + /// + /// + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + public class WidgetInstaller : FileInstaller + { + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("widgetFiles") + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "widgetFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("widgetFiles") + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "widgetFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PhysicalBasePath for the widget files + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string PhysicalBasePath + { + get + { + string widgetPath = Path.Combine("Resources\\Widgets\\User", BasePath); + return Path.Combine(Globals.ApplicationMapPath, widgetPath); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of allowable file extensions (in addition to the Host's List) + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + public override string AllowableFiles + { + get + { + return "js"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/LegacyUtil.cs b/DNN Platform/Library/Services/Installer/LegacyUtil.cs new file mode 100644 index 00000000000..3e0d300ae05 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/LegacyUtil.cs @@ -0,0 +1,509 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Installer.Writers; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + /// ----------------------------------------------------------------------------- + /// + /// The LegacyUtil class is a Utility class that provides helper methods to transfer + /// legacy packages to Cambrian's Universal Installer based system + /// + /// + /// + /// + /// [cnurse] 01/23/2008 created + /// + /// ----------------------------------------------------------------------------- + public class LegacyUtil + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (LegacyUtil)); + private static string AdminModules = + "Adsense, MarketShare, Authentication, Banners, FeedExplorer, FileManager, HostSettings, Lists, LogViewer, Newsletters, PortalAliases, Portals, RecycleBin, Scheduler, SearchAdmin, SearchInput, SearchResults, Security, SiteLog, SiteWizard, SkinDesigner, Solutions, SQL, Tabs, Vendors,"; + + private static string CoreModules = + "DNN_Announcements, Blog, DNN_Documents, DNN_Events, DNN_FAQs, DNN_Feedback, DNN_Forum, Help, DNN_HTML, DNN_IFrame, DNN_Links, DNN_Media, DNN_NewsFeeds, DNN_Reports, Repository, Repository Dashboard, Store Admin, Store Account, Store Catalog, Store Mini Cart, Store Menu, DNN_Survey, DNN_UserDefinedTable, DNN_UsersOnline, Wiki, DNN_XML,"; + + private static string KnownSkinObjects = + "ACTIONBUTTON, ACTIONS, BANNER, BREADCRUMB, COPYRIGHT, CURRENTDATE, DOTNETNUKE, DROPDOWNACTIONS, HELP, HOSTNAME, ICON, LANGUAGE, LINKACTIONS, LINKS, LOGIN, LOGO, MENU, NAV, PRINTMODULE, PRIVACY, SEARCH, SIGNIN, SOLPARTACTIONS, SOLPARTMENU, STYLES, TERMS, TEXT, TITLE, TREEVIEW, USER, VISIBILITY,"; + + private static string KnownSkins = "DNN-Blue, DNN-Gray, MinimalExtropy,"; + + private static PackageInfo CreateSkinPackage(SkinPackageInfo skin) + { + //Create a Package + var package = new PackageInfo(new InstallerInfo()); + package.Name = skin.SkinName; + package.FriendlyName = skin.SkinName; + package.Description = Null.NullString; + package.Version = new Version(1, 0, 0); + package.PackageType = skin.SkinType; + package.License = Util.PACKAGE_NoLicense; + + //See if the Skin is using a Namespace (or is a known skin) + ParsePackageName(package); + + return package; + } + + private static void CreateSkinManifest(XmlWriter writer, string skinFolder, string skinType, string tempInstallFolder, string subFolder) + { + string skinName = Path.GetFileNameWithoutExtension(skinFolder); + var skin = new SkinPackageInfo(); + skin.SkinName = skinName; + skin.SkinType = skinType; + + //Create a Package + PackageInfo package = CreateSkinPackage(skin); + + //Create a SkinPackageWriter + var skinWriter = new SkinPackageWriter(skin, package, tempInstallFolder, subFolder); + skinWriter.GetFiles(false); + + //We need to reset the BasePath so it using the correct basePath rather than the Temp InstallFolder + skinWriter.SetBasePath(); + + //Writer package manifest fragment to writer + skinWriter.WriteManifest(writer, true); + } + + private static void ProcessLegacySkin(string skinFolder, string skinType) + { + string skinName = Path.GetFileName(skinFolder); + if (skinName != "_default") + { + var skin = new SkinPackageInfo(); + skin.SkinName = skinName; + skin.SkinType = skinType; + + //Create a Package + PackageInfo package = CreateSkinPackage(skin); + + //Create a SkinPackageWriter + var skinWriter = new SkinPackageWriter(skin, package); + skinWriter.GetFiles(false); + + //Save the manifest + package.Manifest = skinWriter.WriteManifest(true); + + //Save Package + PackageController.SavePackage(package); + + //Update Skin Package with new PackageID + skin.PackageID = package.PackageID; + + //Save Skin Package + skin.SkinPackageID = SkinController.AddSkinPackage(skin); + + foreach (InstallFile skinFile in skinWriter.Files.Values) + { + if (skinFile.Type == InstallFileType.Ascx) + { + if (skinType == "Skin") + { + SkinController.AddSkin(skin.SkinPackageID, Path.Combine("[G]" + SkinController.RootSkin, Path.Combine(skin.SkinName, skinFile.FullName))); + } + else + { + SkinController.AddSkin(skin.SkinPackageID, Path.Combine("[G]" + SkinController.RootContainer, Path.Combine(skin.SkinName, skinFile.FullName))); + } + } + } + } + } + + private static void ParsePackageName(PackageInfo package, string separator) + { + //See if the Module is using a "Namespace" for its name + int ownerIndex = package.Name.IndexOf(separator); + if (ownerIndex > 0) + { + package.Owner = package.Name.Substring(0, ownerIndex); + } + } + + public static string CreateSkinManifest(string skinFolder, string skinType, string tempInstallFolder) + { + //Test if there are Skins and Containers folders in TempInstallFolder (ie it is a legacy combi package) + bool isCombi = false; + var installFolder = new DirectoryInfo(tempInstallFolder); + DirectoryInfo[] subFolders = installFolder.GetDirectories(); + if (subFolders.Length > 0) + { + if ((subFolders[0].Name.ToLowerInvariant() == "containers" || subFolders[0].Name.ToLowerInvariant() == "skins")) + { + isCombi = true; + } + } + + //Create a writer to create the processed manifest + var sb = new StringBuilder(); + XmlWriter writer = XmlWriter.Create(sb, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)); + PackageWriterBase.WriteManifestStartElement(writer); + if (isCombi) + { + if (Directory.Exists(Path.Combine(tempInstallFolder, "Skins"))) + { + //Add Skin Package Fragment + CreateSkinManifest(writer, skinFolder, "Skin", tempInstallFolder.Replace(Globals.ApplicationMapPath + "\\", ""), "Skins"); + } + if (Directory.Exists(Path.Combine(tempInstallFolder, "Containers"))) + { + //Add Container PAckage Fragment + CreateSkinManifest(writer, skinFolder, "Container", tempInstallFolder.Replace(Globals.ApplicationMapPath + "\\", ""), "Containers"); + } + } + else + { + //Add Package Fragment + CreateSkinManifest(writer, skinFolder, skinType, tempInstallFolder.Replace(Globals.ApplicationMapPath + "\\", ""), ""); + } + PackageWriterBase.WriteManifestEndElement(writer); + + //Close XmlWriter + writer.Close(); + + //Return new manifest + return sb.ToString(); + } + + public static void ParsePackageName(PackageInfo package) + { + ParsePackageName(package, "."); + if (string.IsNullOrEmpty(package.Owner)) + { + ParsePackageName(package, "\\"); + } + if (string.IsNullOrEmpty(package.Owner)) + { + ParsePackageName(package, "_"); + } + if (package.PackageType == "Module" && AdminModules.Contains(package.Name + ",") || package.PackageType == "Module" && CoreModules.Contains(package.Name + ",") || + (package.PackageType == "Container" || package.PackageType == "Skin") && KnownSkins.Contains(package.Name + ",") || + package.PackageType == "SkinObject" && KnownSkinObjects.Contains(package.Name + ",")) + { + if (string.IsNullOrEmpty(package.Owner)) + { + package.Owner = "DotNetNuke"; + package.Name = "DotNetNuke." + package.Name; + switch (package.PackageType) + { + case "Skin": + package.Name += ".Skin"; + package.FriendlyName += " Skin"; + break; + case "Container": + package.Name += ".Container"; + package.FriendlyName += " Container"; + break; + case "SkinObject": + package.Name += "SkinObject"; + package.FriendlyName += " SkinObject"; + break; + } + } + } + if (package.Owner == "DotNetNuke") + { + package.License = Localization.Localization.GetString("License", Localization.Localization.GlobalResourceFile); + package.Organization = "DotNetNuke Corporation"; + package.Url = "www.dotnetnuke.com"; + package.Email = "support@dotnetnuke.com"; + package.ReleaseNotes = "There are no release notes for this version."; + } + else + { + package.License = Util.PACKAGE_NoLicense; + } + } + + public static void ProcessLegacyLanguages() + { + string filePath = Globals.ApplicationMapPath + Localization.Localization.SupportedLocalesFile.Substring(1).Replace("/", "\\"); + if (File.Exists(filePath)) + { + var doc = new XPathDocument(filePath); + + //Check for Browser and Url settings + XPathNavigator browserNav = doc.CreateNavigator().SelectSingleNode("root/browserDetection"); + if (browserNav != null) + { + HostController.Instance.Update("EnableBrowserLanguage", Util.ReadAttribute(browserNav, "enabled", false, null, Null.NullString, "true")); + } + XPathNavigator urlNav = doc.CreateNavigator().SelectSingleNode("root/languageInUrl"); + if (urlNav != null) + { + HostController.Instance.Update("EnableUrlLanguage", Util.ReadAttribute(urlNav, "enabled", false, null, Null.NullString, "true")); + } + + //Process each language + foreach (XPathNavigator nav in doc.CreateNavigator().Select("root/language")) + { + if (nav.NodeType != XPathNodeType.Comment) + { + var language = new Locale(); + language.Text = Util.ReadAttribute(nav, "name"); + language.Code = Util.ReadAttribute(nav, "key"); + language.Fallback = Util.ReadAttribute(nav, "fallback"); + //Save Language + Localization.Localization.SaveLanguage(language); + if (language.Code != Localization.Localization.SystemLocale) + { + //Create a Package + var package = new PackageInfo(new InstallerInfo()); + package.Name = language.Text; + package.FriendlyName = language.Text; + package.Description = Null.NullString; + package.Version = new Version(1, 0, 0); + package.PackageType = "CoreLanguagePack"; + package.License = Util.PACKAGE_NoLicense; + + //Create a LanguagePackWriter + var packageWriter = new LanguagePackWriter(language, package); + + //Save the manifest + package.Manifest = packageWriter.WriteManifest(true); + + //Save Package + PackageController.SavePackage(package); + + var languagePack = new LanguagePackInfo(); + languagePack.LanguageID = language.LanguageId; + languagePack.PackageID = package.PackageID; + languagePack.DependentPackageID = -2; + LanguagePackController.SaveLanguagePack(languagePack); + } + } + } + } + + //Process Portal Locales files + foreach (PortalInfo portal in new PortalController().GetPortals()) + { + int portalID = portal.PortalID; + filePath = string.Format(Globals.ApplicationMapPath + Localization.Localization.ApplicationResourceDirectory.Substring(1).Replace("/", "\\") + "\\Locales.Portal-{0}.xml", portalID); + + if (File.Exists(filePath)) + { + var doc = new XPathDocument(filePath); + + //Check for Browser and Url settings + XPathNavigator browserNav = doc.CreateNavigator().SelectSingleNode("locales/browserDetection"); + if (browserNav != null) + { + PortalController.UpdatePortalSetting(portalID, "EnableBrowserLanguage", Util.ReadAttribute(browserNav, "enabled", false, null, Null.NullString, "true")); + } + XPathNavigator urlNav = doc.CreateNavigator().SelectSingleNode("locales/languageInUrl"); + if (urlNav != null) + { + PortalController.UpdatePortalSetting(portalID, "EnableUrlLanguage", Util.ReadAttribute(urlNav, "enabled", false, null, Null.NullString, "true")); + } + foreach (Locale installedLanguage in LocaleController.Instance.GetLocales(Null.NullInteger).Values) + { + string code = installedLanguage.Code; + bool bFound = false; + + //Check if this language is "inactive" + foreach (XPathNavigator inactiveNav in doc.CreateNavigator().Select("locales/inactive/locale")) + { + if (inactiveNav.Value == code) + { + bFound = true; + break; + } + } + if (!bFound) + { + //Language is enabled - add to portal + Localization.Localization.AddLanguageToPortal(portalID, installedLanguage.LanguageId, false); + } + } + } + else + { + foreach (Locale installedLanguage in LocaleController.Instance.GetLocales(Null.NullInteger).Values) + { + //Language is enabled - add to portal + Localization.Localization.AddLanguageToPortal(portalID, installedLanguage.LanguageId, false); + } + } + } + } + + public static void ProcessLegacyModule(DesktopModuleInfo desktopModule) + { + //Get the Module folder + string moduleFolder = Path.Combine(Globals.ApplicationMapPath, Path.Combine("DesktopModules", desktopModule.FolderName)); + + //Find legacy manifest + XPathNavigator rootNav = null; + try + { + string hostModules = "Portals, SQL, HostSettings, Scheduler, SearchAdmin, Lists, SkinDesigner, Extensions"; + string[] files = Directory.GetFiles(moduleFolder, "*.dnn.config"); + if (files.Length > 0) + { + //Create an XPathDocument from the Xml + var doc = new XPathDocument(new FileStream(files[0], FileMode.Open, FileAccess.Read)); + rootNav = doc.CreateNavigator().SelectSingleNode("dotnetnuke"); + } + + //Module is not affiliated with a Package + var package = new PackageInfo(new InstallerInfo()); + package.Name = desktopModule.ModuleName; + + package.FriendlyName = desktopModule.FriendlyName; + package.Description = desktopModule.Description; + package.Version = new Version(1, 0, 0); + if (!string.IsNullOrEmpty(desktopModule.Version)) + { + package.Version = new Version(desktopModule.Version); + } + if (hostModules.Contains(desktopModule.ModuleName)) + { + //Host Module so make this a system package + package.IsSystemPackage = true; + desktopModule.IsAdmin = true; + } + else + { + desktopModule.IsAdmin = false; + } + package.PackageType = "Module"; + + //See if the Module is using a "Namespace" for its name + ParsePackageName(package); + + if (files.Length > 0) + { + var modulewriter = new ModulePackageWriter(desktopModule, rootNav, package); + package.Manifest = modulewriter.WriteManifest(true); + } + else + { + package.Manifest = ""; //module has no manifest + } + + //Save Package + PackageController.SavePackage(package); + + //Update Desktop Module with new PackageID + desktopModule.PackageID = package.PackageID; + + //Save DesktopModule + DesktopModuleController.SaveDesktopModule(desktopModule, false, false); + } + catch (Exception exc) + { + Logger.Error(exc); + + } + } + + public static void ProcessLegacyModules() + { + foreach (DesktopModuleInfo desktopModule in DesktopModuleController.GetDesktopModules(Null.NullInteger).Values) + { + if (desktopModule.PackageID == Null.NullInteger) + { + ProcessLegacyModule(desktopModule); + } + } + } + + public static void ProcessLegacySkinControls() + { + foreach (SkinControlInfo skinControl in SkinControlController.GetSkinControls().Values) + { + if (skinControl.PackageID == Null.NullInteger) + { + try + { + //SkinControl is not affiliated with a Package + var package = new PackageInfo(new InstallerInfo()); + package.Name = skinControl.ControlKey; + + package.FriendlyName = skinControl.ControlKey; + package.Description = Null.NullString; + package.Version = new Version(1, 0, 0); + package.PackageType = "SkinObject"; + + //See if the SkinControl is using a "Namespace" for its name + ParsePackageName(package); + + var skinControlWriter = new SkinControlPackageWriter(skinControl, package); + package.Manifest = skinControlWriter.WriteManifest(true); + + //Save Package + PackageController.SavePackage(package); + + //Update SkinControl with new PackageID + skinControl.PackageID = package.PackageID; + + //Save SkinControl + SkinControlController.SaveSkinControl(skinControl); + } + catch (Exception exc) + { + Logger.Error(exc); + + } + } + } + } + + public static void ProcessLegacySkins() + { + //Process Legacy Skins + string skinRootPath = Path.Combine(Globals.HostMapPath, SkinController.RootSkin); + foreach (string skinFolder in Directory.GetDirectories(skinRootPath)) + { + ProcessLegacySkin(skinFolder, "Skin"); + } + + //Process Legacy Containers + skinRootPath = Path.Combine(Globals.HostMapPath, SkinController.RootContainer); + foreach (string skinFolder in Directory.GetDirectories(skinRootPath)) + { + ProcessLegacySkin(skinFolder, "Container"); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Log/LogEntry.cs b/DNN Platform/Library/Services/Installer/Log/LogEntry.cs new file mode 100644 index 00000000000..55c95a393ce --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Log/LogEntry.cs @@ -0,0 +1,100 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Installer.Log +{ + /// ----------------------------------------------------------------------------- + /// + /// The LogEntry class provides a single entry for the Installer Log + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class LogEntry + { + private readonly string _description; + + /// ----------------------------------------------------------------------------- + /// + /// This Constructor builds a LogEntry from its type and description + /// + /// + /// + /// The description (detail) of the entry + /// The type of LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public LogEntry(LogType type, string description) + { + Type = type; + _description = description; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the type of LogEntry + /// + /// A LogType + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public LogType Type { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the description of LogEntry + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Description + { + get + { + if (_description == null) + { + return "..."; + } + + return _description; + } + } + + public override string ToString() + { + return string.Format("{0}: {1}", Type, Description); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Log/LogType.cs b/DNN Platform/Library/Services/Installer/Log/LogType.cs new file mode 100644 index 00000000000..ea425e53ed5 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Log/LogType.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer.Log +{ + public enum LogType + { + Info, + Warning, + Failure, + StartJob, + EndJob + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Log/Logger.cs b/DNN Platform/Library/Services/Installer/Log/Logger.cs new file mode 100644 index 00000000000..30acc43b7b4 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Log/Logger.cs @@ -0,0 +1,329 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Web.UI.HtmlControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Installer.Log +{ + /// ----------------------------------------------------------------------------- + /// + /// The Logger class provides an Installer Log + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class Logger + { + private static readonly ILog DnnLogger = LoggerSource.Instance.GetLogger(typeof (Logger)); + private readonly IList _logs; + private string _errorClass; + private bool _hasWarnings; + private string _highlightClass; + private string _normalClass; + private bool _valid; + + public Logger() + { + _logs = new LoggedCollection(); + + _valid = true; + _hasWarnings = Null.NullBoolean; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Css Class used for Error Log Entries + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ErrorClass + { + get + { + if (String.IsNullOrEmpty(_errorClass)) + { + _errorClass = "NormalRed"; + } + return _errorClass; + } + set + { + _errorClass = value; + } + } + + public bool HasWarnings + { + get + { + return _hasWarnings; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Css Class used for Log Entries that should be highlighted + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string HighlightClass + { + get + { + if (String.IsNullOrEmpty(_highlightClass)) + { + _highlightClass = "NormalBold"; + } + return _highlightClass; + } + set + { + _highlightClass = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a List of Log Entries + /// + /// A List of LogEntrys + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public IList Logs + { + get + { + return _logs; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Css Class used for normal Log Entries + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string NormalClass + { + get + { + if (String.IsNullOrEmpty(_normalClass)) + { + _normalClass = "Normal"; + } + return _normalClass; + } + set + { + _normalClass = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Flag that indicates whether the Installation was Valid + /// + /// A List of LogEntrys + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public bool Valid + { + get + { + return _valid; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The AddFailure method adds a new LogEntry of type Failure to the Logs collection + /// + /// This method also sets the Valid flag to false + /// The description of the LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void AddFailure(string failure) + { + _logs.Add(new LogEntry(LogType.Failure, failure)); + _valid = false; + } + + public void AddFailure(Exception ex) + { + AddFailure((Util.EXCEPTION + ex)); + Exceptions.Exceptions.LogException(ex); + } + + /// ----------------------------------------------------------------------------- + /// + /// The AddInfo method adds a new LogEntry of type Info to the Logs collection + /// + /// The description of the LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void AddInfo(string info) + { + _logs.Add(new LogEntry(LogType.Info, info)); + DnnLogger.Info(info); + } + + /// ----------------------------------------------------------------------------- + /// + /// The AddWarning method adds a new LogEntry of type Warning to the Logs collection + /// + /// The description of the LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void AddWarning(string warning) + { + _logs.Add(new LogEntry(LogType.Warning, warning)); + DnnLogger.Warn(warning); + _hasWarnings = true; + } + + /// ----------------------------------------------------------------------------- + /// + /// The EndJob method adds a new LogEntry of type EndJob to the Logs collection + /// + /// The description of the LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void EndJob(string job) + { + _logs.Add(new LogEntry(LogType.EndJob, job)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetLogsTable formats log entries in an HtmlTable + /// + /// + /// [jbrinkman] 24/11/2004 Created new method. Moved from WebUpload.ascx.vb + /// + /// ----------------------------------------------------------------------------- + public HtmlTable GetLogsTable() + { + var arrayTable = new HtmlTable(); + foreach (LogEntry entry in Logs) + { + var tr = new HtmlTableRow(); + var tdType = new HtmlTableCell(); + tdType.InnerText = Util.GetLocalizedString("LOG.PALogger." + entry.Type); + var tdDescription = new HtmlTableCell(); + tdDescription.InnerText = entry.Description; + tr.Cells.Add(tdType); + tr.Cells.Add(tdDescription); + switch (entry.Type) + { + case LogType.Failure: + case LogType.Warning: + tdType.Attributes.Add("class", ErrorClass); + tdDescription.Attributes.Add("class", ErrorClass); + break; + case LogType.StartJob: + case LogType.EndJob: + tdType.Attributes.Add("class", HighlightClass); + tdDescription.Attributes.Add("class", HighlightClass); + break; + case LogType.Info: + tdType.Attributes.Add("class", NormalClass); + tdDescription.Attributes.Add("class", NormalClass); + break; + } + arrayTable.Rows.Add(tr); + if (entry.Type == LogType.EndJob) + { + var spaceTR = new HtmlTableRow(); + spaceTR.Cells.Add(new HtmlTableCell {ColSpan = 2, InnerHtml = " "}); + arrayTable.Rows.Add(spaceTR); + } + } + return arrayTable; + } + + public void ResetFlags() + { + _valid = true; + } + + /// ----------------------------------------------------------------------------- + /// + /// The StartJob method adds a new LogEntry of type StartJob to the Logs collection + /// + /// The description of the LogEntry + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public void StartJob(string job) + { + _logs.Add(new LogEntry(LogType.StartJob, job)); + } + + class LoggedCollection : Collection + { + protected override void InsertItem(int index, LogEntry item) + { + DnnLogger.Debug(item.ToString()); + base.InsertItem(index, item); + } + + protected override void SetItem(int index, LogEntry item) + { + DnnLogger.Debug(item.ToString()); + base.InsertItem(index, item); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/NodeInsertType.cs b/DNN Platform/Library/Services/Installer/NodeInsertType.cs new file mode 100644 index 00000000000..c41221138be --- /dev/null +++ b/DNN Platform/Library/Services/Installer/NodeInsertType.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer +{ + public enum NodeInsertType + { + Before, + After + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Packages/IPackageEditor.cs b/DNN Platform/Library/Services/Installer/Packages/IPackageEditor.cs new file mode 100644 index 00000000000..aca7dac180a --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/IPackageEditor.cs @@ -0,0 +1,32 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer.Packages +{ + public interface IPackageEditor + { + int PackageID { get; set; } + bool IsWizard { get; set; } + + void Initialize(); + + void UpdatePackage(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageController.cs b/DNN Platform/Library/Services/Installer/Packages/PackageController.cs new file mode 100644 index 00000000000..356346cf544 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageController.cs @@ -0,0 +1,364 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Authentication; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageController class provides the business class for the packages + /// + /// + /// + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public class PackageController + { + #region "Private Members" + + private static readonly DataProvider provider = DataProvider.Instance(); + + #endregion + + #region "Public Shared Methods" + + public static int AddPackage(PackageInfo package, bool includeDetail) + { + int packageID = provider.AddPackage(package.PortalID, + package.Name, + package.FriendlyName, + package.Description, + package.PackageType, + package.Version.ToString(3), + package.License, + package.Manifest, + package.Owner, + package.Organization, + package.Url, + package.Email, + package.ReleaseNotes, + package.IsSystemPackage, + UserController.GetCurrentUserInfo().UserID, + package.FolderName, + package.IconFile); + var objEventLog = new EventLogController(); + objEventLog.AddLog(package, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PACKAGE_CREATED); + if (includeDetail) + { + Locale locale; + LanguagePackInfo languagePack; + switch (package.PackageType) + { + case "Auth_System": + //Create a new Auth System + var authSystem = new AuthenticationInfo(); + authSystem.AuthenticationType = package.Name; + authSystem.IsEnabled = Null.NullBoolean; + authSystem.PackageID = packageID; + AuthenticationController.AddAuthentication(authSystem); + break; + case "Container": + case "Skin": + var skinPackage = new SkinPackageInfo(); + skinPackage.SkinName = package.Name; + skinPackage.PackageID = packageID; + skinPackage.SkinType = package.PackageType; + SkinController.AddSkinPackage(skinPackage); + break; + case "CoreLanguagePack": + locale = LocaleController.Instance.GetLocale(PortalController.GetCurrentPortalSettings().DefaultLanguage); + languagePack = new LanguagePackInfo(); + languagePack.PackageID = packageID; + languagePack.LanguageID = locale.LanguageId; + languagePack.DependentPackageID = -2; + LanguagePackController.SaveLanguagePack(languagePack); + break; + case "ExtensionLanguagePack": + locale = LocaleController.Instance.GetLocale(PortalController.GetCurrentPortalSettings().DefaultLanguage); + languagePack = new LanguagePackInfo(); + languagePack.PackageID = packageID; + languagePack.LanguageID = locale.LanguageId; + languagePack.DependentPackageID = Null.NullInteger; + LanguagePackController.SaveLanguagePack(languagePack); + break; + case "Module": + //Create a new DesktopModule + var desktopModule = new DesktopModuleInfo(); + desktopModule.PackageID = packageID; + desktopModule.ModuleName = package.Name; + desktopModule.FriendlyName = package.FriendlyName; + desktopModule.FolderName = package.Name; + desktopModule.Description = package.Description; + desktopModule.Version = package.Version.ToString(3); + desktopModule.SupportedFeatures = 0; + int desktopModuleId = DesktopModuleController.SaveDesktopModule(desktopModule, false, true); + if (desktopModuleId > Null.NullInteger) + { + DesktopModuleController.AddDesktopModuleToPortals(desktopModuleId); + } + break; + case "SkinObject": + var skinControl = new SkinControlInfo(); + skinControl.PackageID = packageID; + skinControl.ControlKey = package.Name; + SkinControlController.SaveSkinControl(skinControl); + break; + } + } + + DataCache.ClearPackagesCache(package.PortalID); + return packageID; + } + + public static bool CanDeletePackage(PackageInfo package, PortalSettings portalSettings) + { + bool bCanDelete = true; + switch (package.PackageType) + { + case "Skin": + case "Container": + //Need to get path of skin being deleted so we can call the public CanDeleteSkin function in the SkinController + string strFolderPath = string.Empty; + string strRootSkin = package.PackageType == "Skin" ? SkinController.RootSkin : SkinController.RootContainer; + SkinPackageInfo _SkinPackageInfo = SkinController.GetSkinByPackageID(package.PackageID); + if (_SkinPackageInfo.PortalID == Null.NullInteger) + { + strFolderPath = Path.Combine(Path.Combine(Globals.HostMapPath, strRootSkin), _SkinPackageInfo.SkinName); + } + else + { + strFolderPath = Path.Combine(Path.Combine(portalSettings.HomeDirectoryMapPath, strRootSkin), _SkinPackageInfo.SkinName); + } + + bCanDelete = SkinController.CanDeleteSkin(strFolderPath, portalSettings.HomeDirectoryMapPath); + break; + case "Provider": + //Check if the provider is the default provider + XmlDocument configDoc = Config.Load(); + string providerName = package.Name; + if (providerName.IndexOf(".") > Null.NullInteger) + { + providerName = providerName.Substring(providerName.IndexOf(".") + 1); + } + switch (providerName) + { + case "SchedulingProvider": + providerName = "DNNScheduler"; + break; + case "SearchIndexProvider": + providerName = "ModuleIndexProvider"; + break; + case "SearchProvider": + providerName = "SearchDataStoreProvider"; + break; + } + XPathNavigator providerNavigator = configDoc.CreateNavigator().SelectSingleNode("/configuration/dotnetnuke/*[@defaultProvider='" + providerName + "']"); + bCanDelete = (providerNavigator == null); + break; + } + return bCanDelete; + } + + public static void DeletePackage(PackageInfo package) + { + switch (package.PackageType) + { + case "Auth_System": + AuthenticationInfo authSystem = AuthenticationController.GetAuthenticationServiceByPackageID(package.PackageID); + if (authSystem != null) + { + AuthenticationController.DeleteAuthentication(authSystem); + } + break; + case "CoreLanguagePack": + LanguagePackInfo languagePack = LanguagePackController.GetLanguagePackByPackage(package.PackageID); + if (languagePack != null) + { + LanguagePackController.DeleteLanguagePack(languagePack); + } + break; + case "Module": + var controller = new DesktopModuleController(); + DesktopModuleInfo desktopModule = DesktopModuleController.GetDesktopModuleByPackageID(package.PackageID); + if (desktopModule != null) + { + controller.DeleteDesktopModule(desktopModule); + } + break; + case "SkinObject": + SkinControlInfo skinControl = SkinControlController.GetSkinControlByPackageID(package.PackageID); + if (skinControl != null) + { + SkinControlController.DeleteSkinControl(skinControl); + } + break; + } + DeletePackage(package.PackageID); + } + + public static void DeletePackage(int packageID) + { + provider.DeletePackage(packageID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("packageID", + packageID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.PACKAGE_DELETED); + + if (PortalSettings.Current != null) + { + DataCache.ClearPackagesCache(PortalSettings.Current.PortalId); + } + DataCache.ClearPackagesCache(Null.NullInteger); + } + + public static PackageInfo GetPackage(int packageID) + { + return GetPackage(packageID, false); + } + + public static PackageInfo GetPackage(int packageID, bool ignoreCache) + { + if (ignoreCache) + { + return CBO.FillObject(provider.GetPackage(packageID)); + } + + return GetPackages().FirstOrDefault(p => p.PackageID == packageID); + } + + public static PackageInfo GetPackageByName(string name) + { + return GetPackageByName(Null.NullInteger, name); + } + + public static PackageInfo GetPackageByName(int portalId, string name) + { + //return CBO.FillObject(provider.GetPackageByName(portalId, name)); + return GetPackages(portalId).FirstOrDefault(p => p.Name == name); + } + + public static List GetPackages() + { + return GetPackages(Null.NullInteger); + } + + public static List GetPackages(int portalID) + { + var cacheKey = string.Format(DataCache.PackagesCacheKey, portalID); + var cacheItemArgs = new CacheItemArgs(cacheKey, DataCache.PackagesCacheTimeout, DataCache.PackagesCachePriority, portalID); + return CBO.GetCachedObject>(cacheItemArgs, GetPackagesCallback); + } + + private static object GetPackagesCallback(CacheItemArgs cacheItemArgs) + { + var portalId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillCollection(provider.GetPackages(portalId)); + } + + public static List GetPackagesByType(string type) + { + return GetPackagesByType(Null.NullInteger, type); + } + + public static IDictionary GetModulePackagesInUse(int portalID, bool forHost) + { + return CBO.FillDictionary("PackageID", provider.GetModulePackagesInUse(portalID, forHost)); + } + + public static List GetPackagesByType(int portalID, string type) + { + //return CBO.FillCollection(provider.GetPackagesByType(portalID, type)); + return GetPackages(portalID).Where(p => p.PackageType == type).ToList(); + } + + public static PackageType GetPackageType(string type) + { + return CBO.FillObject(provider.GetPackageType(type)); + } + + public static List GetPackageTypes() + { + return CBO.FillCollection(provider.GetPackageTypes()); + } + + public static void SavePackage(PackageInfo package) + { + if (package.PackageID == Null.NullInteger) + { + package.PackageID = AddPackage(package, false); + } + else + { + UpdatePackage(package); + } + } + + public static void UpdatePackage(PackageInfo package) + { + provider.UpdatePackage(package.PortalID, + package.Name, + package.FriendlyName, + package.Description, + package.PackageType, + package.Version.ToString(3), + package.License, + package.Manifest, + package.Owner, + package.Organization, + package.Url, + package.Email, + package.ReleaseNotes, + package.IsSystemPackage, + UserController.GetCurrentUserInfo().UserID, + package.FolderName, + package.IconFile); + var objEventLog = new EventLogController(); + objEventLog.AddLog(package, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.PACKAGE_UPDATED); + + DataCache.ClearPackagesCache(package.PortalID); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventArgs.cs b/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventArgs.cs new file mode 100644 index 00000000000..8d7f41c2b07 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventArgs.cs @@ -0,0 +1,77 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages +{ + ///----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace : DotNetNuke.Services.Installer.Packages + /// Class : PackageCreatedEventArgs + ///----------------------------------------------------------------------------- + /// + /// PackageCreatedEventArgs provides a custom EventArgs class for a + /// Package Created Event. + /// + /// + /// [cnurse] 01/23/2008 Created + /// + ///----------------------------------------------------------------------------- + public class PackageCreatedEventArgs : EventArgs + { + private readonly PackageInfo _Package; + + ///----------------------------------------------------------------------------- + /// + /// Builds a new PackageCreatedEventArgs + /// + /// The package associated with this event + /// + /// + /// [cnurse] 01/23/2008 Created + /// + ///----------------------------------------------------------------------------- + public PackageCreatedEventArgs(PackageInfo package) + { + _Package = package; + } + + ///----------------------------------------------------------------------------- + /// + /// Gets the Package associated with this event + /// + /// + /// [cnurse] 01/23/2008 Created + /// + ///----------------------------------------------------------------------------- + public PackageInfo Package + { + get + { + return _Package; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventHandler.cs b/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventHandler.cs new file mode 100644 index 00000000000..2be32356018 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageCreatedEventHandler.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer.Packages +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Services.Installer.Packages + /// Class: PackageCreatedEventHandler + /// ----------------------------------------------------------------------------- + /// + /// The PackageCreatedEventHandler delegate defines a custom event handler for a + /// PAckage Created Event. + /// + /// + /// [cnurse] 01/23/2008 Created + /// + /// ----------------------------------------------------------------------------- + public delegate void PackageCreatedEventHandler(object sender, PackageCreatedEventArgs e); +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageEditorBase.cs b/DNN Platform/Library/Services/Installer/Packages/PackageEditorBase.cs new file mode 100644 index 00000000000..de419364bba --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageEditorBase.cs @@ -0,0 +1,155 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageEditorBase class provides a Base Classs for Package Editors + /// + /// + /// [cnurse] 02/04/2008 Created + /// + /// ----------------------------------------------------------------------------- + public class PackageEditorBase : ModuleUserControlBase, IPackageEditor + { + private bool _IsWizard = Null.NullBoolean; + private PackageInfo _Package; + private int _PackageID = Null.NullInteger; + + protected virtual string EditorID + { + get + { + return Null.NullString; + } + } + + protected bool IsSuperTab + { + get + { + return ModuleContext.PortalSettings.ActiveTab.IsSuperTab; + } + } + + protected PackageInfo Package + { + get + { + if (_Package == null) + { + _Package = PackageController.GetPackage(PackageID); + } + return _Package; + } + } + + #region IPackageEditor Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Package ID + /// + /// An Integer + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public int PackageID + { + get + { + return _PackageID; + } + set + { + _PackageID = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether the Editor is in the Wizard + /// + /// An Boolean + /// + /// [cnurse] 08/26/2008 created + /// + /// ----------------------------------------------------------------------------- + public bool IsWizard + { + get + { + return _IsWizard; + } + set + { + _IsWizard = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Used to Initialize the Control + /// + /// + /// [cnurse] 02/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public virtual void Initialize() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Used to Update the Package + /// + /// + /// [cnurse] 02/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public virtual void UpdatePackage() + { + } + + #endregion + + protected override void OnInit(EventArgs e) + { + ID = EditorID; + base.OnInit(e); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageInfo.cs b/DNN Platform/Library/Services/Installer/Packages/PackageInfo.cs new file mode 100644 index 00000000000..22b436d6f76 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageInfo.cs @@ -0,0 +1,358 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Services.Installer.Log; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageInfo class represents a single Installer Package + /// + /// + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class PackageInfo : BaseEntityInfo + { + /// ----------------------------------------------------------------------------- + /// + /// This Constructor creates a new InstallPackage instance as defined by the + /// Parameters + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public PackageInfo(InstallerInfo info) : this() + { + AttachInstallerInfo(info); + } + + /// + /// This Constructor creates a new InstallPackage instance + /// + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public PackageInfo() + { + PackageID = Null.NullInteger; + PortalID = Null.NullInteger; + Version = new Version(0, 0, 0); + IsValid = true; + InstalledVersion = new Version(0, 0, 0); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ID of this package + /// + /// An Integer + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public int PackageID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ID of this portal + /// + /// An Integer + /// + /// [cnurse] 09/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public int PortalID { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Owner of this package + /// + /// A String + /// + /// [cnurse] 03/26/2008 created + /// + /// ----------------------------------------------------------------------------- + public string Owner { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Organisation for this package + /// + /// A String + /// + /// [cnurse] 03/26/2008 created + /// + /// ----------------------------------------------------------------------------- + public string Organization { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Url for this package + /// + /// A String + /// + /// [cnurse] 03/26/2008 created + /// + /// ----------------------------------------------------------------------------- + public string Url { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Email for this package + /// + /// A String + /// + /// [cnurse] 03/26/2008 created + /// + /// ----------------------------------------------------------------------------- + public string Email { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Description of this package + /// + /// A String + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Description { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the FileName of this package + /// + /// A String + /// ----------------------------------------------------------------------------- + public string FileName { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Files that are included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public Dictionary Files + { + get + { + return InstallerInfo.Files; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the FriendlyName of this package + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string FriendlyName { get; set; } + + public string FolderName { get; set; } + + public string IconFile { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated InstallerInfo + /// + /// An InstallerInfo object + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public InstallerInfo InstallerInfo { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Installed Version of the Package + /// + /// A System.Version + /// + /// [cnurse] 08/07/2007 created + /// + /// ----------------------------------------------------------------------------- + public Version InstalledVersion { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the InstallMode + /// + /// An InstallMode value + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public InstallMode InstallMode + { + get + { + return InstallerInfo.InstallMode; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets whether this package is a "system" Package + /// + /// A String + /// + /// [cnurse] 02/19/2008 created + /// + /// ----------------------------------------------------------------------------- + + public bool IsSystemPackage { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the Package is Valid + /// + /// A Boolean value + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public bool IsValid { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the License of this package + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string License { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Logger + /// + /// An Logger object + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + [XmlIgnore] + public Logger Log + { + get + { + return InstallerInfo.Log; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Manifest of this package + /// + /// A String + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Manifest { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name of this package + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Name { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Type of this package + /// + /// A String + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string PackageType { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the ReleaseNotes of this package + /// + /// A String + /// + /// [cnurse] 01/07/2008 created + /// + /// ----------------------------------------------------------------------------- + public string ReleaseNotes { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Version of this package + /// + /// A System.Version + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public Version Version { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// The AttachInstallerInfo method attachs an InstallerInfo instance to the Package + /// + /// The InstallerInfo instance to attach + /// + /// [cnurse] 08/01/2007 created + /// + /// ----------------------------------------------------------------------------- + public void AttachInstallerInfo(InstallerInfo installer) + { + InstallerInfo = installer; + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageType.cs b/DNN Platform/Library/Services/Installer/Packages/PackageType.cs new file mode 100644 index 00000000000..0d779a640ab --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageType.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages +{ + /// + /// This class allows PackageType to have a memeber named PackageType + /// to remain compatible with the original VB implementation + /// + public class PackageTypeMemberNameFixer + { + public PackageTypeMemberNameFixer() + { + PackageType = string.Empty; + } + + public string PackageType { get; set; } + } + + /// ----------------------------------------------------------------------------- + /// + /// The PackageType class represents a single Installer Package Type + /// + /// ----------------------------------------------------------------------------- + public class PackageType : PackageTypeMemberNameFixer + { + public string Description { get; set; } + public string EditorControlSrc { get; set; } + public SecurityAccessLevel SecurityAccessLevel { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Installer/Packages/PackageTypeEditControl.cs b/DNN Platform/Library/Services/Installer/Packages/PackageTypeEditControl.cs new file mode 100644 index 00000000000..cbdf34ae2bf --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Packages/PackageTypeEditControl.cs @@ -0,0 +1,108 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Web.UI; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.UI.WebControls; + +using DNNLocalization = DotNetNuke.Services.Localization.Localization; + +#endregion + +namespace DotNetNuke.Services.Installer.Packages.WebControls +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Services.Installer.Packages.WebControls + /// Class: PackageTypeEditControl + /// ----------------------------------------------------------------------------- + /// + /// The PackageTypeEditControl control provides a standard UI component for editing + /// package types. + /// + /// + /// [cnurse] 01/25/2008 created + /// + /// ----------------------------------------------------------------------------- + [ToolboxData("<{0}:PackageTypeEditControl runat=server>")] + public class PackageTypeEditControl : TextEditControl + { + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// RenderEditMode renders the Edit mode of the control + /// + /// A HtmlTextWriter. + /// + /// [cnurse] 02/27/2006 created + /// + /// ----------------------------------------------------------------------------- + protected override void RenderEditMode(HtmlTextWriter writer) + { + List packageTypes = PackageController.GetPackageTypes(); + + //Render the Select Tag + ControlStyle.AddAttributesToRender(writer); + writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); + writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID); + writer.RenderBeginTag(HtmlTextWriterTag.Select); + + //Add the Not Specified Option + writer.AddAttribute(HtmlTextWriterAttribute.Value, Null.NullString); + + if (StringValue == Null.NullString) + { + writer.AddAttribute(HtmlTextWriterAttribute.Selected, "selected"); + } + + //Render Option Tag + writer.RenderBeginTag(HtmlTextWriterTag.Option); + writer.Write("<" + DNNLocalization.GetString("Not_Specified", DNNLocalization.SharedResourceFile) + ">"); + writer.RenderEndTag(); + + foreach (PackageType type in packageTypes) + { + //Add the Value Attribute + writer.AddAttribute(HtmlTextWriterAttribute.Value, type.PackageType); + + if (type.PackageType == StringValue) + { + //Add the Selected Attribute + writer.AddAttribute(HtmlTextWriterAttribute.Selected, "selected"); + } + + //Render Option Tag + writer.RenderBeginTag(HtmlTextWriterTag.Option); + writer.Write(type.PackageType); + writer.RenderEndTag(); + } + + //Close Select Tag + writer.RenderEndTag(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/TextEncoding.cs b/DNN Platform/Library/Services/Installer/TextEncoding.cs new file mode 100644 index 00000000000..1baa6274b80 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/TextEncoding.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Installer +{ + public enum TextEncoding + { + UTF7, + UTF8, + UTF16BigEndian, + UTF16LittleEndian, + Unknown + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Util.cs b/DNN Platform/Library/Services/Installer/Util.cs new file mode 100644 index 00000000000..83098b3f56d --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Util.cs @@ -0,0 +1,742 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Common.Utilities.Internal; +using DotNetNuke.Entities.Host; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + /// ----------------------------------------------------------------------------- + /// + /// The InstallerBase class is a Base Class for all Installer + /// classes that need to use Localized Strings. It provides these strings + /// as localized Constants. + /// + /// + /// + /// + /// [cnurse] 07/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public class Util + { + #region Constants + + // ReSharper disable InconsistentNaming + public const string DEFAULT_MANIFESTEXT = ".manifest"; + public static string ASSEMBLY_Added = GetLocalizedString("ASSEMBLY_Added"); + public static string ASSEMBLY_InUse = GetLocalizedString("ASSEMBLY_InUse"); + public static string ASSEMBLY_Registered = GetLocalizedString("ASSEMBLY_Registered"); + public static string ASSEMBLY_UnRegistered = GetLocalizedString("ASSEMBLY_UnRegistered"); + public static string ASSEMBLY_Updated = GetLocalizedString("ASSEMBLY_Updated"); + public static string AUTHENTICATION_ReadSuccess = GetLocalizedString("AUTHENTICATION_ReadSuccess"); + public static string AUTHENTICATION_LoginSrcMissing = GetLocalizedString("AUTHENTICATION_LoginSrcMissing"); + public static string AUTHENTICATION_Registered = GetLocalizedString("AUTHENTICATION_Registered"); + public static string AUTHENTICATION_SettingsSrcMissing = GetLocalizedString("AUTHENTICATION_SettingsSrcMissing"); + public static string AUTHENTICATION_TypeMissing = GetLocalizedString("AUTHENTICATION_TypeMissing"); + public static string AUTHENTICATION_UnRegistered = GetLocalizedString("AUTHENTICATION_UnRegistered"); + public static string CLEANUP_Processing = GetLocalizedString("CLEANUP_Processing"); + public static string CLEANUP_ProcessComplete = GetLocalizedString("CLEANUP_ProcessComplete"); + public static string COMPONENT_Installed = GetLocalizedString("COMPONENT_Installed"); + public static string COMPONENT_Skipped = GetLocalizedString("COMPONENT_Skipped"); + public static string COMPONENT_RolledBack = GetLocalizedString("COMPONENT_RolledBack"); + public static string COMPONENT_RollingBack = GetLocalizedString("COMPONENT_RollingBack"); + public static string COMPONENT_UnInstalled = GetLocalizedString("COMPONENT_UnInstalled"); + public static string CONFIG_Committed = GetLocalizedString("CONFIG_Committed"); + public static string CONFIG_RolledBack = GetLocalizedString("CONFIG_RolledBack"); + public static string CONFIG_Updated = GetLocalizedString("CONFIG_Updated"); + public static string DASHBOARD_ReadSuccess = GetLocalizedString("DASHBOARD_ReadSuccess"); + public static string DASHBOARD_SrcMissing = GetLocalizedString("DASHBOARD_SrcMissing"); + public static string DASHBOARD_Registered = GetLocalizedString("DASHBOARD_Registered"); + public static string DASHBOARD_KeyMissing = GetLocalizedString("DASHBOARD_KeyMissing"); + public static string DASHBOARD_LocalResourcesMissing = GetLocalizedString("DASHBOARD_LocalResourcesMissing"); + public static string DASHBOARD_UnRegistered = GetLocalizedString("DASHBOARD_UnRegistered"); + public static string DNN_Reading = GetLocalizedString("DNN_Reading"); + public static string DNN_ReadingComponent = GetLocalizedString("DNN_ReadingComponent"); + public static string DNN_ReadingPackage = GetLocalizedString("DNN_ReadingPackage"); + public static string DNN_Success = GetLocalizedString("DNN_Success"); + public static string EVENTMESSAGE_CommandMissing = GetLocalizedString("EVENTMESSAGE_CommandMissing"); + public static string EVENTMESSAGE_TypeMissing = GetLocalizedString("EVENTMESSAGE_TypeMissing"); + public static string EXCEPTION = GetLocalizedString("EXCEPTION"); + public static string EXCEPTION_NameMissing = GetLocalizedString("EXCEPTION_NameMissing"); + public static string EXCEPTION_TypeMissing = GetLocalizedString("EXCEPTION_TypeMissing"); + public static string EXCEPTION_VersionMissing = GetLocalizedString("EXCEPTION_VersionMissing"); + public static string EXCEPTION_FileLoad = GetLocalizedString("EXCEPTION_FileLoad"); + public static string EXCEPTION_FileRead = GetLocalizedString("EXCEPTION_FileRead"); + public static string EXCEPTION_InstallerCreate = GetLocalizedString("EXCEPTION_InstallerCreate"); + public static string EXCEPTION_MissingDnn = GetLocalizedString("EXCEPTION_MissingDnn"); + public static string EXCEPTION_MultipleDnn = GetLocalizedString("EXCEPTION_MultipleDnn"); + public static string EXCEPTION_Type = GetLocalizedString("EXCEPTION_Type"); + public static string FILE_CreateBackup = GetLocalizedString("FILE_CreateBackup"); + public static string FILE_Created = GetLocalizedString("FILE_Created"); + public static string FILE_Deleted = GetLocalizedString("FILE_Deleted"); + public static string FILE_Found = GetLocalizedString("FILE_Found"); + public static string FILE_Loading = GetLocalizedString("FILE_Loading"); + public static string FILE_NotAllowed = GetLocalizedString("FILE_NotAllowed"); + public static string FILE_NotFound = GetLocalizedString("FILE_NotFound"); + public static string FILE_ReadSuccess = GetLocalizedString("FILE_ReadSuccess"); + public static string FILE_RestoreBackup = GetLocalizedString("FILE_RestoreBackup"); + public static string FILES_CreatedResources = GetLocalizedString("FILES_CreatedResources"); + public static string FILES_Expanding = GetLocalizedString("FILES_Expanding"); + public static string FILES_Loading = GetLocalizedString("FILES_Loading"); + public static string FILES_Reading = GetLocalizedString("FILES_Reading"); + public static string FILES_ReadingEnd = GetLocalizedString("FILES_ReadingEnd"); + public static string FOLDER_Created = GetLocalizedString("FOLDER_Created"); + public static string FOLDER_Deleted = GetLocalizedString("FOLDER_Deleted"); + public static string FOLDER_DeletedBackup = GetLocalizedString("FOLDER_DeletedBackup"); + public static string INSTALL_Compatibility = GetLocalizedString("INSTALL_Compatibility"); + public static string INSTALL_Dependencies = GetLocalizedString("INSTALL_Dependencies"); + public static string INSTALL_Aborted = GetLocalizedString("INSTALL_Aborted"); + public static string INSTALL_Failed = GetLocalizedString("INSTALL_Failed"); + public static string INSTALL_Committed = GetLocalizedString("INSTALL_Committed"); + public static string INSTALL_Namespace = GetLocalizedString("INSTALL_Namespace"); + public static string INSTALL_Package = GetLocalizedString("INSTALL_Package"); + public static string INSTALL_Permissions = GetLocalizedString("INSTALL_Permissions"); + public static string INSTALL_Start = GetLocalizedString("INSTALL_Start"); + public static string INSTALL_Success = GetLocalizedString("INSTALL_Success"); + public static string INSTALL_Version = GetLocalizedString("INSTALL_Version"); + public static string LANGUAGE_PortalsEnabled = GetLocalizedString("LANGUAGE_PortalsEnabled"); + public static string LANGUAGE_Registered = GetLocalizedString("LANGUAGE_Registered"); + public static string LANGUAGE_UnRegistered = GetLocalizedString("LANGUAGE_UnRegistered"); + public static string MODULE_ControlKeyMissing = GetLocalizedString("MODULE_ControlKeyMissing"); + public static string MODULE_ControlTypeMissing = GetLocalizedString("MODULE_ControlTypeMissing"); + public static string MODULE_FriendlyNameMissing = GetLocalizedString("MODULE_FriendlyNameMissing"); + public static string MODULE_InvalidVersion = GetLocalizedString("MODULE_InvalidVersion"); + public static string MODULE_ReadSuccess = GetLocalizedString("MODULE_ReadSuccess"); + public static string MODULE_Registered = GetLocalizedString("MODULE_Registered"); + public static string MODULE_UnRegistered = GetLocalizedString("MODULE_UnRegistered"); + public static string PACKAGE_NoLicense = GetLocalizedString("PACKAGE_NoLicense"); + public static string PACKAGE_NoReleaseNotes = GetLocalizedString("PACKAGE_NoReleaseNotes"); + public static string PACKAGE_UnRecognizable = GetLocalizedString("PACKAGE_UnRecognizable"); + public static string SECURITY_Installer = GetLocalizedString("SECURITY_Installer"); + public static string SECURITY_NotRegistered = GetLocalizedString("SECURITY_NotRegistered"); + public static string SKIN_BeginProcessing = GetLocalizedString("SKIN_BeginProcessing"); + public static string SKIN_Installed = GetLocalizedString("SKIN_Installed"); + public static string SKIN_EndProcessing = GetLocalizedString("SKIN_EndProcessing"); + public static string SKIN_Registered = GetLocalizedString("SKIN_Registered"); + public static string SKIN_UnRegistered = GetLocalizedString("SKIN_UnRegistered"); + public static string SQL_Begin = GetLocalizedString("SQL_Begin"); + public static string SQL_BeginFile = GetLocalizedString("SQL_BeginFile"); + public static string SQL_BeginUnInstall = GetLocalizedString("SQL_BeginUnInstall"); + public static string SQL_Committed = GetLocalizedString("SQL_Committed"); + public static string SQL_End = GetLocalizedString("SQL_End"); + public static string SQL_EndFile = GetLocalizedString("SQL_EndFile"); + public static string SQL_EndUnInstall = GetLocalizedString("SQL_EndUnInstall"); + public static string SQL_Exceptions = GetLocalizedString("SQL_Exceptions"); + public static string SQL_Executing = GetLocalizedString("SQL_Executing"); + public static string SQL_RolledBack = GetLocalizedString("SQL_RolledBack"); + public static string UNINSTALL_Start = GetLocalizedString("UNINSTALL_Start"); + public static string UNINSTALL_StartComp = GetLocalizedString("UNINSTALL_StartComp"); + public static string UNINSTALL_Failure = GetLocalizedString("UNINSTALL_Failure"); + public static string UNINSTALL_Success = GetLocalizedString("UNINSTALL_Success"); + public static string UNINSTALL_SuccessComp = GetLocalizedString("UNINSTALL_SuccessComp"); + public static string UNINSTALL_Warnings = GetLocalizedString("UNINSTALL_Warnings"); + public static string UNINSTALL_WarningsComp = GetLocalizedString("UNINSTALL_WarningsComp"); + public static string URLPROVIDER_NameMissing = GetLocalizedString("URLPROVIDER_NameMissing"); + public static string URLPROVIDER_ReadSuccess = GetLocalizedString("URLPROVIDER_ReadSuccess"); + public static string URLPROVIDER_Registered = GetLocalizedString("URLPROVIDER_Registered"); + public static string URLPROVIDER_TypeMissing = GetLocalizedString("URLPROVIDER_TypeMissing"); + public static string URLPROVIDER_UnRegistered = GetLocalizedString("URLPROVIDER_UnRegistered"); + public static string WRITER_AddFileToManifest = GetLocalizedString("WRITER_AddFileToManifest"); + public static string WRITER_CreateArchive = GetLocalizedString("WRITER_CreateArchive"); + public static string WRITER_CreatedManifest = GetLocalizedString("WRITER_CreatedManifest"); + public static string WRITER_CreatedPackage = GetLocalizedString("WRITER_CreatedPackage"); + public static string WRITER_CreatingManifest = GetLocalizedString("WRITER_CreatingManifest"); + public static string WRITER_CreatingPackage = GetLocalizedString("WRITER_CreatingPackage"); + public static string WRITER_SavedFile = GetLocalizedString("WRITER_SavedFile"); + public static string WRITER_SaveFileError = GetLocalizedString("WRITER_SaveFileError"); + public static string REGEX_Version = "\\d{2}.\\d{2}.\\d{2}"; + // ReSharper restore InconsistentNaming + #endregion + + #region "Private Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The StreamToStream method reads a source stream and wrtites it to a destination stream + /// + /// The Source Stream + /// The Destination Stream + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + private static void StreamToStream(Stream sourceStream, Stream destStream) + { + var buf = new byte[1024]; + int count; + do + { + //Read the chunk from the source + count = sourceStream.Read(buf, 0, 1024); + + //Write the chunk to the destination + destStream.Write(buf, 0, count); + } while (count > 0); + destStream.Flush(); + } + + private static void TryDeleteFolder(DirectoryInfo folder, Logger log) + { + if (folder.GetFiles().Length == 0 && folder.GetDirectories().Length == 0) + { + folder.Delete(); + log.AddInfo(string.Format(FOLDER_Deleted, folder.Name)); + TryDeleteFolder(folder.Parent, log); + } + } + + private static string ValidateNode(string propValue, bool isRequired, Logger log, string logmessage, string defaultValue) + { + if (string.IsNullOrEmpty(propValue)) + { + if (isRequired) + { + //Log Error + log.AddFailure(logmessage); + } + else + { + //Use Default + propValue = defaultValue; + } + } + return propValue; + } + + #endregion + + #region Public Shared Methods + + /// ----------------------------------------------------------------------------- + /// + /// The BackupFile method backs up a file to the backup folder + /// + /// The file to backup + /// The basePath to the file + /// A Logger to log the result + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void BackupFile(InstallFile installFile, string basePath, Logger log) + { + string fullFileName = Path.Combine(basePath, installFile.FullName); + string backupFileName = Path.Combine(installFile.BackupPath, installFile.Name + ".config"); + + //create the backup folder if neccessary + if (!Directory.Exists(installFile.BackupPath)) + { + Directory.CreateDirectory(installFile.BackupPath); + } + + //Copy file to backup location + RetryableAction.RetryEverySecondFor30Seconds(() => FileSystemUtils.CopyFile(fullFileName, backupFileName), "Backup file " + fullFileName); + log.AddInfo(string.Format(FILE_CreateBackup, installFile.FullName)); + } + + /// ----------------------------------------------------------------------------- + /// + /// The CopyFile method copies a file from the temporary extract location. + /// + /// The file to copy + /// The basePath to the file + /// A Logger to log the result + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void CopyFile(InstallFile installFile, string basePath, Logger log) + { + string filePath = Path.Combine(basePath, installFile.Path); + string fullFileName = Path.Combine(basePath, installFile.FullName); + + //create the folder if neccessary + if (!Directory.Exists(filePath)) + { + log.AddInfo(string.Format(FOLDER_Created, filePath)); + Directory.CreateDirectory(filePath); + } + + //Copy file from temp location + RetryableAction.RetryEverySecondFor30Seconds(() => FileSystemUtils.CopyFile(installFile.TempFileName, fullFileName), "Copy file to " + fullFileName); + + log.AddInfo(string.Format(FILE_Created, installFile.FullName)); + } + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteFile method deletes a file. + /// + /// The file to delete + /// The basePath to the file + /// A Logger to log the result + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteFile(InstallFile installFile, string basePath, Logger log) + { + DeleteFile(installFile.FullName, basePath, log); + } + + /// ----------------------------------------------------------------------------- + /// + /// The DeleteFile method deletes a file. + /// + /// The file to delete + /// The basePath to the file + /// A Logger to log the result + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void DeleteFile(string fileName, string basePath, Logger log) + { + string fullFileName = Path.Combine(basePath, fileName); + if (File.Exists(fullFileName)) + { + RetryableAction.RetryEverySecondFor30Seconds(() => FileSystemUtils.DeleteFile(fullFileName), "Delete file " + fullFileName); + log.AddInfo(string.Format(FILE_Deleted, fileName)); + string folderName = Path.GetDirectoryName(fullFileName); + if (folderName != null) + { + var folder = new DirectoryInfo(folderName); + TryDeleteFolder(folder, log); + } + } + } + + + /// ----------------------------------------------------------------------------- + /// + /// The GetLocalizedString method provides a conveniencewrapper around the + /// Localization of Strings + /// + /// The localization key + /// The localized string + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public static string GetLocalizedString(string key) + { + return Localization.Localization.GetString(key, Localization.Localization.SharedResourceFile); + } + + public static bool IsFileValid(InstallFile file, string packageWhiteList) + { + //Check the White List + FileExtensionWhitelist whiteList = Host.AllowedExtensionWhitelist; + + //Check the White Lists + string strExtension = file.Extension.ToLowerInvariant(); + if ((strExtension == "dnn" || whiteList.IsAllowedExtension(strExtension) || packageWhiteList.Contains(strExtension) || + (packageWhiteList.Contains("*dataprovider") && strExtension.EndsWith("dataprovider")))) + { + //Install File is Valid + return true; + } + + return false; + } + + /// ----------------------------------------------------------------------------- + /// + /// The InstallURL method provides a utility method to build the correct url + /// to install a package (and return to where you came from) + /// + /// The id of the tab you are on + /// The type of package you are installing + /// The localized string + /// + /// [cnurse] 07/26/2007 created + /// + /// ----------------------------------------------------------------------------- + public static string InstallURL(int tabId, string type) + { + var parameters = new string[2]; + parameters[0] = "rtab=" + tabId; + if (!string.IsNullOrEmpty(type)) + { + parameters[1] = "ptype=" + type; + } + var context = new ModuleInstanceContext(); + return context.NavigateUrl(tabId, "Install", false, parameters); + } + + public static string InstallURL(int tabId, string returnUrl, string type) + { + var parameters = new string[3]; + parameters[0] = "rtab=" + tabId; + if (!string.IsNullOrEmpty(returnUrl)) + { + parameters[1] = "returnUrl=" + returnUrl; + } + if (!string.IsNullOrEmpty(type)) + { + parameters[2] = "ptype=" + type; + } + var context = new ModuleInstanceContext(); + return context.NavigateUrl(tabId, "Install", false, parameters); + } + + public static string InstallURL(int tabId, string returnUrl, string type, string package) + { + var parameters = new string[4]; + parameters[0] = "rtab=" + tabId; + if (!string.IsNullOrEmpty(returnUrl)) + { + parameters[1] = "returnUrl=" + returnUrl; + } + if (!string.IsNullOrEmpty(type)) + { + parameters[2] = "ptype=" + type; + } + if (!string.IsNullOrEmpty(package)) + { + parameters[3] = "package=" + package; + } + var context = new ModuleInstanceContext(); + return context.NavigateUrl(tabId, "Install", false, parameters); + } + + public static string UnInstallURL(int tabId, int packageId, string returnUrl) + { + var parameters = new string[3]; + parameters[0] = "rtab=" + tabId; + parameters[1] = "returnUrl=" + returnUrl; + parameters[2] = "packageId=" + packageId; + var context = new ModuleInstanceContext(); + return context.NavigateUrl(tabId, "UnInstall", true, parameters); + } + + /// ----------------------------------------------------------------------------- + /// + /// The PackageWriterURL method provides a utility method to build the correct url + /// to create a package (and return to where you came from) + /// + /// The ModuleContext of the module + /// The id of the package you are packaging + /// The localized string + /// + /// [cnurse] 01/31/2008 created + /// [vnguyen] 05/24/2011 updated: calls NavigateUrl of Module Context to handle popups + /// + /// ----------------------------------------------------------------------------- + public static string PackageWriterURL(ModuleInstanceContext context, int packageId) + { + var parameters = new string[3]; + parameters[0] = "rtab=" + context.TabId; + parameters[1] = "packageId=" + packageId; + parameters[2] = "mid=" + context.ModuleId; + + return context.NavigateUrl(context.TabId, "PackageWriter", true, parameters); + } + + public static string ParsePackageIconFileName(PackageInfo package) + { + var filename = string.Empty; + if ((package.IconFile != null) && (package.PackageType == "Module" || package.PackageType == "Auth_System" || package.PackageType == "Container" || package.PackageType == "Skin")) + { + filename = package.IconFile.StartsWith("~/" + package.FolderName) ? package.IconFile.Remove(0, ("~/" + package.FolderName).Length).TrimStart('/') : package.IconFile; + } + return filename; + } + + public static string ParsePackageIconFile(PackageInfo package) + { + var iconFile = string.Empty; + if ((package.IconFile != null) && (package.PackageType == "Module" || package.PackageType == "Auth_System" || package.PackageType == "Container" || package.PackageType == "Skin")) + { + iconFile = !package.IconFile.StartsWith("~/") ? "~/" + package.FolderName + "/" + package.IconFile : package.IconFile; + } + return iconFile; + } + + public static string ReadAttribute(XPathNavigator nav, string attributeName) + { + return ValidateNode(nav.GetAttribute(attributeName, ""), false, null, "", ""); + } + + public static string ReadAttribute(XPathNavigator nav, string attributeName, Logger log, string logmessage) + { + return ValidateNode(nav.GetAttribute(attributeName, ""), true, log, logmessage, ""); + } + + public static string ReadAttribute(XPathNavigator nav, string attributeName, bool isRequired, Logger log, string logmessage, string defaultValue) + { + return ValidateNode(nav.GetAttribute(attributeName, ""), isRequired, log, logmessage, defaultValue); + } + + #endregion + + #region ReadElement + + public static string ReadElement(XPathNavigator nav, string elementName) + { + return ValidateNode(XmlUtils.GetNodeValue(nav, elementName), false, null, "", ""); + } + + public static string ReadElement(XPathNavigator nav, string elementName, string defaultValue) + { + return ValidateNode(XmlUtils.GetNodeValue(nav, elementName), false, null, "", defaultValue); + } + + public static string ReadElement(XPathNavigator nav, string elementName, Logger log, string logmessage) + { + return ValidateNode(XmlUtils.GetNodeValue(nav, elementName), true, log, logmessage, ""); + } + + public static string ReadElement(XPathNavigator nav, string elementName, bool isRequired, Logger log, string logmessage, string defaultValue) + { + return ValidateNode(XmlUtils.GetNodeValue(nav, elementName), isRequired, log, logmessage, defaultValue); + } + + /// ----------------------------------------------------------------------------- + /// + /// The RestoreFile method restores a file from the backup folder + /// + /// The file to restore + /// The basePath to the file + /// A Logger to log the result + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void RestoreFile(InstallFile installFile, string basePath, Logger log) + { + string fullFileName = Path.Combine(basePath, installFile.FullName); + string backupFileName = Path.Combine(installFile.BackupPath, installFile.Name + ".config"); + + //Copy File back over install file + FileSystemUtils.CopyFile(backupFileName, fullFileName); + + log.AddInfo(string.Format(FILE_RestoreBackup, installFile.FullName)); + } + + /// ----------------------------------------------------------------------------- + /// + /// The UnInstallURL method provides a utility method to build the correct url + /// to uninstall a package (and return to where you came from) + /// + /// The id of the tab you are on + /// The id of the package you are uninstalling + /// The localized string + /// + /// [cnurse] 07/31/2007 created + /// [vnguyen] 05/24/2011 updated: calls NavigateUrl of Module Context to handle popups + /// + /// ----------------------------------------------------------------------------- + public static string UnInstallURL(int tabId, int packageId) + { + var parameters = new string[2]; + parameters[0] = "rtab=" + tabId; + parameters[1] = "packageId=" + packageId; + var context = new ModuleInstanceContext(); + return context.NavigateUrl(tabId, "UnInstall", true, parameters); + } + + /// ----------------------------------------------------------------------------- + /// + /// The WriteStream reads a source stream and writes it to a destination file + /// + /// The Source Stream + /// The Destination file + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public static void WriteStream(Stream sourceStream, string destFileName) + { + //Delete the file + FileSystemUtils.DeleteFile(destFileName); + + var file = new FileInfo(destFileName); + if (file.Directory != null && !file.Directory.Exists) + { + file.Directory.Create(); + } + Stream fileStrm = file.Create(); + + StreamToStream(sourceStream, fileStrm); + + //Close the stream + fileStrm.Close(); + } + + public static WebResponse GetExternalRequest(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, bool DoPOST, string UserAgent, + string Referer, out string Filename) + { + return GetExternalRequest(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, DoPOST, UserAgent, Referer, out Filename, Host.WebRequestTimeout); + } + + public static WebResponse GetExternalRequest(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, bool DoPOST, string UserAgent, + string Referer, out string Filename, int requestTimeout) + { + return GetExternalRequest(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, string.Empty, string.Empty, DoPOST, UserAgent, Referer, out Filename, requestTimeout); + } + + public static WebResponse GetExternalRequest(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, + string ProxyUsername, string ProxyPassword, bool DoPOST, string UserAgent, string Referer, out string Filename) + { + return GetExternalRequest(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, ProxyUsername, ProxyPassword, DoPOST, UserAgent, Referer, out Filename, Host.WebRequestTimeout); + } + + public static WebResponse GetExternalRequest(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, + string ProxyUsername, string ProxyPassword, bool DoPOST, string UserAgent, string Referer, out string Filename, int requestTimeout) + { + if (!DoPOST && Data != null && Data.Length > 0) + { + string restoftheurl = Encoding.ASCII.GetString(Data); + if (URL != null && URL.IndexOf("?") <= 0) + { + URL = URL + "?"; + } + URL = URL + restoftheurl; + } + + var wreq = (HttpWebRequest)WebRequest.Create(URL); + wreq.UserAgent = UserAgent; + wreq.Referer = Referer; + wreq.Method = "GET"; + if (DoPOST) + { + wreq.Method = "POST"; + } + + wreq.Timeout = requestTimeout; + + if (!string.IsNullOrEmpty(ProxyAddress)) + { + var proxy = new WebProxy(ProxyAddress, ProxyPort); + if (!string.IsNullOrEmpty(ProxyUsername)) + { + var proxyCredentials = new NetworkCredential(ProxyUsername, ProxyPassword); + proxy.Credentials = proxyCredentials; + } + wreq.Proxy = proxy; + } + + if (Username != null && Password != null && Domain != null && Username.Trim() != "" && Password.Trim() != null && Domain.Trim() != null) + { + wreq.Credentials = new NetworkCredential(Username, Password, Domain); + } + else if (Username != null && Password != null && Username.Trim() != "" && Password.Trim() != null) + { + wreq.Credentials = new NetworkCredential(Username, Password); + } + + if (DoPOST && Data != null && Data.Length > 0) + { + wreq.ContentType = "application/x-www-form-urlencoded"; + Stream request = wreq.GetRequestStream(); + request.Write(Data, 0, Data.Length); + request.Close(); + } + + Filename = ""; + WebResponse wrsp = wreq.GetResponse(); + string cd = wrsp.Headers["Content-Disposition"]; + if (cd != null && cd.Trim() != string.Empty && cd.StartsWith("attachment")) + { + if (cd.IndexOf("filename") > -1 && cd.Substring(cd.IndexOf("filename")).IndexOf("=") > -1) + { + string filenameParam = cd.Substring(cd.IndexOf("filename")); + + if (filenameParam.IndexOf("\"") > -1) + { + Filename = filenameParam.Substring(filenameParam.IndexOf("\"") + 1).TrimEnd(Convert.ToChar("\"")).TrimEnd(Convert.ToChar("\\")); + } + else + { + Filename = filenameParam.Substring(filenameParam.IndexOf("=") + 1); + } + } + } + + return wrsp; + } + + public static void DeployExtension(WebResponse wr, string myfile, string installFolder) + { + Stream remoteStream = null; + Stream localStream = null; + + try + { + // Once the WebResponse object has been retrieved, + // get the stream object associated with the response's data + remoteStream = wr.GetResponseStream(); + + // Create the local file with zip extension to ensure installation + localStream = File.Create(installFolder + "/" + myfile); + + // Allocate a 1k buffer + var buffer = new byte[1024]; + int bytesRead; + + // Simple do/while loop to read from stream until + // no bytes are returned + do + { + // Read data (up to 1k) from the stream + bytesRead = remoteStream.Read(buffer, 0, buffer.Length); + + // Write the data to the local file + localStream.Write(buffer, 0, bytesRead); + + // Increment total bytes processed + //TODO fix this line bytesProcessed += bytesRead; + } while (bytesRead > 0); + } + finally + { + // Close the response and streams objects here + // to make sure they're closed even if an exception + // is thrown at some point + if (remoteStream != null) + { + remoteStream.Close(); + } + if (localStream != null) + { + localStream.Close(); + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/AssemblyComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/AssemblyComponentWriter.cs new file mode 100644 index 00000000000..5a4ba4379a2 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/AssemblyComponentWriter.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The AssemblyComponentWriter class handles creating the manifest for Assembly + /// Component(s) + /// + /// + /// + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + public class AssemblyComponentWriter : FileComponentWriter + { + public AssemblyComponentWriter(string basePath, Dictionary assemblies, PackageInfo package) : base(basePath, assemblies, package) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("assemblies") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "assemblies"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("Assembly") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "Assembly"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("assembly") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "assembly"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/AuthenticationPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/AuthenticationPackageWriter.cs new file mode 100644 index 00000000000..b9e2e98d5c1 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/AuthenticationPackageWriter.cs @@ -0,0 +1,114 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Xml; + +using DotNetNuke.Services.Authentication; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The AuthenticationPackageWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class AuthenticationPackageWriter : PackageWriterBase + { + #region "Constructors" + + public AuthenticationPackageWriter(PackageInfo package) : base(package) + { + AuthSystem = AuthenticationController.GetAuthenticationServiceByPackageID(package.PackageID); + Initialize(); + } + + public AuthenticationPackageWriter(AuthenticationInfo authSystem, PackageInfo package) : base(package) + { + AuthSystem = authSystem; + Initialize(); + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Authentication System + /// + /// An AuthenticationInfo object + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public AuthenticationInfo AuthSystem { get; set; } + + #endregion + + #region "Private Methods" + + private void Initialize() + { + BasePath = Path.Combine("DesktopModules\\AuthenticationServices", AuthSystem.AuthenticationType); + AppCodePath = Path.Combine("App_Code\\AuthenticationServices", AuthSystem.AuthenticationType); + AssemblyPath = "bin"; + } + + private void WriteAuthenticationComponent(XmlWriter writer) + { + //Start component Element + writer.WriteStartElement("component"); + writer.WriteAttributeString("type", "AuthenticationSystem"); + + //Start authenticationService Element + writer.WriteStartElement("authenticationService"); + + writer.WriteElementString("type", AuthSystem.AuthenticationType); + writer.WriteElementString("settingsControlSrc", AuthSystem.SettingsControlSrc); + writer.WriteElementString("loginControlSrc", AuthSystem.LoginControlSrc); + writer.WriteElementString("logoffControlSrc", AuthSystem.LogoffControlSrc); + + //End authenticationService Element + writer.WriteEndElement(); + + //End component Element + writer.WriteEndElement(); + } + + #endregion + + protected override void WriteManifestComponent(XmlWriter writer) + { + //Write Authentication Component + WriteAuthenticationComponent(writer); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/CleanupComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/CleanupComponentWriter.cs new file mode 100644 index 00000000000..d925eec16ad --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/CleanupComponentWriter.cs @@ -0,0 +1,90 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.IO; +using System.Xml; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The CleanupComponentWriter class handles creating the manifest for Cleanup + /// Component(s) + /// + /// + /// + /// + /// [cnurse] 02/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public class CleanupComponentWriter + { + #region "Private Members" + + private readonly SortedList _Files; + private string _BasePath; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs the ContainerComponentWriter + /// + /// Base Path. + /// A Dictionary of files + /// + /// [cnurse] 02/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public CleanupComponentWriter(string basePath, SortedList files) + { + _Files = files; + _BasePath = basePath; + } + + #endregion + + #region "Public Methods" + + public virtual void WriteManifest(XmlWriter writer) + { + foreach (KeyValuePair kvp in _Files) + { + //Start component Element + writer.WriteStartElement("component"); + writer.WriteAttributeString("type", "Cleanup"); + writer.WriteAttributeString("fileName", kvp.Value.Name); + writer.WriteAttributeString("version", Path.GetFileNameWithoutExtension(kvp.Value.Name)); + + //End component Element + writer.WriteEndElement(); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ContainerComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ContainerComponentWriter.cs new file mode 100644 index 00000000000..3b66b401f1d --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ContainerComponentWriter.cs @@ -0,0 +1,128 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ContainerComponentWriter class handles creating the manifest for Container + /// Component(s) + /// + /// + /// + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ContainerComponentWriter : SkinComponentWriter + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs the ContainerComponentWriter + /// + /// The name of the Container + /// The Base Path for the files + /// A Dictionary of files + /// + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public ContainerComponentWriter(string containerName, string basePath, Dictionary files, PackageInfo package) : base(containerName, basePath, files, package) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("containerFiles") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "containerFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("Skin") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "Container"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("containerFile") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "containerFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the SkinName Node ("containerName") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string SkinNameNodeName + { + get + { + return "containerName"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ContainerPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ContainerPackageWriter.cs new file mode 100644 index 00000000000..4aadf674732 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ContainerPackageWriter.cs @@ -0,0 +1,60 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; + +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ContainerPackageWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ContainerPackageWriter : SkinPackageWriter + { + public ContainerPackageWriter(PackageInfo package) : base(package) + { + BasePath = "Portals\\_default\\Containers\\" + SkinPackage.SkinName; + } + + public ContainerPackageWriter(SkinPackageInfo skinPackage, PackageInfo package) : base(skinPackage, package) + { + BasePath = "Portals\\_default\\Containers\\" + skinPackage.SkinName; + } + + protected override void WriteFilesToManifest(XmlWriter writer) + { + var containerFileWriter = new ContainerComponentWriter(SkinPackage.SkinName, BasePath, Files, Package); + containerFileWriter.WriteManifest(writer); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/FileComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/FileComponentWriter.cs new file mode 100644 index 00000000000..1ce1890c2fc --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/FileComponentWriter.cs @@ -0,0 +1,289 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The FileComponentWriter class handles creating the manifest for File Component(s) + /// + /// + /// + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + public class FileComponentWriter + { + #region "Private Members" + + private readonly string _BasePath; + private readonly Dictionary _Files; + private readonly PackageInfo _Package; + private int _InstallOrder = Null.NullInteger; + private int _UnInstallOrder = Null.NullInteger; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs the FileComponentWriter + /// + /// The Base Path for the files + /// A Dictionary of files + /// Package Info. + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public FileComponentWriter(string basePath, Dictionary files, PackageInfo package) + { + _Files = files; + _BasePath = basePath; + _Package = package; + } + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("files") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string CollectionNodeName + { + get + { + return "files"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("File") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string ComponentType + { + get + { + return "File"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("file") + /// + /// A String + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string ItemNodeName + { + get + { + return "file"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Logger + /// + /// A Logger + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual Logger Log + { + get + { + return _Package.Log; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Package + /// + /// A PackageInfo + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual PackageInfo Package + { + get + { + return _Package; + } + } + + #endregion + + #region "Public Properties" + + public int InstallOrder + { + get + { + return _InstallOrder; + } + set + { + _InstallOrder = value; + } + } + + public int UnInstallOrder + { + get + { + return _UnInstallOrder; + } + set + { + _UnInstallOrder = value; + } + } + + #endregion + + #region "Protected Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The WriteCustomManifest method writes the custom manifest items (that subclasses + /// of FileComponentWriter may need) + /// + /// The Xmlwriter to use + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void WriteCustomManifest(XmlWriter writer) + { + } + + protected virtual void WriteFileElement(XmlWriter writer, InstallFile file) + { + Log.AddInfo(string.Format(Util.WRITER_AddFileToManifest, file.Name)); + + //Start file Element + writer.WriteStartElement(ItemNodeName); + + //Write path + if (!string.IsNullOrEmpty(file.Path)) + { + string path = file.Path; + if (!string.IsNullOrEmpty(_BasePath)) + { + if (file.Path.ToLowerInvariant().Contains(_BasePath.ToLowerInvariant())) + { + path = file.Path.ToLowerInvariant().Replace(_BasePath.ToLowerInvariant() + "\\", ""); + } + } + writer.WriteElementString("path", path); + } + + //Write name + writer.WriteElementString("name", file.Name); + + //Write sourceFileName + if (!string.IsNullOrEmpty(file.SourceFileName)) + { + writer.WriteElementString("sourceFileName", file.SourceFileName); + } + + //Close file Element + writer.WriteEndElement(); + } + + #endregion + + #region "Public Methods" + + public virtual void WriteManifest(XmlWriter writer) + { + //Start component Element + writer.WriteStartElement("component"); + writer.WriteAttributeString("type", ComponentType); + if (InstallOrder > Null.NullInteger) + { + writer.WriteAttributeString("installOrder", InstallOrder.ToString()); + } + if (UnInstallOrder > Null.NullInteger) + { + writer.WriteAttributeString("unInstallOrder", UnInstallOrder.ToString()); + } + + //Start files element + writer.WriteStartElement(CollectionNodeName); + + //Write custom manifest items + WriteCustomManifest(writer); + + //Write basePath Element + if (!string.IsNullOrEmpty(_BasePath)) + { + writer.WriteElementString("basePath", _BasePath); + } + foreach (InstallFile file in _Files.Values) + { + WriteFileElement(writer, file); + } + + //End files Element + writer.WriteEndElement(); + + //End component Element + writer.WriteEndElement(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/LanguageComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/LanguageComponentWriter.cs new file mode 100644 index 00000000000..46ee6bdc9e5 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/LanguageComponentWriter.cs @@ -0,0 +1,183 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The LanguageComponentWriter class handles creating the manifest for Language + /// Component(s) + /// + /// + /// + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + public class LanguageComponentWriter : FileComponentWriter + { + #region "Private Members" + + private readonly int _DependentPackageID; + private readonly Locale _Language; + private readonly LanguagePackType _PackageType; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs the LanguageComponentWriter + /// + /// Language Info. + /// Base Path. + /// A Dictionary of files + /// Package Info. + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + public LanguageComponentWriter(Locale language, string basePath, Dictionary files, PackageInfo package) : base(basePath, files, package) + { + _Language = language; + _PackageType = LanguagePackType.Core; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs the LanguageComponentWriter + /// + /// Language Package info. + /// Base Path. + /// A Dictionary of files + /// Package Info. + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + public LanguageComponentWriter(LanguagePackInfo languagePack, string basePath, Dictionary files, PackageInfo package) : base(basePath, files, package) + { + _Language = LocaleController.Instance.GetLocale(languagePack.LanguageID); + _PackageType = languagePack.PackageType; + _DependentPackageID = languagePack.DependentPackageID; + } + + #endregion + + #region "Protected Properties" + + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("languageFiles") + /// + /// A String + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "languageFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("CoreLanguage/ExtensionLanguage") + /// + /// A String + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + if (_PackageType == LanguagePackType.Core) + { + return "CoreLanguage"; + } + else + { + return "ExtensionLanguage"; + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("languageFile") + /// + /// A String + /// + /// [cnurse] 02/08/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "languageFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The WriteCustomManifest method writes the custom manifest items + /// + /// The Xmlwriter to use + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void WriteCustomManifest(XmlWriter writer) + { + //Write language Elements + writer.WriteElementString("code", _Language.Code); + if (_PackageType == LanguagePackType.Core) + { + writer.WriteElementString("displayName", _Language.Text); + writer.WriteElementString("fallback", _Language.Fallback); + } + else + { + PackageInfo package = PackageController.GetPackage(_DependentPackageID); + writer.WriteElementString("package", package.Name); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/LanguagePackWriter.cs b/DNN Platform/Library/Services/Installer/Writers/LanguagePackWriter.cs new file mode 100644 index 00000000000..05740f09aa7 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/LanguagePackWriter.cs @@ -0,0 +1,601 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The LanguagePackWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class LanguagePackWriter : PackageWriterBase + { + #region "Private Members" + + private bool _IsCore = Null.NullBoolean; + private Locale _Language; + private LanguagePackInfo _LanguagePack; + + #endregion + + #region "Constructors" + + + public LanguagePackWriter(PackageInfo package) : base(package) + { + _LanguagePack = LanguagePackController.GetLanguagePackByPackage(package.PackageID); + if (LanguagePack != null) + { + _Language = LocaleController.Instance.GetLocale(_LanguagePack.LanguageID); + if (LanguagePack.PackageType == LanguagePackType.Core) + { + BasePath = Null.NullString; + } + else + { + //Get the BasePath of the Dependent Package + PackageInfo dependendentPackage = PackageController.GetPackage(LanguagePack.DependentPackageID); + PackageWriterBase dependentPackageWriter = PackageWriterFactory.GetWriter(dependendentPackage); + BasePath = dependentPackageWriter.BasePath; + } + } + else + { + BasePath = Null.NullString; + } + } + + public LanguagePackWriter(XPathNavigator manifestNav, InstallerInfo installer) + { + _Language = new Locale(); + XPathNavigator cultureNav = manifestNav.SelectSingleNode("Culture"); + _Language.Text = Util.ReadAttribute(cultureNav, "DisplayName"); + _Language.Code = Util.ReadAttribute(cultureNav, "Code"); + _Language.Fallback = Localization.Localization.SystemLocale; + + //Create a Package + Package = new PackageInfo(installer); + Package.Name = Language.Text; + Package.FriendlyName = Language.Text; + Package.Description = Null.NullString; + Package.Version = new Version(1, 0, 0); + Package.License = Util.PACKAGE_NoLicense; + + ReadLegacyManifest(manifestNav); + + if (_IsCore) + { + Package.PackageType = "CoreLanguagePack"; + } + else + { + Package.PackageType = "ExtensionLanguagePack"; + } + BasePath = Null.NullString; + } + + public LanguagePackWriter(Locale language, PackageInfo package) : base(package) + { + _Language = language; + BasePath = Null.NullString; + } + + #endregion + + #region "Public Properties" + + public override bool IncludeAssemblies + { + get + { + return false; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Language + /// + /// An Locale object + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public Locale Language + { + get + { + return _Language; + } + set + { + _Language = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Language Pack + /// + /// An LanguagePackInfo object + /// + /// [cnurse] 05/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public LanguagePackInfo LanguagePack + { + get + { + return _LanguagePack; + } + set + { + _LanguagePack = value; + } + } + + private void ReadLegacyManifest(XPathNavigator manifestNav) + { + string fileName = Null.NullString; + string filePath = Null.NullString; + string sourceFileName = Null.NullString; + string resourcetype = Null.NullString; + string moduleName = Null.NullString; + foreach (XPathNavigator fileNav in manifestNav.Select("Files/File")) + { + fileName = Util.ReadAttribute(fileNav, "FileName").ToLowerInvariant(); + resourcetype = Util.ReadAttribute(fileNav, "FileType"); + moduleName = Util.ReadAttribute(fileNav, "ModuleName").ToLowerInvariant(); + sourceFileName = Path.Combine(resourcetype, Path.Combine(moduleName, fileName)); + string extendedExtension = "." + Language.Code.ToLowerInvariant() + ".resx"; + switch (resourcetype) + { + case "GlobalResource": + filePath = "App_GlobalResources"; + _IsCore = true; + break; + case "ControlResource": + filePath = "Controls\\App_LocalResources"; + break; + case "AdminResource": + _IsCore = true; + switch (moduleName) + { + case "authentication": + filePath = "DesktopModules\\Admin\\Authentication\\App_LocalResources"; + break; + case "controlpanel": + filePath = "Admin\\ControlPanel\\App_LocalResources"; + break; + case "files": + filePath = "DesktopModules\\Admin\\FileManager\\App_LocalResources"; + break; + case "host": + switch (fileName.Replace(extendedExtension, "")) + { + case "authentication.ascx": + filePath = ""; + break; + case "friendlyurls.ascx": + filePath = "DesktopModules\\Admin\\HostSettings\\App_LocalResources"; + break; + case "hostsettings.ascx": + filePath = "DesktopModules\\Admin\\HostSettings\\App_LocalResources"; + break; + case "requestfilters.ascx": + filePath = "DesktopModules\\Admin\\HostSettings\\App_LocalResources"; + break; + case "solutions.ascx": + filePath = "DesktopModules\\Admin\\Solutions\\App_LocalResources"; + break; + } + break; + case "lists": + filePath = "DesktopModules\\Admin\\Lists\\App_LocalResources"; + break; + case "localization": + switch (fileName.Replace(extendedExtension, "")) + { + case "languageeditor.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + case "languageeditorext.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + case "timezoneeditor.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + case "resourceverifier.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + default: + filePath = ""; + break; + } + break; + case "log": + filePath = "DesktopModules\\Admin\\SiteLog\\App_LocalResources"; + break; + case "logging": + filePath = "DesktopModules\\Admin\\LogViewer\\App_LocalResources"; + break; + case "moduledefinitions": + switch (fileName.Replace(extendedExtension, "")) + { + case "editmodulecontrol.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + case "importmoduledefinition.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + case "timezoneeditor.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + default: + filePath = ""; + break; + } + break; + case "modules": + filePath = "Admin\\Modules\\App_LocalResources"; + break; + case "packages": + filePath = "DesktopModules\\Admin\\Extensions\\App_LocalResources"; + break; + case "portal": + switch (fileName.Replace(extendedExtension, "")) + { + case "editportalalias.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "portalalias.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "portals.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "privacy.ascx": + filePath = "Admin\\Portal\\App_LocalResources"; + break; + case "signup.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "sitesettings.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "sitewizard.ascx": + filePath = "DesktopModules\\Admin\\SiteWizard\\App_LocalResources"; + break; + case "sql.ascx": + filePath = "DesktopModules\\Admin\\SQL\\App_LocalResources"; + break; + case "systemmessages.ascx": + filePath = ""; + break; + case "template.ascx": + filePath = "DesktopModules\\Admin\\Portals\\App_LocalResources"; + break; + case "terms.ascx": + filePath = "Admin\\Portal\\App_LocalResources"; + break; + } + break; + case "scheduling": + filePath = "DesktopModules\\Admin\\Scheduler\\App_LocalResources"; + break; + case "search": + switch (fileName.Replace(extendedExtension, "")) + { + case "inputsettings.ascx": + filePath = "DesktopModules\\Admin\\SearchInput\\App_LocalResources"; + break; + case "resultssettings.ascx": + filePath = "DesktopModules\\Admin\\SearchResults\\App_LocalResources"; + break; + case "searchadmin.ascx": + filePath = "DesktopModules\\Admin\\SearchAdmin\\App_LocalResources"; + break; + case "searchinput.ascx": + filePath = "DesktopModules\\Admin\\SearchInput\\App_LocalResources"; + break; + case "searchresults.ascx": + filePath = "DesktopModules\\Admin\\SearchResults\\App_LocalResources"; + break; + } + break; + case "security": + switch (fileName.Replace(extendedExtension, "")) + { + case "accessdenied.ascx": + filePath = "Admin\\Security\\App_LocalResources"; + break; + case "authenticationsettings.ascx": + filePath = ""; + break; + case "editgroups.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "editroles.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "register.ascx": + filePath = ""; + break; + case "roles.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "securityroles.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "sendpassword.ascx": + filePath = "Admin\\Security\\App_LocalResources"; + break; + case "signin.ascx": + filePath = ""; + break; + } + break; + case "skins": + switch (fileName.Replace(extendedExtension, "")) + { + case "attributes.ascx": + filePath = "DesktopModules\\Admin\\SkinDesigner\\App_LocalResources"; + break; + case "editskins.ascx": + filePath = "DesktopModules\\Admin\\Extensions\\Editors\\App_LocalResources"; + break; + default: + filePath = "Admin\\Skins\\App_LocalResources"; + break; + } + break; + case "syndication": + filePath = "DesktopModules\\Admin\\FeedExplorer\\App_LocalResources"; + break; + case "tabs": + switch (fileName.Replace(extendedExtension, "")) + { + case "export.ascx": + filePath = "Admin\\Tabs\\App_LocalResources"; + break; + case "import.ascx": + filePath = "Admin\\Tabs\\App_LocalResources"; + break; + case "managetabs.ascx": + filePath = "DesktopModules\\Admin\\Tabs\\App_LocalResources"; + break; + case "recyclebin.ascx": + filePath = "DesktopModules\\Admin\\RecycleBin\\App_LocalResources"; + break; + case "tabs.ascx": + filePath = "DesktopModules\\Admin\\Tabs\\App_LocalResources"; + break; + } + break; + case "users": + switch (fileName.Replace(extendedExtension, "")) + { + case "bulkemail.ascx": + filePath = "DesktopModules\\Admin\\Newsletters\\App_LocalResources"; + fileName = "Newsletter.ascx" + extendedExtension; + break; + case "editprofiledefinition.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "manageusers.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "memberservices.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "membership.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "password.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "profile.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "profiledefinitions.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "user.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "users.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "usersettings.ascx": + filePath = "DesktopModules\\Admin\\Security\\App_LocalResources"; + break; + case "viewprofile.ascx": + filePath = "Admin\\Users\\App_LocalResources"; + break; + } + break; + case "vendors": + switch (fileName.Replace(extendedExtension, "")) + { + case "adsense.ascx": + filePath = ""; + break; + case "editadsense.ascx": + filePath = ""; + break; + case "affiliates.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + case "banneroptions.ascx": + filePath = "DesktopModules\\Admin\\Banners\\App_LocalResources"; + break; + case "banners.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + case "displaybanners.ascx": + filePath = "DesktopModules\\Admin\\Banners\\App_LocalResources"; + break; + case "editaffiliate.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + case "editbanner.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + case "editvendors.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + case "vendors.ascx": + filePath = "DesktopModules\\Admin\\Vendors\\App_LocalResources"; + break; + } + break; + } + break; + case "LocalResource": + filePath = Path.Combine("DesktopModules", Path.Combine(moduleName, "App_LocalResources")); + //Two assumptions are made here + //1. Core files appear in the package before extension files + //2. Module packages only include one module + if (!_IsCore && _LanguagePack == null) + { + //Check if language is installed + Locale locale = LocaleController.Instance.GetLocale(_Language.Code); + if (locale == null) + { + LegacyError = "CoreLanguageError"; + } + else + { + //Attempt to figure out the Extension + foreach (KeyValuePair kvp in + DesktopModuleController.GetDesktopModules(Null.NullInteger)) + { + if (kvp.Value.FolderName.ToLowerInvariant() == moduleName) + { + //Found Module - Get Package + PackageInfo dependentPackage = PackageController.GetPackage(kvp.Value.PackageID); + Package.Name += "_" + dependentPackage.Name; + Package.FriendlyName += " " + dependentPackage.FriendlyName; + _LanguagePack = new LanguagePackInfo(); + _LanguagePack.DependentPackageID = dependentPackage.PackageID; + _LanguagePack.LanguageID = locale.LanguageId; + break; + } + } + if (_LanguagePack == null) + { + LegacyError = "DependencyError"; + } + } + } + break; + case "ProviderResource": + filePath = Path.Combine("Providers", Path.Combine(moduleName, "App_LocalResources")); + break; + case "InstallResource": + filePath = "Install\\App_LocalResources"; + break; + } + if (!string.IsNullOrEmpty(filePath)) + { + AddFile(Path.Combine(filePath, fileName), sourceFileName); + } + } + } + + #endregion + + #region "Protected methods" + + protected override void GetFiles(bool includeSource, bool includeAppCode) + { + //Language file starts at the root + ParseFolder(Path.Combine(Globals.ApplicationMapPath, BasePath), Globals.ApplicationMapPath); + } + + protected override void ParseFiles(DirectoryInfo folder, string rootPath) + { + if (LanguagePack.PackageType == LanguagePackType.Core) + { + if (folder.FullName.ToLowerInvariant().Contains("desktopmodules") && !folder.FullName.ToLowerInvariant().Contains("admin") || folder.FullName.ToLowerInvariant().Contains("providers")) + { + return; + } + if (folder.FullName.ToLowerInvariant().Contains("install") && folder.FullName.ToLowerInvariant().Contains("temp")) + { + return; + } + } + if (folder.Name.ToLowerInvariant() == "app_localresources" || folder.Name.ToLowerInvariant() == "app_globalresources" || folder.Name.ToLowerInvariant() =="_default") + { + //Add the Files in the Folder + FileInfo[] files = folder.GetFiles(); + foreach (FileInfo file in files) + { + string filePath = folder.FullName.Replace(rootPath, ""); + if (filePath.StartsWith("\\")) + { + filePath = filePath.Substring(1); + } + if (file.Name.ToLowerInvariant().Contains(Language.Code.ToLowerInvariant()) || (Language.Code.ToLowerInvariant() == "en-us" && !file.Name.Contains("-"))) + { + AddFile(Path.Combine(filePath, file.Name)); + } + } + } + } + + protected override void WriteFilesToManifest(XmlWriter writer) + { + LanguageComponentWriter languageFileWriter; + if (LanguagePack == null) + { + languageFileWriter = new LanguageComponentWriter(Language, BasePath, Files, Package); + } + else + { + languageFileWriter = new LanguageComponentWriter(LanguagePack, BasePath, Files, Package); + } + languageFileWriter.WriteManifest(writer); + } + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/LibraryPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/LibraryPackageWriter.cs new file mode 100644 index 00000000000..a264ddcedc7 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/LibraryPackageWriter.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The LibraryPackageWriter class + /// + /// + /// + /// + /// [cnurse] 11/07/2008 created + /// + /// ----------------------------------------------------------------------------- + public class LibraryPackageWriter : PackageWriterBase + { + public LibraryPackageWriter(PackageInfo package) : base(package) + { + BasePath = "DesktopModules\\Libraries"; + AssemblyPath = "bin"; + } + + protected override void GetFiles(bool includeSource, bool includeAppCode) + { + base.GetFiles(includeSource, false); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ModulePackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ModulePackageWriter.cs new file mode 100644 index 00000000000..5aeeef6441d --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ModulePackageWriter.cs @@ -0,0 +1,422 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ModulePackageWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ModulePackageWriter : PackageWriterBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModulePackageWriter)); + #region "Constructors" + + public ModulePackageWriter(XPathNavigator manifestNav, InstallerInfo installer) + { + DesktopModule = new DesktopModuleInfo(); + + //Create a Package + Package = new PackageInfo(installer); + + ReadLegacyManifest(manifestNav, true); + + Package.Name = DesktopModule.ModuleName; + Package.FriendlyName = DesktopModule.FriendlyName; + Package.Description = DesktopModule.Description; + if (!string.IsNullOrEmpty(DesktopModule.Version)) + { + Package.Version = new Version(DesktopModule.Version); + } + + Package.PackageType = "Module"; + + LegacyUtil.ParsePackageName(Package); + + Initialize(DesktopModule.FolderName); + } + + public ModulePackageWriter(DesktopModuleInfo desktopModule, XPathNavigator manifestNav, PackageInfo package) : base(package) + { + DesktopModule = desktopModule; + + Initialize(desktopModule.FolderName); + if (manifestNav != null) + { + ReadLegacyManifest(manifestNav.SelectSingleNode("folders/folder"), false); + } + string physicalFolderPath = Path.Combine(Globals.ApplicationMapPath, BasePath); + ProcessModuleFolders(physicalFolderPath, physicalFolderPath); + } + + public ModulePackageWriter(PackageInfo package) : base(package) + { + DesktopModule = DesktopModuleController.GetDesktopModuleByPackageID(package.PackageID); + Initialize(DesktopModule.FolderName); + } + + public ModulePackageWriter(DesktopModuleInfo desktopModule, PackageInfo package) : base(package) + { + DesktopModule = desktopModule; + Initialize(desktopModule.FolderName); + } + + #endregion + + #region "Protected Properties" + + protected override Dictionary Dependencies + { + get + { + var dependencies = new Dictionary(); + if (!string.IsNullOrEmpty(DesktopModule.Dependencies)) + { + dependencies["type"] = DesktopModule.Dependencies; + } + if (!string.IsNullOrEmpty(DesktopModule.Permissions)) + { + dependencies["permission"] = DesktopModule.Permissions; + } + return dependencies; + } + } + + #endregion + + #region "Public Properties" + + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Desktop Module + /// + /// A DesktopModuleInfo object + /// + /// [cnurse] 02/01/2008 created + /// + /// ----------------------------------------------------------------------------- + public DesktopModuleInfo DesktopModule { get; set; } + + #endregion + + #region "Private Methods" + + private void Initialize(string folder) + { + BasePath = Path.Combine("DesktopModules", folder).Replace("/", "\\"); + AppCodePath = Path.Combine("App_Code", folder).Replace("/", "\\"); + AssemblyPath = "bin"; + } + + private static void ProcessControls(XPathNavigator controlNav, string moduleFolder, ModuleDefinitionInfo definition) + { + var moduleControl = new ModuleControlInfo(); + + moduleControl.ControlKey = Util.ReadElement(controlNav, "key"); + moduleControl.ControlTitle = Util.ReadElement(controlNav, "title"); + + //Write controlSrc + string controlSrc = Util.ReadElement(controlNav, "src"); + if (!(controlSrc.ToLower().StartsWith("desktopmodules") || !controlSrc.ToLower().EndsWith(".ascx"))) + { + //this code allows a developer to reference an ASCX file in a different folder than the module folder ( good for ASCX files shared between modules where you want only a single copy ) + //or it allows the developer to use webcontrols rather than usercontrols + + controlSrc = Path.Combine("DesktopModules", Path.Combine(moduleFolder, controlSrc)); + } + controlSrc = controlSrc.Replace('\\', '/'); + moduleControl.ControlSrc = controlSrc; + + moduleControl.IconFile = Util.ReadElement(controlNav, "iconfile"); + + string controlType = Util.ReadElement(controlNav, "type"); + if (!string.IsNullOrEmpty(controlType)) + { + try + { + moduleControl.ControlType = (SecurityAccessLevel) TypeDescriptor.GetConverter(typeof (SecurityAccessLevel)).ConvertFromString(controlType); + } + catch (Exception exc) + { + Logger.Error(exc); + + throw new Exception(Util.EXCEPTION_Type); + } + } + string viewOrder = Util.ReadElement(controlNav, "vieworder"); + if (!string.IsNullOrEmpty(viewOrder)) + { + moduleControl.ViewOrder = int.Parse(viewOrder); + } + moduleControl.HelpURL = Util.ReadElement(controlNav, "helpurl"); + string supportsPartialRendering = Util.ReadElement(controlNav, "supportspartialrendering"); + if (!string.IsNullOrEmpty(supportsPartialRendering)) + { + moduleControl.SupportsPartialRendering = bool.Parse(supportsPartialRendering); + } + string supportsPopUps = Util.ReadElement(controlNav, "supportspopups"); + if (!string.IsNullOrEmpty(supportsPopUps)) + { + moduleControl.SupportsPartialRendering = bool.Parse(supportsPopUps); + } + + definition.ModuleControls[moduleControl.ControlKey] = moduleControl; + } + + private void ProcessModuleFiles(string folder, string basePath) + { + //we are going to drill down through the folders to add the files + foreach (string fileName in Directory.GetFiles(folder)) + { + string name = fileName.Replace(basePath + "\\", ""); + AddFile(name, name); + } + } + + private void ProcessModuleFolders(string folder, string basePath) + { + //Process Folders recursively + foreach (string directoryName in Directory.GetDirectories(folder)) + { + ProcessModuleFolders(directoryName, basePath); + } + + //process files + ProcessModuleFiles(folder, basePath); + } + + private void ProcessModules(XPathNavigator moduleNav, string moduleFolder) + { + var definition = new ModuleDefinitionInfo(); + + definition.FriendlyName = Util.ReadElement(moduleNav, "friendlyname"); + string cacheTime = Util.ReadElement(moduleNav, "cachetime"); + if (!string.IsNullOrEmpty(cacheTime)) + { + definition.DefaultCacheTime = int.Parse(cacheTime); + } + + //Process legacy controls Node + foreach (XPathNavigator controlNav in moduleNav.Select("controls/control")) + { + ProcessControls(controlNav, moduleFolder, definition); + } + DesktopModule.ModuleDefinitions[definition.FriendlyName] = definition; + } + + private void ReadLegacyManifest(XPathNavigator folderNav, bool processModule) + { + if (processModule) + { + //Version 2 of legacy manifest + string name = Util.ReadElement(folderNav, "name"); + DesktopModule.FolderName = name; + DesktopModule.ModuleName = name; + DesktopModule.FriendlyName = name; + string folderName = Util.ReadElement(folderNav, "foldername"); + if (!string.IsNullOrEmpty(folderName)) + { + DesktopModule.FolderName = folderName; + } + if (string.IsNullOrEmpty(DesktopModule.FolderName)) + { + DesktopModule.FolderName = "MyModule"; + } + string friendlyname = Util.ReadElement(folderNav, "friendlyname"); + if (!string.IsNullOrEmpty(friendlyname)) + { + DesktopModule.FriendlyName = friendlyname; + DesktopModule.ModuleName = friendlyname; + } + string iconFile = Util.ReadElement(folderNav, "iconfile"); + if (!string.IsNullOrEmpty(iconFile)) + { + Package.IconFile = iconFile; + } + string modulename = Util.ReadElement(folderNav, "modulename"); + if (!string.IsNullOrEmpty(modulename)) + { + DesktopModule.ModuleName = modulename; + } + string permissions = Util.ReadElement(folderNav, "permissions"); + if (!string.IsNullOrEmpty(permissions)) + { + DesktopModule.Permissions = permissions; + } + string dependencies = Util.ReadElement(folderNav, "dependencies"); + if (!string.IsNullOrEmpty(dependencies)) + { + DesktopModule.Dependencies = dependencies; + } + DesktopModule.Version = Util.ReadElement(folderNav, "version", "01.00.00"); + DesktopModule.Description = Util.ReadElement(folderNav, "description"); + DesktopModule.BusinessControllerClass = Util.ReadElement(folderNav, "businesscontrollerclass"); + + //Process legacy modules Node + foreach (XPathNavigator moduleNav in folderNav.Select("modules/module")) + { + ProcessModules(moduleNav, DesktopModule.FolderName); + } + } + + //Process legacy files Node + foreach (XPathNavigator fileNav in folderNav.Select("files/file")) + { + string fileName = Util.ReadElement(fileNav, "name"); + string filePath = Util.ReadElement(fileNav, "path"); + + //In Legacy Modules the file can be physically located in the Root of the zip folder - or in the path/file location + //First test the folder + string sourceFileName; + if (filePath.Contains("[app_code]")) + { + //Special case for App_code - files can be in App_Code\ModuleName or root + sourceFileName = Path.Combine(filePath, fileName).Replace("[app_code]", "App_Code\\" + DesktopModule.FolderName); + } + else + { + sourceFileName = Path.Combine(filePath, fileName); + } + string tempFolder = Package.InstallerInfo.TempInstallFolder; + if (!File.Exists(Path.Combine(tempFolder, sourceFileName))) + { + sourceFileName = fileName; + } + + //In Legacy Modules the assembly is always in "bin" - ignore the path element + if (fileName.ToLower().EndsWith(".dll")) + { + AddFile("bin/" + fileName, sourceFileName); + } + else + { + AddFile(Path.Combine(filePath, fileName), sourceFileName); + } + } + + //Process resource file Node + if (!string.IsNullOrEmpty(Util.ReadElement(folderNav, "resourcefile"))) + { + AddResourceFile(new InstallFile(Util.ReadElement(folderNav, "resourcefile"), Package.InstallerInfo)); + } + } + + private void WriteEventMessage(XmlWriter writer) + { + //Start Start eventMessage + writer.WriteStartElement("eventMessage"); + + //Write Processor Type + writer.WriteElementString("processorType", "DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke"); + + //Write Processor Type + writer.WriteElementString("processorCommand", "UpgradeModule"); + + //Write Event Message Attributes + writer.WriteStartElement("attributes"); + + //Write businessControllerClass Attribute + writer.WriteElementString("businessControllerClass", DesktopModule.BusinessControllerClass); + + //Write businessControllerClass Attribute + writer.WriteElementString("desktopModuleID", "[DESKTOPMODULEID]"); + + //Write upgradeVersionsList Attribute + string upgradeVersions = Null.NullString; + Versions.Sort(); + foreach (string version in Versions) + { + upgradeVersions += version + ","; + } + if (upgradeVersions.Length > 1) + { + upgradeVersions = upgradeVersions.Remove(upgradeVersions.Length - 1, 1); + } + writer.WriteElementString("upgradeVersionsList", upgradeVersions); + + //End end of Event Message Attribues + writer.WriteEndElement(); + + //End component Element + writer.WriteEndElement(); + } + + private void WriteModuleComponent(XmlWriter writer) + { + //Start component Element + writer.WriteStartElement("component"); + writer.WriteAttributeString("type", "Module"); + + //Write Module Manifest + if (AppCodeFiles.Count > 0) + { + DesktopModule.CodeSubDirectory = DesktopModule.FolderName; + } + CBO.SerializeObject(DesktopModule, writer); + + //Write EventMessage + if (!string.IsNullOrEmpty(DesktopModule.BusinessControllerClass)) + { + WriteEventMessage(writer); + } + + //End component Element + writer.WriteEndElement(); + } + + #endregion + + #region "Protected Methods" + + protected override void WriteManifestComponent(XmlWriter writer) + { + //Write Module Component + WriteModuleComponent(writer); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Installer/Writers/PackageWriterBase.cs b/DNN Platform/Library/Services/Installer/Writers/PackageWriterBase.cs new file mode 100644 index 00000000000..7cc0fa30296 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/PackageWriterBase.cs @@ -0,0 +1,843 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; + +using ICSharpCode.SharpZipLib.Zip; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class PackageWriterBase + { +#region "Private Members" + + private readonly Dictionary _AppCodeFiles = new Dictionary(); + private readonly Dictionary _Assemblies = new Dictionary(); + private readonly SortedList _CleanUpFiles = new SortedList(); + private readonly Dictionary _Files = new Dictionary(); + private readonly Dictionary _Resources = new Dictionary(); + private readonly Dictionary _Scripts = new Dictionary(); + private readonly List _Versions = new List(); + private string _BasePath = Null.NullString; + private PackageInfo _Package; + + #endregion + + #region "Constructors" + + protected PackageWriterBase() + { + } + + public PackageWriterBase(PackageInfo package) + { + _Package = package; + _Package.AttachInstallerInfo(new InstallerInfo()); + } + + #endregion + + #region "Protected Properties" + + protected virtual Dictionary Dependencies + { + get + { + return new Dictionary(); + } + } + + #endregion + + #region "Public Properties" + + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of AppCodeFiles that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 02/12/2008 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary AppCodeFiles + { + get + { + return _AppCodeFiles; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Path for the Package's app code files + /// + /// A String + /// + /// [cnurse] 02/12/2008 created + /// + /// ----------------------------------------------------------------------------- + public string AppCodePath { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Assemblies that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Assemblies + { + get + { + return _Assemblies; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Path for the Package's assemblies + /// + /// A String + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public string AssemblyPath { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Base Path for the Package + /// + /// A String + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public string BasePath + { + get + { + return _BasePath; + } + set + { + _BasePath = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of CleanUpFiles that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 02/21/2008 created + /// + /// ----------------------------------------------------------------------------- + public SortedList CleanUpFiles + { + get + { + return _CleanUpFiles; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Files that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Files + { + get + { + return _Files; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets whether a project file is found in the folder + /// + /// A String + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public bool HasProjectFile { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to include Assemblies + /// + /// A Boolean + /// + /// [cnurse] 02/06/2008 created + /// + /// ----------------------------------------------------------------------------- + public virtual bool IncludeAssemblies + { + get + { + return true; + } + } + + /// + /// Gets and sets whether there are any errors in parsing legacy packages + /// + /// + /// + /// + public string LegacyError { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Logger + /// + /// An Logger object + /// + /// [cnurse] 07/31/2007 created + /// + /// ----------------------------------------------------------------------------- + public Logger Log + { + get + { + return Package.Log; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated Package + /// + /// An PackageInfo object + /// + /// [cnurse] 07/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public PackageInfo Package + { + get + { + return _Package; + } + set + { + _Package = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Resources that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Resources + { + get + { + return _Resources; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Scripts that should be included in the Package + /// + /// A Dictionary(Of String, InstallFile) + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public Dictionary Scripts + { + get + { + return _Scripts; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a List of Versions that should be included in the Package + /// + /// A List(Of String) + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public List Versions + { + get + { + return _Versions; + } + } + + #endregion + + #region "Private Methods" + + private void AddFilesToZip(ZipOutputStream stream, IDictionary files, string basePath) + { + foreach (InstallFile packageFile in files.Values) + { + string filepath; + if (string.IsNullOrEmpty(basePath)) + { + filepath = Path.Combine(Globals.ApplicationMapPath, packageFile.FullName); + } + else + { + filepath = Path.Combine(Path.Combine(Globals.ApplicationMapPath, basePath), packageFile.FullName.Replace(basePath + "\\", "")); + } + if (File.Exists(filepath)) + { + string packageFilePath = packageFile.Path; + if (!string.IsNullOrEmpty(basePath)) + { + packageFilePath = packageFilePath.Replace(basePath + "\\", ""); + } + FileSystemUtils.AddToZip(ref stream, filepath, packageFile.Name, packageFilePath); + Log.AddInfo(string.Format(Util.WRITER_SavedFile, packageFile.FullName)); + } + } + } + + private void CreateZipFile(string zipFileName) + { + int CompressionLevel = 9; + var zipFile = new FileInfo(zipFileName); + + string ZipFileShortName = zipFile.Name; + + FileStream strmZipFile = null; + Log.StartJob(Util.WRITER_CreatingPackage); + try + { + Log.AddInfo(string.Format(Util.WRITER_CreateArchive, ZipFileShortName)); + strmZipFile = File.Create(zipFileName); + ZipOutputStream strmZipStream = null; + try + { + strmZipStream = new ZipOutputStream(strmZipFile); + strmZipStream.SetLevel(CompressionLevel); + + //Add Files To zip + AddFilesToZip(strmZipStream, _Assemblies, ""); + AddFilesToZip(strmZipStream, _AppCodeFiles, AppCodePath); + AddFilesToZip(strmZipStream, _Files, BasePath); + AddFilesToZip(strmZipStream, _CleanUpFiles, BasePath); + AddFilesToZip(strmZipStream, _Resources, BasePath); + AddFilesToZip(strmZipStream, _Scripts, BasePath); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + Log.AddFailure(string.Format(Util.WRITER_SaveFileError, ex)); + } + finally + { + if (strmZipStream != null) + { + strmZipStream.Finish(); + strmZipStream.Close(); + } + } + Log.EndJob(Util.WRITER_CreatedPackage); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + Log.AddFailure(string.Format(Util.WRITER_SaveFileError, ex)); + } + finally + { + if (strmZipFile != null) + { + strmZipFile.Close(); + } + } + } + + private void WritePackageEndElement(XmlWriter writer) + { + //Close components Element + writer.WriteEndElement(); + + //Close package Element + writer.WriteEndElement(); + } + + private void WritePackageStartElement(XmlWriter writer) + { + //Start package Element + writer.WriteStartElement("package"); + writer.WriteAttributeString("name", Package.Name); + writer.WriteAttributeString("type", Package.PackageType); + writer.WriteAttributeString("version", Package.Version.ToString(3)); + + //Write FriendlyName + writer.WriteElementString("friendlyName", Package.FriendlyName); + + //Write Description + writer.WriteElementString("description", Package.Description); + writer.WriteElementString("iconFile", Util.ParsePackageIconFileName(Package)); + + //Write Author + writer.WriteStartElement("owner"); + + writer.WriteElementString("name", Package.Owner); + writer.WriteElementString("organization", Package.Organization); + writer.WriteElementString("url", Package.Url); + writer.WriteElementString("email", Package.Email); + + //Write Author End + writer.WriteEndElement(); + + //Write License + writer.WriteElementString("license", Package.License); + + //Write Release Notes + writer.WriteElementString("releaseNotes", Package.ReleaseNotes); + + //Write Dependencies + if (Dependencies.Count > 0) + { + writer.WriteStartElement("dependencies"); + foreach (KeyValuePair kvp in Dependencies) + { + writer.WriteStartElement("dependency"); + writer.WriteAttributeString("type", kvp.Key); + writer.WriteString(kvp.Value); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + //Write components Element + writer.WriteStartElement("components"); + } + + #endregion + + #region "Protected Methods" + + protected virtual void AddFile(string fileName) + { + AddFile(new InstallFile(fileName, Package.InstallerInfo)); + } + + protected virtual void AddFile(string fileName, string sourceFileName) + { + AddFile(new InstallFile(fileName, sourceFileName, Package.InstallerInfo)); + } + + protected virtual void ConvertLegacyManifest(XPathNavigator legacyManifest, XmlWriter writer) + { + } + + protected virtual void GetFiles(bool includeSource, bool includeAppCode) + { + string baseFolder = Path.Combine(Globals.ApplicationMapPath, BasePath); + if (Directory.Exists(baseFolder)) + { + //Create the DirectoryInfo object + var folderInfo = new DirectoryInfo(baseFolder); + + //Get the Project File in the folder + FileInfo[] files = folderInfo.GetFiles("*.??proj"); + + if (files.Length == 0) //Assume Dynamic (App_Code based) Module + { + //Add the files in the DesktopModules Folder + ParseFolder(baseFolder, baseFolder); + + //Add the files in the AppCode Folder + if (includeAppCode) + { + string appCodeFolder = Path.Combine(Globals.ApplicationMapPath, AppCodePath); + ParseFolder(appCodeFolder, appCodeFolder); + } + } + else //WAP Project File is present + { + HasProjectFile = true; + + //Parse the Project files (probably only one) + foreach (FileInfo projFile in files) + { + ParseProjectFile(projFile, includeSource); + } + } + } + } + + protected virtual void ParseFiles(DirectoryInfo folder, string rootPath) + { + //Add the Files in the Folder + FileInfo[] files = folder.GetFiles(); + foreach (FileInfo file in files) + { + string filePath = folder.FullName.Replace(rootPath, ""); + if (filePath.StartsWith("\\")) + { + filePath = filePath.Substring(1); + } + if (folder.FullName.ToLowerInvariant().Contains("app_code")) + { + filePath = "[app_code]" + filePath; + } + if (file.Extension.ToLowerInvariant() != ".dnn" && (file.Attributes & FileAttributes.Hidden) == 0) + { + AddFile(Path.Combine(filePath, file.Name)); + } + } + } + + protected virtual void ParseFolder(string folderName, string rootPath) + { + if (Directory.Exists(folderName)) + { + var folder = new DirectoryInfo(folderName); + + //Recursively parse the subFolders + DirectoryInfo[] subFolders = folder.GetDirectories(); + foreach (DirectoryInfo subFolder in subFolders) + { + if ((subFolder.Attributes & FileAttributes.Hidden) == 0) + { + ParseFolder(subFolder.FullName, rootPath); + } + } + + //Add the Files in the Folder + ParseFiles(folder, rootPath); + } + } + + protected void ParseProjectFile(FileInfo projFile, bool includeSource) + { + string fileName = ""; + + //Create an XPathDocument from the Xml + var doc = new XPathDocument(new FileStream(projFile.FullName, FileMode.Open, FileAccess.Read)); + XPathNavigator rootNav = doc.CreateNavigator(); + var manager = new XmlNamespaceManager(rootNav.NameTable); + manager.AddNamespace("proj", "http://schemas.microsoft.com/developer/msbuild/2003"); + rootNav.MoveToFirstChild(); + + XPathNavigator assemblyNav = rootNav.SelectSingleNode("proj:PropertyGroup/proj:AssemblyName", manager); + fileName = assemblyNav.Value; + XPathNavigator buildPathNav = rootNav.SelectSingleNode("proj:PropertyGroup/proj:OutputPath", manager); + string buildPath = buildPathNav.Value.Replace("..\\", ""); + buildPath = buildPath.Replace(AssemblyPath + "\\", ""); + AddFile(Path.Combine(buildPath, fileName + ".dll")); + + //Check for referenced assemblies + foreach (XPathNavigator itemNav in rootNav.Select("proj:ItemGroup/proj:Reference", manager)) + { + fileName = Util.ReadAttribute(itemNav, "Include"); + if (fileName.IndexOf(",") > -1) + { + fileName = fileName.Substring(0, fileName.IndexOf(",")); + } + if ( + !(fileName.ToLowerInvariant().StartsWith("system") || fileName.ToLowerInvariant().StartsWith("microsoft") || fileName.ToLowerInvariant() == "dotnetnuke" || + fileName.ToLowerInvariant() == "dotnetnuke.webutility" || fileName.ToLowerInvariant() == "dotnetnuke.webcontrols")) + { + AddFile(fileName + ".dll"); + } + } + + //Add all the files that are classified as None + foreach (XPathNavigator itemNav in rootNav.Select("proj:ItemGroup/proj:None", manager)) + { + fileName = Util.ReadAttribute(itemNav, "Include"); + AddFile(fileName); + } + + //Add all the files that are classified as Content + foreach (XPathNavigator itemNav in rootNav.Select("proj:ItemGroup/proj:Content", manager)) + { + fileName = Util.ReadAttribute(itemNav, "Include"); + AddFile(fileName); + } + + //Add all the files that are classified as Compile + if (includeSource) + { + foreach (XPathNavigator itemNav in rootNav.Select("proj:ItemGroup/proj:Compile", manager)) + { + fileName = Util.ReadAttribute(itemNav, "Include"); + AddFile(fileName); + } + } + } + + protected virtual void WriteFilesToManifest(XmlWriter writer) + { + var fileWriter = new FileComponentWriter(BasePath, Files, Package); + fileWriter.WriteManifest(writer); + } + + protected virtual void WriteManifestComponent(XmlWriter writer) + { + } + + #endregion + + #region "Public Methods" + + public virtual void AddFile(InstallFile file) + { + switch (file.Type) + { + case InstallFileType.AppCode: + _AppCodeFiles[file.FullName.ToLower()] = file; + break; + case InstallFileType.Assembly: + _Assemblies[file.FullName.ToLower()] = file; + break; + case InstallFileType.CleanUp: + _CleanUpFiles[file.FullName.ToLower()] = file; + break; + case InstallFileType.Script: + _Scripts[file.FullName.ToLower()] = file; + break; + default: + _Files[file.FullName.ToLower()] = file; + break; + } + if ((file.Type == InstallFileType.CleanUp || file.Type == InstallFileType.Script) && Regex.IsMatch(file.Name, Util.REGEX_Version)) + { + string version = Path.GetFileNameWithoutExtension(file.Name); + if (!_Versions.Contains(version)) + { + _Versions.Add(version); + } + } + } + + public void AddResourceFile(InstallFile file) + { + _Resources[file.FullName.ToLower()] = file; + } + + public void CreatePackage(string archiveName, string manifestName, string manifest, bool createManifest) + { + if (createManifest) + { + WriteManifest(manifestName, manifest); + } + AddFile(manifestName); + CreateZipFile(archiveName); + } + + public void GetFiles(bool includeSource) + { + //Call protected method that does the work + GetFiles(includeSource, true); + } + + /// + /// WriteManifest writes an existing manifest + /// + /// The name of the manifest file + /// The manifest + /// This overload takes a package manifest and writes it to a file + public void WriteManifest(string manifestName, string manifest) + { + XmlWriter writer = XmlWriter.Create(Path.Combine(Globals.ApplicationMapPath, Path.Combine(BasePath, manifestName)), XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)); + Log.StartJob(Util.WRITER_CreatingManifest); + WriteManifest(writer, manifest); + Log.EndJob(Util.WRITER_CreatedManifest); + } + + /// + /// WriteManifest writes a package manifest to an XmlWriter + /// + /// The XmlWriter + /// The manifest + /// This overload takes a package manifest and writes it to a Writer + public void WriteManifest(XmlWriter writer, string manifest) + { + WriteManifestStartElement(writer); + writer.WriteRaw(manifest); + + //Close Dotnetnuke Element + WriteManifestEndElement(writer); + + //Close Writer + writer.Close(); + } + + /// + /// WriteManifest writes the manifest assoicated with this PackageWriter to a string + /// + /// A flag that indicates whether to return the package element + /// as a fragment (True) or whether to add the outer dotnetnuke and packages elements (False) + /// The manifest as a string + /// + public string WriteManifest(bool packageFragment) + { + //Create a writer to create the processed manifest + var sb = new StringBuilder(); + XmlWriter writer = XmlWriter.Create(sb, XmlUtils.GetXmlWriterSettings(ConformanceLevel.Fragment)); + + WriteManifest(writer, packageFragment); + + //Close XmlWriter + writer.Close(); + + //Return new manifest + return sb.ToString(); + } + + public void WriteManifest(XmlWriter writer, bool packageFragment) + { + Log.StartJob(Util.WRITER_CreatingManifest); + + if (!packageFragment) + { + //Start dotnetnuke element + WriteManifestStartElement(writer); + } + + //Start package Element + WritePackageStartElement(writer); + + //write Script Component + if (Scripts.Count > 0) + { + var scriptWriter = new ScriptComponentWriter(BasePath, Scripts, Package); + scriptWriter.WriteManifest(writer); + } + + //write Clean Up Files Component + if (CleanUpFiles.Count > 0) + { + var cleanupFileWriter = new CleanupComponentWriter(BasePath, CleanUpFiles); + cleanupFileWriter.WriteManifest(writer); + } + + //Write the Custom Component + WriteManifestComponent(writer); + + //Write Assemblies Component + if (Assemblies.Count > 0) + { + var assemblyWriter = new AssemblyComponentWriter(AssemblyPath, Assemblies, Package); + assemblyWriter.WriteManifest(writer); + } + + //Write AppCode Files Component + if (AppCodeFiles.Count > 0) + { + var fileWriter = new FileComponentWriter(AppCodePath, AppCodeFiles, Package); + fileWriter.WriteManifest(writer); + } + + //write Files Component + if (Files.Count > 0) + { + WriteFilesToManifest(writer); + } + + //write ResourceFiles Component + if (Resources.Count > 0) + { + var fileWriter = new ResourceFileComponentWriter(BasePath, Resources, Package); + fileWriter.WriteManifest(writer); + } + + //Close Package + WritePackageEndElement(writer); + + if (!packageFragment) + { + //Close Dotnetnuke Element + WriteManifestEndElement(writer); + } + Log.EndJob(Util.WRITER_CreatedManifest); + } + + public static void WriteManifestEndElement(XmlWriter writer) + { + //Close packages Element + writer.WriteEndElement(); + + //Close root Element + writer.WriteEndElement(); + } + + public static void WriteManifestStartElement(XmlWriter writer) + { + //Start the new Root Element + writer.WriteStartElement("dotnetnuke"); + writer.WriteAttributeString("type", "Package"); + writer.WriteAttributeString("version", "5.0"); + + //Start packages Element + writer.WriteStartElement("packages"); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/PackageWriterFactory.cs b/DNN Platform/Library/Services/Installer/Writers/PackageWriterFactory.cs new file mode 100644 index 00000000000..6dfab982894 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/PackageWriterFactory.cs @@ -0,0 +1,105 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Common.Lists; +using DotNetNuke.Framework; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The PackageWriterFactory is a factory class that is used to instantiate the + /// appropriate Package Writer + /// + /// + /// + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public class PackageWriterFactory + { + #region "Public Shared Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The GetWriter method instantiates the relevant PackageWriter Installer + /// + /// The associated PackageInfo instance + /// + /// [cnurse] 01/31/2008 created + /// + /// ----------------------------------------------------------------------------- + public static PackageWriterBase GetWriter(PackageInfo package) + { + PackageWriterBase writer = null; + switch (package.PackageType) + { + case "Auth_System": + writer = new AuthenticationPackageWriter(package); + break; + case "Module": + writer = new ModulePackageWriter(package); + break; + case "Container": + writer = new ContainerPackageWriter(package); + break; + case "Skin": + writer = new SkinPackageWriter(package); + break; + case "CoreLanguagePack": + case "ExtensionLanguagePack": + writer = new LanguagePackWriter(package); + break; + case "SkinObject": + writer = new SkinControlPackageWriter(package); + break; + case "Provider": + writer = new ProviderPackageWriter(package); + break; + case "Library": + writer = new LibraryPackageWriter(package); + break; + case "Widget": + writer = new WidgetPackageWriter(package); + break; + default: + //PackageType is defined in the List + var listController = new ListController(); + ListEntryInfo entry = listController.GetListEntryInfo("PackageWriter", package.PackageType); + + if (entry != null && !string.IsNullOrEmpty(entry.Text)) + { + //The class for the Installer is specified in the Text property + writer = (PackageWriterBase) Reflection.CreateObject(entry.Text, "PackageWriter_" + entry.Value); + } + break; + } + return writer; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ProviderPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ProviderPackageWriter.cs new file mode 100644 index 00000000000..31a5dcde99e --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ProviderPackageWriter.cs @@ -0,0 +1,65 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ProviderPackageWriter class + /// + /// + /// + /// + /// [cnurse] 05/29/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ProviderPackageWriter : PackageWriterBase + { + public ProviderPackageWriter(PackageInfo package) : base(package) + { + XmlDocument configDoc = Config.Load(); + XPathNavigator providerNavigator = configDoc.CreateNavigator().SelectSingleNode("/configuration/dotnetnuke/*/providers/add[@name='" + package.Name + "']"); + string providerPath = Null.NullString; + if (providerNavigator != null) + { + providerPath = Util.ReadAttribute(providerNavigator, "providerPath"); + } + if (!string.IsNullOrEmpty(providerPath)) + { + BasePath = providerPath.Replace("~/", "").Replace("/", "\\"); + } + } + + protected override void GetFiles(bool includeSource, bool includeAppCode) + { + base.GetFiles(includeSource, false); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ResourceFileComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ResourceFileComponentWriter.cs new file mode 100644 index 00000000000..f00b226cc03 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ResourceFileComponentWriter.cs @@ -0,0 +1,110 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ResourceFileComponentWriter class handles creating the manifest for Resource + /// File Component(s) + /// + /// + /// + /// + /// [cnurse] 02/22/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ResourceFileComponentWriter : FileComponentWriter + { + /// ----------------------------------------------------------------------------- + /// + /// Constructs the ResourceFileComponentWriter + /// + /// The Base Path for the files + /// A Dictionary of files + /// + /// + /// [cnurse] 02/22/2008 created + /// + /// ----------------------------------------------------------------------------- + public ResourceFileComponentWriter(string basePath, Dictionary files, PackageInfo package) : base(basePath, files, package) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("resourceFiles") + /// + /// A String + /// + /// [cnurse] 02/22/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "resourceFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("ResourceFile") + /// + /// A String + /// + /// [cnurse] 02/22/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "ResourceFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("resourceFile") + /// + /// A String + /// + /// [cnurse] 02/22/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "resourceFile"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/ScriptComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/ScriptComponentWriter.cs new file mode 100644 index 00000000000..3d95d94c397 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/ScriptComponentWriter.cs @@ -0,0 +1,165 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The ScriptComponentWriter class handles creating the manifest for Script + /// Component(s) + /// + /// + /// + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + public class ScriptComponentWriter : FileComponentWriter + { + #region "Constructors" + + public ScriptComponentWriter(string basePath, Dictionary scripts, PackageInfo package) : base(basePath, scripts, package) + { + } + + #endregion + + #region "Public Properties" + + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("scripts") + /// + /// A String + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "scripts"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("Script") + /// + /// A String + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "Script"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("script") + /// + /// A String + /// + /// [cnurse] 02/11/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "script"; + } + } + + protected override void WriteFileElement(XmlWriter writer, InstallFile file) + { + Log.AddInfo(string.Format(Util.WRITER_AddFileToManifest, file.Name)); + string type = "Install"; + string version = Null.NullString; + string fileName = Path.GetFileNameWithoutExtension(file.Name); + if (fileName.ToLower() == "uninstall") //UnInstall.SqlDataprovider + { + type = "UnInstall"; + version = Package.Version.ToString(3); + } + else if (fileName.ToLower() == "install") //Install.SqlDataprovider + { + type = "Install"; + version = new Version(0, 0, 0).ToString(3); + } + else if (fileName.StartsWith("Install")) //Install.xx.xx.xx.SqlDataprovider + { + type = "Install"; + version = fileName.Replace("Install.", ""); + } + else //xx.xx.xx.SqlDataprovider + { + type = "Install"; + version = fileName; + } + + //Start file Element + writer.WriteStartElement(ItemNodeName); + writer.WriteAttributeString("type", type); + + //Write path + if (!string.IsNullOrEmpty(file.Path)) + { + writer.WriteElementString("path", file.Path); + } + + //Write name + writer.WriteElementString("name", file.Name); + + //'Write sourceFileName + if (!string.IsNullOrEmpty(file.SourceFileName)) + { + writer.WriteElementString("sourceFileName", file.SourceFileName); + } + + //Write Version + writer.WriteElementString("version", version); + + //Close file Element + writer.WriteEndElement(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/SkinComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/SkinComponentWriter.cs new file mode 100644 index 00000000000..875fa8a2267 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/SkinComponentWriter.cs @@ -0,0 +1,162 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Xml; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinComponentWriter class handles creating the manifest for Skin Component(s) + /// + /// + /// + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public class SkinComponentWriter : FileComponentWriter + { + #region "Private Members" + + private readonly string _SkinName; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs the SkinComponentWriter + /// + /// The name of the Skin + /// The Base Path for the files + /// A Dictionary of files + /// Package Info. + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public SkinComponentWriter(string skinName, string basePath, Dictionary files, PackageInfo package) : base(basePath, files, package) + { + _SkinName = skinName; + } + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("skinFiles") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "skinFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("Skin") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "Skin"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("skinFile") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "skinFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the SkinName Node ("skinName") + /// + /// A String + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected virtual string SkinNameNodeName + { + get + { + return "skinName"; + } + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// The WriteCustomManifest method writes the custom manifest items (that subclasses + /// of FileComponentWriter may need) + /// + /// The Xmlwriter to use + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void WriteCustomManifest(XmlWriter writer) + { + writer.WriteElementString(SkinNameNodeName, _SkinName); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/SkinControlPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/SkinControlPackageWriter.cs new file mode 100644 index 00000000000..487ff404e5e --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/SkinControlPackageWriter.cs @@ -0,0 +1,154 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinControlPackageWriter class + /// + /// + /// + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public class SkinControlPackageWriter : PackageWriterBase + { + #region "Constructors" + + public SkinControlPackageWriter(PackageInfo package) : base(package) + { + SkinControl = SkinControlController.GetSkinControlByPackageID(package.PackageID); + BasePath = Path.Combine("DesktopModules", package.Name.ToLower()).Replace("/", "\\"); + AppCodePath = Path.Combine("App_Code", package.Name.ToLower()).Replace("/", "\\"); + } + + public SkinControlPackageWriter(SkinControlInfo skinControl, PackageInfo package) : base(package) + { + SkinControl = skinControl; + BasePath = Path.Combine("DesktopModules", package.Name.ToLower()).Replace("/", "\\"); + AppCodePath = Path.Combine("App_Code", package.Name.ToLower()).Replace("/", "\\"); + } + + public SkinControlPackageWriter(XPathNavigator manifestNav, InstallerInfo installer) + { + SkinControl = new SkinControlInfo(); + + //Create a Package + Package = new PackageInfo(installer); + + ReadLegacyManifest(manifestNav, true); + + Package.Description = Null.NullString; + Package.Version = new Version(1, 0, 0); + Package.PackageType = "SkinObject"; + Package.License = Util.PACKAGE_NoLicense; + + BasePath = Path.Combine("DesktopModules", Package.Name.ToLower()).Replace("/", "\\"); + AppCodePath = Path.Combine("App_Code", Package.Name.ToLower()).Replace("/", "\\"); + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the associated SkinControl + /// + /// A SkinControlInfo object + /// + /// [cnurse] 03/28/2008 created + /// + /// ----------------------------------------------------------------------------- + public SkinControlInfo SkinControl { get; set; } + + #endregion + + private void ReadLegacyManifest(XPathNavigator legacyManifest, bool processModule) + { + XPathNavigator folderNav = legacyManifest.SelectSingleNode("folders/folder"); + + if (processModule) + { + Package.Name = Util.ReadElement(folderNav, "name"); + Package.FriendlyName = Package.Name; + + //Process legacy controls Node + foreach (XPathNavigator controlNav in folderNav.Select("modules/module/controls/control")) + { + SkinControl.ControlKey = Util.ReadElement(controlNav, "key"); + SkinControl.ControlSrc = Path.Combine(Path.Combine("DesktopModules", Package.Name.ToLower()), Util.ReadElement(controlNav, "src")).Replace("\\", "/"); + string supportsPartialRendering = Util.ReadElement(controlNav, "supportspartialrendering"); + if (!string.IsNullOrEmpty(supportsPartialRendering)) + { + SkinControl.SupportsPartialRendering = bool.Parse(supportsPartialRendering); + } + } + } + + //Process legacy files Node + foreach (XPathNavigator fileNav in folderNav.Select("files/file")) + { + string fileName = Util.ReadElement(fileNav, "name"); + string filePath = Util.ReadElement(fileNav, "path"); + + AddFile(Path.Combine(filePath, fileName), fileName); + } + + //Process resource file Node + if (!string.IsNullOrEmpty(Util.ReadElement(folderNav, "resourcefile"))) + { + AddFile(Util.ReadElement(folderNav, "resourcefile")); + } + } + + #region "Protected Methods" + + protected override void WriteManifestComponent(XmlWriter writer) + { + //Start component Element + writer.WriteStartElement("component"); + writer.WriteAttributeString("type", "SkinObject"); + + //Write SkinControl Manifest + CBO.SerializeObject(SkinControl, writer); + + //End component Element + writer.WriteEndElement(); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/SkinPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/SkinPackageWriter.cs new file mode 100644 index 00000000000..88c179d5804 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/SkinPackageWriter.cs @@ -0,0 +1,158 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Xml; + +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.UI.Skins; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinPackageWriter class + /// + /// + /// + /// + /// [cnurse] 01/30/2008 created + /// + /// ----------------------------------------------------------------------------- + public class SkinPackageWriter : PackageWriterBase + { + #region "Private Members" + + private readonly SkinPackageInfo _SkinPackage; + private readonly string _SubFolder; + + #endregion + + #region "Constructors" + + public SkinPackageWriter(PackageInfo package) : base(package) + { + _SkinPackage = SkinController.GetSkinByPackageID(package.PackageID); + SetBasePath(); + } + + public SkinPackageWriter(SkinPackageInfo skinPackage, PackageInfo package) : base(package) + { + _SkinPackage = skinPackage; + SetBasePath(); + } + + public SkinPackageWriter(SkinPackageInfo skinPackage, PackageInfo package, string basePath) : base(package) + { + _SkinPackage = skinPackage; + BasePath = basePath; + } + + public SkinPackageWriter(SkinPackageInfo skinPackage, PackageInfo package, string basePath, string subFolder) : base(package) + { + _SkinPackage = skinPackage; + _SubFolder = subFolder; + BasePath = Path.Combine(basePath, subFolder); + } + + #endregion + + #region "Protected Properties" + public override bool IncludeAssemblies + { + get + { + return false; + } + } + + protected SkinPackageInfo SkinPackage + { + get + { + return _SkinPackage; + } + } + + #endregion + + public void SetBasePath() + { + if (_SkinPackage.SkinType == "Skin") + { + BasePath = Path.Combine("Portals\\_default\\Skins", SkinPackage.SkinName); + } + else + { + BasePath = Path.Combine("Portals\\_default\\Containers", SkinPackage.SkinName); + } + } + + protected override void GetFiles(bool includeSource, bool includeAppCode) + { + //Call base class method with includeAppCode = false + base.GetFiles(includeSource, false); + } + + protected override void ParseFiles(DirectoryInfo folder, string rootPath) + { + //Add the Files in the Folder + FileInfo[] files = folder.GetFiles(); + foreach (FileInfo file in files) + { + string filePath = folder.FullName.Replace(rootPath, ""); + if (filePath.StartsWith("\\")) + { + filePath = filePath.Substring(1); + } + if (file.Extension.ToLowerInvariant() != ".dnn") + { + if (string.IsNullOrEmpty(_SubFolder)) + { + AddFile(Path.Combine(filePath, file.Name)); + } + else + { + filePath = Path.Combine(filePath, file.Name); + AddFile(filePath, Path.Combine(_SubFolder, filePath)); + } + } + } + } + + protected override void WriteFilesToManifest(XmlWriter writer) + { + var skinFileWriter = new SkinComponentWriter(SkinPackage.SkinName, BasePath, Files, Package); + if (SkinPackage.SkinType == "Skin") + { + skinFileWriter = new SkinComponentWriter(SkinPackage.SkinName, BasePath, Files, Package); + } + else + { + skinFileWriter = new ContainerComponentWriter(SkinPackage.SkinName, BasePath, Files, Package); + } + skinFileWriter.WriteManifest(writer); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/WidgetComponentWriter.cs b/DNN Platform/Library/Services/Installer/Writers/WidgetComponentWriter.cs new file mode 100644 index 00000000000..7e1cfbab849 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/WidgetComponentWriter.cs @@ -0,0 +1,98 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The WidgetComponentWriter class handles creating the manifest for Widget Component(s) + /// + /// + /// + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + public class WidgetComponentWriter : FileComponentWriter + { + public WidgetComponentWriter(string basePath, Dictionary files, PackageInfo package) : base(basePath, files, package) + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Collection Node ("widgetFiles") + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string CollectionNodeName + { + get + { + return "widgetFiles"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Item Node ("widgetFiles") + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ItemNodeName + { + get + { + return "widgetFile"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the name of the Component Type ("Widget") + /// + /// A String + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string ComponentType + { + get + { + return "Widget"; + } + } + } +} diff --git a/DNN Platform/Library/Services/Installer/Writers/WidgetPackageWriter.cs b/DNN Platform/Library/Services/Installer/Writers/WidgetPackageWriter.cs new file mode 100644 index 00000000000..5a577ce9a83 --- /dev/null +++ b/DNN Platform/Library/Services/Installer/Writers/WidgetPackageWriter.cs @@ -0,0 +1,84 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Xml; + +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Installer.Writers +{ + /// ----------------------------------------------------------------------------- + /// + /// The WidgetPackageWriter class + /// + /// + /// + /// + /// [cnurse] 11/24/2008 created + /// + /// ----------------------------------------------------------------------------- + public class WidgetPackageWriter : PackageWriterBase + { + #region "Constructors" + + public WidgetPackageWriter(PackageInfo package) : base(package) + { + string company = package.Name; + if(company.Contains(".")) + { + company = company.Substring(0, company.IndexOf(".")); + } + + BasePath = Path.Combine("Resources\\Widgets\\User", company); + } + + #endregion + + #region "Public Properties" + + public override bool IncludeAssemblies + { + get + { + return false; + } + } + + #endregion + + protected override void GetFiles(bool includeSource, bool includeAppCode) + { + //Call base class method with includeAppCode = false + base.GetFiles(includeSource, false); + } + + protected override void WriteFilesToManifest(XmlWriter writer) + { + string company = Package.Name.Substring(0, Package.Name.IndexOf(".")); + var widgetFileWriter = new WidgetComponentWriter(company, Files, Package); + widgetFileWriter.WriteManifest(writer); + } + } +} diff --git a/DNN Platform/Library/Services/Installer/XmlMerge.cs b/DNN Platform/Library/Services/Installer/XmlMerge.cs new file mode 100644 index 00000000000..ee2330498fa --- /dev/null +++ b/DNN Platform/Library/Services/Installer/XmlMerge.cs @@ -0,0 +1,613 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml; + +using DotNetNuke.Application; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Upgrade; + +#endregion + +namespace DotNetNuke.Services.Installer +{ + /// ----------------------------------------------------------------------------- + /// + /// The XmlMerge class is a utility class for XmlSplicing config files + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public class XmlMerge + { + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the XmlMerge class. + /// + /// + /// + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlMerge(string sourceFileName, string version, string sender) + { + Version = version; + Sender = sender; + SourceConfig = new XmlDocument(); + SourceConfig.Load(sourceFileName); + } + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the XmlMerge class. + /// + /// + /// + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlMerge(Stream sourceStream, string version, string sender) + { + Version = version; + Sender = sender; + SourceConfig = new XmlDocument(); + SourceConfig.Load(sourceStream); + } + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the XmlMerge class. + /// + /// + /// + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlMerge(TextReader sourceReader, string version, string sender) + { + Version = version; + Sender = sender; + SourceConfig = new XmlDocument(); + SourceConfig.Load(sourceReader); + } + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the XmlMerge class. + /// + /// + /// + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlMerge(XmlDocument sourceDoc, string version, string sender) + { + Version = version; + Sender = sender; + SourceConfig = sourceDoc; + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Source for the Config file + /// + /// An XmlDocument + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlDocument SourceConfig { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Sender (source) of the changes to be merged + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Sender { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Target Config file + /// + /// An XmlDocument + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public XmlDocument TargetConfig { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the File Name of the Target Config file + /// + /// A String + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public string TargetFileName { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Version of the changes to be merged + /// + /// A String + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public string Version { get; private set; } + + #endregion + + #region "Private Methods" + + private void AddNode(XmlNode rootNode, XmlNode actionNode) + { + foreach (XmlNode child in actionNode.ChildNodes) + { + if (child.NodeType == XmlNodeType.Element || child.NodeType == XmlNodeType.Comment) + { + rootNode.AppendChild(TargetConfig.ImportNode(child, true)); + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddNode:" + child.InnerXml.ToString()); + } + } + } + + private void InsertNode(XmlNode childRootNode, XmlNode actionNode, NodeInsertType mode) + { + XmlNode rootNode = childRootNode.ParentNode; + Debug.Assert(rootNode != null); + + foreach (XmlNode child in actionNode.ChildNodes) + { + if (child.NodeType == XmlNodeType.Element || child.NodeType == XmlNodeType.Comment) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InsertNode:" + child.InnerXml.ToString()); + switch (mode) + { + case NodeInsertType.Before: + rootNode.InsertBefore(TargetConfig.ImportNode(child, true), childRootNode); + break; + case NodeInsertType.After: + rootNode.InsertAfter(TargetConfig.ImportNode(child, true), childRootNode); + break; + } + } + } + } + + private void ProcessNode(XmlNode node, XmlNode targetRoot) + { + Debug.Assert(node.Attributes != null, "node.Attributes != null"); + + XmlNode rootNode = FindMatchingNode(targetRoot, node, "path"); + + string nodeAction = node.Attributes["action"].Value.ToLowerInvariant(); + + if (rootNode == null) + { + return; //not every TargetRoot will contain every target node + } + + switch (nodeAction) + { + case "add": + AddNode(rootNode, node); + break; + case "insertbefore": + InsertNode(rootNode, node, NodeInsertType.Before); + break; + case "insertafter": + InsertNode(rootNode, node, NodeInsertType.After); + break; + case "remove": + RemoveNode(rootNode); + break; + case "removeattribute": + RemoveAttribute(rootNode, node); + break; + case "update": + UpdateNode(rootNode, node); + break; + case "updateattribute": + UpdateAttribute(rootNode, node); + break; + } + } + + private XmlNode FindNode(XmlNode root, string rootNodePath, XmlNamespaceManager nsmgr) + { + rootNodePath = AdjustRootNodePathRelativeToLocationElements(root, rootNodePath); + return root.SelectSingleNode(rootNodePath, nsmgr); + } + + private XmlNode FindNode(XmlNode root, string rootNodePath) + { + rootNodePath = AdjustRootNodePathRelativeToLocationElements(root, rootNodePath); + return root.SelectSingleNode(rootNodePath); + } + + private string AdjustRootNodePathRelativeToLocationElements(XmlNode root, string rootNodePath) + { + if(root.Name != "location") + { + return rootNodePath; + } + + var index = rootNodePath.IndexOf("configuration"); + var adjustedPath = rootNodePath.Substring(index + "configuration".Length); + adjustedPath = adjustedPath.TrimStart(new[] {'/'}); + if(String.IsNullOrEmpty(adjustedPath)) + { + adjustedPath = "."; + } + + return adjustedPath; + } + + private void ProcessNodes(XmlNodeList nodes, bool saveConfig) + { + //The nodes definition is not correct so skip changes + if (TargetConfig != null) + { + //in web.config it is possible to add nodes that contain nodes that would + //otherwise be in the root node, therefore some files can have multiple roots + //making it tricky to decide where to apply the xml merge operations + var targetRoots = GetTargetRoots().ToList(); + + if(targetRoots.Count == 1) + { + var root = targetRoots[0]; + foreach (XmlNode node in nodes) + { + ProcessNode(node, root); + } + } + else + { + foreach (XmlNode node in nodes) + { + var hits = FindMatchingNodes(node, targetRoots, "path").ToList(); + + if(hits.Count == 0) + { + continue; + } + + if(hits.Count == 1) + { + ProcessNode(node, hits[0]); + } + else if(hits.Count < targetRoots.Count) + { + ProcessNode(node, hits[0]); + } + else + { + //hit on all roots + XmlNode hit = FindMatchingNodes(node, hits, "targetpath").FirstOrDefault(); + if (hit != null) + { + ProcessNode(node, hit); + } + else + { + //all paths match at root level but no targetpaths match below that so default to the initial root + ProcessNode(node, hits[0]); + } + } + } + } + + if (saveConfig) + { + Config.Save(TargetConfig, TargetFileName); + } + } + } + + private IEnumerable FindMatchingNodes(XmlNode mergeNode, IEnumerable rootNodes, string pathAttributeName) + { + foreach (var targetRoot in rootNodes) + { + var rootNode = FindMatchingNode(targetRoot, mergeNode, pathAttributeName); + + if(rootNode != null) + { + yield return targetRoot; + } + } + } + + private XmlNode FindMatchingNode(XmlNode rootNode, XmlNode mergeNode, string pathAttributeName) + { + Debug.Assert(mergeNode.Attributes != null); + + XmlNode matchingNode = null; + if(mergeNode.Attributes[pathAttributeName] != null) + { + string rootNodePath = mergeNode.Attributes[pathAttributeName].Value; + if (mergeNode.Attributes["nameSpace"] == null) + { + matchingNode = FindNode(rootNode, rootNodePath); + } + else + { + //Use Namespace Manager + string xmlNameSpace = mergeNode.Attributes["nameSpace"].Value; + string xmlNameSpacePrefix = mergeNode.Attributes["nameSpacePrefix"].Value; + var nsmgr = new XmlNamespaceManager(TargetConfig.NameTable); + nsmgr.AddNamespace(xmlNameSpacePrefix, xmlNameSpace); + matchingNode = FindNode(rootNode, rootNodePath, nsmgr); + } + } + return matchingNode; + } + + private IEnumerable GetTargetRoots() + { + yield return TargetConfig.DocumentElement; + + var locations = TargetConfig.SelectNodes("/configuration/location"); + if (locations != null) + { + foreach (XmlNode node in locations) + { + yield return node; + } + } + } + + private void RemoveAttribute(XmlNode rootNode, XmlNode actionNode) + { + Debug.Assert(actionNode.Attributes != null, "actionNode.Attributes != null"); + Debug.Assert(rootNode.Attributes != null, "rootNode.Attributes != null"); + + if (actionNode.Attributes["name"] != null) + { + string attributeName = actionNode.Attributes["name"].Value; + if (!string.IsNullOrEmpty(attributeName)) + { + if (rootNode.Attributes[attributeName] != null) + { + rootNode.Attributes.Remove(rootNode.Attributes[attributeName]); + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveAttribute:attributeName=" + attributeName.ToString()); + } + } + } + } + + private void RemoveNode(XmlNode node) + { + if (node != null) + { + + //Get Parent + XmlNode parentNode = node.ParentNode; + + //Remove current Node + if (parentNode != null) + { + parentNode.RemoveChild(node); + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveNode:" + node.InnerXml.ToString()); + } + } + } + + private void UpdateAttribute(XmlNode rootNode, XmlNode actionNode) + { + Debug.Assert(actionNode.Attributes != null, "actionNode.Attributes != null"); + Debug.Assert(rootNode.Attributes != null, "rootNode.Attributes != null"); + + if (actionNode.Attributes["name"] != null && actionNode.Attributes["value"] != null) + { + string attributeName = actionNode.Attributes["name"].Value; + string attributeValue = actionNode.Attributes["value"].Value; + if (!string.IsNullOrEmpty(attributeName)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateAttribute:attributeName=" + attributeName.ToString()); + if (rootNode.Attributes[attributeName] == null) + { + rootNode.Attributes.Append(TargetConfig.CreateAttribute(attributeName)); + } + rootNode.Attributes[attributeName].Value = attributeValue; + } + } + } + + private void UpdateNode(XmlNode rootNode, XmlNode actionNode) + { + Debug.Assert(actionNode.Attributes != null, "actionNode.Attributes != null"); + + string keyAttribute = ""; + if (actionNode.Attributes["key"] != null) + { + keyAttribute = actionNode.Attributes["key"].Value; + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateNode: keyAttribute=" + keyAttribute.ToString()); + } + foreach (XmlNode child in actionNode.ChildNodes) + { + Debug.Assert(child.Attributes != null, "child.Attributes != null"); + + if (child.NodeType == XmlNodeType.Element) + { + XmlNode targetNode = null; + if (!string.IsNullOrEmpty(keyAttribute)) + { + if (child.Attributes[keyAttribute] != null) + { + string path = string.Format("{0}[@{1}='{2}']", child.LocalName, keyAttribute, child.Attributes[keyAttribute].Value); + targetNode = rootNode.SelectSingleNode(path); + } + } + else + { + targetNode = FindMatchingNode(rootNode, actionNode, "targetpath"); + } + if (targetNode == null) + { + //Since there is no collision we can just add the node + rootNode.AppendChild(TargetConfig.ImportNode(child, true)); + continue; + } + + //There is a collision so we need to determine what to do. + string collisionAction = actionNode.Attributes["collision"].Value; + switch (collisionAction.ToLowerInvariant()) + { + case "overwrite": + rootNode.RemoveChild(targetNode); + rootNode.InnerXml = rootNode.InnerXml + child.OuterXml; + break; + case "save": + string commentHeaderText = string.Format(Localization.Localization.GetString("XMLMERGE_Upgrade", Localization.Localization.SharedResourceFile), + Environment.NewLine, + Sender, + Version, + DateTime.Now); + XmlComment commentHeader = TargetConfig.CreateComment(commentHeaderText); + XmlComment commentNode = TargetConfig.CreateComment(targetNode.OuterXml); + rootNode.RemoveChild(targetNode); + rootNode.InnerXml = rootNode.InnerXml + commentHeader.OuterXml + commentNode.OuterXml + child.OuterXml; + break; + case "ignore": + break; + } + } + } + } + + #endregion + + #region "Public Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// The UpdateConfig method processes the source file and updates the Target + /// Config Xml Document. + /// + /// An Xml Document represent the Target Xml File + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public void UpdateConfig(XmlDocument target) + { + TargetConfig = target; + if (TargetConfig != null) + { + ProcessNodes(SourceConfig.SelectNodes("/configuration/nodes/node"), false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UpdateConfig method processes the source file and updates the Target + /// Config file. + /// + /// An Xml Document represent the Target Xml File + /// The fileName for the Target Xml File - relative to the webroot + /// + /// [cnurse] 08/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public void UpdateConfig(XmlDocument target, string fileName) + { + TargetFileName = fileName; + TargetConfig = target; + if (TargetConfig != null) + { + ProcessNodes(SourceConfig.SelectNodes("/configuration/nodes/node"), true); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The UpdateConfigs method processes the source file and updates the various config + /// files + /// + /// + /// [cnurse] 08/03/2007 created + /// + /// ----------------------------------------------------------------------------- + public void UpdateConfigs() + { + var nodes = SourceConfig.SelectNodes("/configuration/nodes"); + if (nodes != null) + foreach (XmlNode configNode in nodes) + { + Debug.Assert(configNode.Attributes != null, "configNode.Attributes != null"); + + //Attempt to load TargetFile property from configFile Atribute + TargetFileName = configNode.Attributes["configfile"].Value; + string targetProductName = ""; + if (configNode.Attributes["productName"] != null) + { + targetProductName = configNode.Attributes["productName"].Value; + } + bool isAppliedToProduct; + TargetConfig = Config.Load(TargetFileName); + if (String.IsNullOrEmpty(targetProductName) || targetProductName == "All") + { + isAppliedToProduct = true; + } + else + { + isAppliedToProduct = DotNetNukeContext.Current.Application.ApplyToProduct(targetProductName); + } + //The nodes definition is not correct so skip changes + if (TargetConfig != null && isAppliedToProduct) + { + ProcessNodes(configNode.SelectNodes("node"), true); + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Journal/CommentInfo.cs b/DNN Platform/Library/Services/Journal/CommentInfo.cs new file mode 100644 index 00000000000..ba92f5d612a --- /dev/null +++ b/DNN Platform/Library/Services/Journal/CommentInfo.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using DotNetNuke.Services.Tokens; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + + +namespace DotNetNuke.Services.Journal { + public class CommentInfo : IHydratable, IPropertyAccess { + public int CommentId { get; set; } + public int JournalId { get; set; } + public string Comment { get; set; } + public DateTime DateCreated { get; set; } + public DateTime DateUpdated { get; set; } + public XmlDocument CommentXML { get; set; } + public int UserId { get; set; } + public string DisplayName { get; set; } + + + public int KeyID { + get { + return CommentId; + } + set { + CommentId = value; + } + } + + public void Fill(System.Data.IDataReader dr) { + CommentId = Null.SetNullInteger(dr["CommentId"]); + JournalId = Null.SetNullInteger(dr["JournalId"]); + Comment = Null.SetNullString(dr["Comment"]); + DateCreated = Null.SetNullDateTime(dr["DateCreated"]); + DateUpdated = Null.SetNullDateTime(dr["DateUpdated"]); + if (!String.IsNullOrEmpty(Null.SetNullString(dr["CommentXML"]))) { + CommentXML = new XmlDocument(); + CommentXML.LoadXml(dr["CommentXML"].ToString()); + } + UserId = Null.SetNullInteger(dr["UserId"]); + DisplayName = Null.SetNullString(dr["DisplayName"]); + + + } + + public CacheLevel Cacheability { + get { + return CacheLevel.fullyCacheable; + } + + } + + public string GetProperty(string propertyName, string format, System.Globalization.CultureInfo formatProvider, Entities.Users.UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound) { + throw new NotImplementedException(); + } + } +} diff --git a/DNN Platform/Library/Services/Journal/Content.cs b/DNN Platform/Library/Services/Journal/Content.cs new file mode 100644 index 00000000000..3a8d770322d --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Content.cs @@ -0,0 +1,161 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion +using System.Linq; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content; +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.Journal { + + public class Content { + + /// + /// This should only run after the Post exists in the data store. + /// + /// The newly created ContentItemID from the data store. + /// This is for the first question in the thread. Not for replies or items with ParentID > 0. + internal ContentItem CreateContentItem(JournalItem objJournalItem, int tabId) { + var typeController = new ContentTypeController(); + string contentTypeName = "DNNCorp_JournalProfile"; + if (objJournalItem.SocialGroupId > 0) { + contentTypeName = "DNNCorp_JournalGroup"; + } + var colContentTypes = (from t in typeController.GetContentTypes() where t.ContentType == contentTypeName select t); + int contentTypeID; + + if (colContentTypes.Count() > 0) { + var contentType = colContentTypes.Single(); + contentTypeID = contentType == null ? CreateContentType(contentTypeName) : contentType.ContentTypeId; + } else { + contentTypeID = CreateContentType(contentTypeName); + } + + var objContent = new ContentItem { + Content = GetContentBody(objJournalItem), + ContentTypeId = contentTypeID, + Indexed = false, + ContentKey = "journalid=" + objJournalItem.JournalId, + ModuleID = -1, + TabID = tabId + }; + + objContent.ContentItemId = Util.GetContentController().AddContentItem(objContent); + + // Add Terms + //var cntTerm = new Terms(); + //cntTerm.ManageQuestionTerms(objPost, objContent); + + return objContent; + } + + /// + /// This is used to update the content in the ContentItems table. Should be called when a question is updated. + /// + internal void UpdateContentItem(JournalItem objJournalItem, int tabId) { + var objContent = Util.GetContentController().GetContentItem(objJournalItem.ContentItemId); + + if (objContent == null) return; + //Only update content the contentitem if it was created by the journal + if ((objContent.ContentTypeId == GetContentTypeID("DNNCorp_JournalProfile") && objJournalItem.ProfileId > 0) + || (objContent.ContentTypeId == GetContentTypeID("DNNCorp_JournalGroup") && objJournalItem.SocialGroupId > 0)) + { + objContent.Content = GetContentBody(objJournalItem); + objContent.TabID = tabId; + objContent.ContentKey = "journalid=" + objJournalItem.JournalId; // we reset this just in case the page changed. + + Util.GetContentController().UpdateContentItem(objContent); + } + + + // Update Terms + //var cntTerm = new Terms(); + //cntTerm.ManageQuestionTerms(objPost, objContent); + } + + /// + /// This removes a content item associated with a question/thread from the data store. Should run every time an entire thread is deleted. + /// + /// + internal void DeleteContentItem(int contentItemID) { + if (contentItemID <= Null.NullInteger) return; + var objContent = Util.GetContentController().GetContentItem(contentItemID); + if (objContent == null) return; + + // remove any metadata/terms associated first (perhaps we should just rely on ContentItem cascade delete here?) + //var cntTerms = new Terms(); + //cntTerms.RemoveQuestionTerms(objContent); + + Util.GetContentController().DeleteContentItem(objContent); + } + + /// + /// This is used to determine the ContentTypeID (part of the Core API) based on this module's content type. If the content type doesn't exist yet for the module, it is created. + /// + /// The primary key value (ContentTypeID) from the core API's Content Types table. + internal static int GetContentTypeID(string ContentTypeName) { + var typeController = new ContentTypeController(); + var colContentTypes = (from t in typeController.GetContentTypes() where t.ContentType == ContentTypeName select t); + int contentTypeId; + + if (colContentTypes.Count() > 0) { + var contentType = colContentTypes.Single(); + contentTypeId = contentType == null ? CreateContentType(ContentTypeName) : contentType.ContentTypeId; + } else { + contentTypeId = CreateContentType(ContentTypeName); + } + + return contentTypeId; + } + + #region Private Methods + + /// + /// Creates a Content Type (for taxonomy) in the data store. + /// + /// The primary key value of the new ContentType. + private static int CreateContentType(string ContentTypeName) { + var typeController = new ContentTypeController(); + var objContentType = new ContentType { ContentType = ContentTypeName }; + + return typeController.AddContentType(objContentType); + } + /// + /// Creates the content text + /// + /// + /// + private static string GetContentBody(JournalItem objJournalItem) { + if (!string.IsNullOrEmpty(objJournalItem.Title)) { + return objJournalItem.Title; + } else if (!string.IsNullOrEmpty(objJournalItem.Summary)) { + return objJournalItem.Summary; + } else if (!string.IsNullOrEmpty(objJournalItem.Body)) { + return objJournalItem.Body; + } else { + return null; + } + } + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Data/IJournalDataService.cs b/DNN Platform/Library/Services/Journal/Data/IJournalDataService.cs new file mode 100644 index 00000000000..078717cb147 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Data/IJournalDataService.cs @@ -0,0 +1,111 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Data; + +#endregion + +namespace DotNetNuke.Services.Journal +{ + public interface IJournalDataService + { + IDataReader Journal_ListForSummary(int portalId, int moduleId, int currentUserId, int rowIndex, int maxRows); + + IDataReader Journal_ListForProfile(int portalId, int moduleId, int currentUserId, int profileId, int rowIndex, + int maxRows); + + IDataReader Journal_ListForGroup(int portalId, int moduleId, int currentUserId, int groupId, int rowIndex, + int maxRows); + + void Journal_Delete(int journalId); + + void Journal_DeleteByKey(int portalId, string objectKey); + + void Journal_DeleteByGroupId(int portalId, int groupId); + + void Journal_SoftDelete(int journalId); + + void Journal_SoftDeleteByKey(int portalId, string objectKey); + + void Journal_SoftDeleteByGroupId(int portalId, int groupId); + + IDataReader Journal_Get(int portalId, int currentUserId, int journalId); + IDataReader Journal_Get(int portalId, int currentUserId, int journalId, bool includeAllItems, bool isDeleted); + IDataReader Journal_GetByKey(int portalId, string objectKey); + IDataReader Journal_GetByKey(int portalId, string objectKey, bool includeAllItems, bool isDeleted); + int Journal_Save(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, string summary, + string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet); + int Journal_Save(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, string summary, + string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet, bool commentsHidden, bool commentsDisabled); + + int Journal_Update(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, string summary, + string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet); + int Journal_Update(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, string summary, + string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet, bool commentsHidden, bool commentsDisabled); + + void Journal_UpdateContentItemId(int journalId, int contentItemId); + + void Journal_Like(int journalId, int userId, string displayName); + + IDataReader Journal_LikeList(int portalId, int journalId); + + void Journal_Comment_Delete(int journalId, int commentId); + + int Journal_Comment_Save(int journalId, int commentId, int userId, string comment, string xml); + + IDataReader Journal_Comment_List(int journalId); + + IDataReader Journal_Comment_Get(int commentId); + + IDataReader Journal_Comment_ListByJournalIds(string journalIds); + + void Journal_Comment_Like(int journalId, int commentId, int userId, string displayName); + + IDataReader Journal_Comment_LikeList(int portalId, int journalId, int commentId); + void Journal_Comments_ToggleDisable(int portalId, int journalId, bool disable); + void Journal_Comments_ToggleHidden(int portalId, int journalId, bool hidden); + + IDataReader Journal_Types_List(int portalId); + + IDataReader Journal_Types_GetById(int journalTypeId); + + IDataReader Journal_Types_Get(string journalType); + + void Journal_Types_Delete(int journalTypeId, int portalId); + + int Journal_Types_Save(int journalTypeId, string journalType, string icon, int portalId, bool isEnabled, + bool appliesToProfile, bool appliesToGroup, bool appliesToStream, string options, + bool supportsNotify); + + IDataReader Journal_GetStatsForGroup(int portalId, int groupId); + + IDataReader Journal_TypeFilters_List(int portalId, int moduleId); + + void Journal_TypeFilters_Delete(int portalId, int moduleId); + + void Journal_TypeFilters_Save(int portalId, int moduleId, int journalTypeId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Data/JournalDataService.cs b/DNN Platform/Library/Services/Journal/Data/JournalDataService.cs new file mode 100644 index 00000000000..8f63276a4c1 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Data/JournalDataService.cs @@ -0,0 +1,43 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.IO; +using System.Xml; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Journal { + public class JournalDataService : ServiceLocator + { + protected override Func GetFactory() + { + return () => new JournalDataServiceImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Data/JournalDataServiceImpl.cs b/DNN Platform/Library/Services/Journal/Data/JournalDataServiceImpl.cs new file mode 100644 index 00000000000..320862912bd --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Data/JournalDataServiceImpl.cs @@ -0,0 +1,241 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Journal +{ + internal class JournalDataServiceImpl : IJournalDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + + #region IJournalDataService Members + + public IDataReader Journal_ListForSummary(int portalId, int moduleId, int currentUserId, int rowIndex, + int maxRows) + { + return _provider.ExecuteReader("Journal_ListForSummary", portalId, moduleId, currentUserId, rowIndex, + maxRows); + } + + public IDataReader Journal_ListForProfile(int portalId, int moduleId, int currentUserId, int profileId, + int rowIndex, int maxRows) + { + return _provider.ExecuteReader("Journal_ListForProfile", portalId, moduleId, currentUserId, profileId, + rowIndex, maxRows); + } + + public IDataReader Journal_ListForGroup(int portalId, int moduleId, int currentUserId, int groupId, int rowIndex, + int maxRows) + { + return _provider.ExecuteReader("Journal_ListForGroup", portalId, moduleId, currentUserId, groupId, rowIndex, + maxRows); + } + + public void Journal_Delete(int journalId) + { + _provider.ExecuteNonQuery("Journal_Delete", journalId); + } + + public void Journal_DeleteByKey(int portalId, string objectKey) + { + _provider.ExecuteNonQuery("Journal_DeleteByKey", portalId, objectKey); + } + + public void Journal_DeleteByGroupId(int portalId, int groupId) + { + _provider.ExecuteNonQuery("Journal_DeleteByGroupId", portalId, groupId); + } + + public void Journal_SoftDelete(int journalId) + { + _provider.ExecuteNonQuery("Journal_Delete", journalId, true); + } + + public void Journal_SoftDeleteByKey(int portalId, string objectKey) + { + _provider.ExecuteNonQuery("Journal_DeleteByKey", portalId, objectKey, true); + } + + public void Journal_SoftDeleteByGroupId(int portalId, int groupId) + { + _provider.ExecuteNonQuery("Journal_DeleteByGroupId", portalId, groupId, true); + } + + public void Journal_Like(int journalId, int userId, string displayName) + { + _provider.ExecuteNonQuery("Journal_Like", journalId, userId, displayName); + } + + public IDataReader Journal_LikeList(int portalId, int journalId) + { + return _provider.ExecuteReader("Journal_LikeList", portalId, journalId); + } + + public void Journal_UpdateContentItemId(int journalId, int contentItemId) + { + _provider.ExecuteNonQuery("Journal_UpdateContentItemId", journalId, contentItemId); + } + public IDataReader Journal_Get(int portalId, int currentUserId, int journalId) { + return Journal_Get(portalId, currentUserId, journalId, false, false); + } + public IDataReader Journal_Get(int portalId, int currentUserId, int journalId, bool includeAllItems, bool isDeleted) + { + return _provider.ExecuteReader("Journal_Get", portalId, currentUserId, journalId, includeAllItems, isDeleted); + } + public IDataReader Journal_GetByKey(int portalId, string objectKey) { + return Journal_GetByKey(portalId, objectKey, false, false); + } + public IDataReader Journal_GetByKey(int portalId, string objectKey, bool includeAllItems, bool isDeleted) + { + return _provider.ExecuteReader("Journal_GetByKey", portalId, objectKey, includeAllItems, isDeleted); + } + public int Journal_Save(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, + string summary, string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet) + { + journalId = _provider.ExecuteScalar("Journal_Save", portalId, journalId, journalTypeId, currentUserId, profileId, + groupId, title, summary, itemData, xml, objectKey, accessKey, securitySet, false, false); + return journalId; + } + public int Journal_Save(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, + string summary, string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet, bool commentsDisabled, bool commentsHidden) + { + journalId = _provider.ExecuteScalar("Journal_Save", portalId, journalId, journalTypeId, currentUserId, profileId, + groupId, title, summary, itemData, xml, objectKey, accessKey, securitySet, commentsDisabled, commentsHidden); + return journalId; + } + public int Journal_Update(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, + string summary, string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet) + { + journalId = _provider.ExecuteScalar("Journal_Update", portalId, journalId, journalTypeId, currentUserId, profileId, + groupId, title, summary, itemData, xml, objectKey, accessKey, securitySet, false, false); + + return journalId; + } + public int Journal_Update(int portalId, int currentUserId, int profileId, int groupId, int journalId, int journalTypeId, string title, + string summary, string body, string itemData, string xml, string objectKey, Guid accessKey, string securitySet, bool commentsDisabled, bool commentsHidden) + { + journalId = _provider.ExecuteScalar("Journal_Update", portalId, journalId, journalTypeId, currentUserId, profileId, + groupId, title, summary, itemData, xml, objectKey, accessKey, securitySet, commentsDisabled, commentsHidden); + return journalId; + } + public void Journal_Comment_Delete(int journalId, int commentId) { + _provider.ExecuteNonQuery("Journal_Comment_Delete", journalId, commentId); + } + + public int Journal_Comment_Save(int journalId, int commentId, int userId, string comment, string xml) + { + commentId = _provider.ExecuteScalar("Journal_Comment_Save", journalId, commentId, userId, comment, xml); + return commentId; + } + + public IDataReader Journal_Comment_List(int journalId) + { + return _provider.ExecuteReader("Journal_Comment_List", journalId); + } + + public IDataReader Journal_Comment_Get(int commentId) + { + return _provider.ExecuteReader("Journal_Comment_Get", commentId); + } + + public IDataReader Journal_Comment_ListByJournalIds(string journalIds) + { + return _provider.ExecuteReader("Journal_Comment_ListByJournalIds", journalIds); + } + + public void Journal_Comment_Like(int journalId, int commentId, int userId, string displayName) + { + _provider.ExecuteNonQuery("Journal_Comment_Like", journalId, commentId, userId, displayName); + } + public IDataReader Journal_Comment_LikeList(int portalId, int journalId, int commentId) { + return _provider.ExecuteReader("Journal_Comment_LikeList", portalId, journalId, commentId); + } + public void Journal_Comments_ToggleDisable(int portalId, int journalId, bool disable) + { + _provider.ExecuteNonQuery("Journal_Comments_ToggleDisable", portalId, journalId, disable); + } + + public void Journal_Comments_ToggleHidden(int portalId, int journalId, bool hidden) + { + _provider.ExecuteNonQuery("Journal_Comments_ToggleHidden", portalId, journalId, hidden); + } + public IDataReader Journal_Types_List(int portalId) { + return _provider.ExecuteReader("Journal_Types_List", portalId); + } + + public IDataReader Journal_Types_GetById(int journalTypeId) + { + return _provider.ExecuteReader("Journal_Types_GetById", journalTypeId); + } + + public IDataReader Journal_Types_Get(string journalType) + { + return _provider.ExecuteReader("Journal_Types_Get", journalType); + } + + public void Journal_Types_Delete(int journalTypeId, int portalId) + { + _provider.ExecuteNonQuery("Journal_Types_Delete", journalTypeId, portalId); + } + + public int Journal_Types_Save(int journalTypeId, string journalType, string icon, int portalId, bool isEnabled, + bool appliesToProfile, bool appliesToGroup, bool appliesToStream, string options, + bool supportsNotify) + { + journalTypeId = _provider.ExecuteScalar("Journal_Types_Save", journalTypeId, journalType, icon, + portalId, isEnabled, appliesToProfile, appliesToGroup, + appliesToStream, options, supportsNotify); + return journalTypeId; + } + + public IDataReader Journal_GetStatsForGroup(int portalId, int groupId) + { + return _provider.ExecuteReader("Journal_GetStatsForGroup", portalId, groupId); + } + + public IDataReader Journal_TypeFilters_List(int portalId, int moduleId) + { + return _provider.ExecuteReader("Journal_TypeFilters_List", portalId, moduleId); + } + + public void Journal_TypeFilters_Delete(int portalId, int moduleId) + { + _provider.ExecuteNonQuery("Journal_TypeFilters_Delete", portalId, moduleId); + } + + public void Journal_TypeFilters_Save(int portalId, int moduleId, int journalTypeId) + { + _provider.ExecuteNonQuery("Journal_TypeFilters_Save", portalId, moduleId, journalTypeId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/IJournalController.cs b/DNN Platform/Library/Services/Journal/IJournalController.cs new file mode 100644 index 00000000000..7cb5dbda8fe --- /dev/null +++ b/DNN Platform/Library/Services/Journal/IJournalController.cs @@ -0,0 +1,61 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Services.Journal +{ + public interface IJournalController + { + // Journal Items + JournalTypeInfo GetJournalType(string journalType); + JournalTypeInfo GetJournalTypeById(int journalTypeId); + JournalItem GetJournalItemByKey(int portalId, string objectKey); + JournalItem GetJournalItemByKey(int portalId, string objectKey, bool includeAllItems); + JournalItem GetJournalItemByKey(int portalId, string objectKey, bool includeAllItems, bool isDeleted); + JournalItem GetJournalItem(int portalId, int userId, int journalId); + JournalItem GetJournalItem(int portalId, int userId, int journalId, bool includeAllItems); + JournalItem GetJournalItem(int portalId, int userId, int journalId, bool includeAllItems, bool isDeleted); + IEnumerable GetJournalTypes(int portalId); + void SaveJournalItem(JournalItem journalItem, int tabId); + void UpdateJournalItem(JournalItem journalItem, int tabId); + + // Delete Journal Items + void DeleteJournalItem(int portalId, int userId, int journalId); + void DeleteJournalItemByGroupId(int portalId, int groupId); + void DeleteJournalItemByKey(int portalId, string objectKey); + void SoftDeleteJournalItem(int portalId, int userId, int journalId); + void SoftDeleteJournalItemByGroupId(int portalId, int groupId); + void SoftDeleteJournalItemByKey(int portalId, string objectKey); + + // Journal Comments + void DisableComments(int portalId, int journalId); + void HideComments(int portalId, int journalId); + void EnableComments(int portalId, int journalId); + void ShowComments(int portalId, int journalId); + IList GetCommentsByJournalIds(List journalIdList); + void LikeJournalItem(int journalId, int userId, string displayName); + void SaveComment(CommentInfo ci); + CommentInfo GetComment(int commentId); + void DeleteComment(int journalId, int commentId); + void LikeComment(int journalId, int commentId, int userId, string displayName); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Internal/IInternalJournalController.cs b/DNN Platform/Library/Services/Journal/Internal/IInternalJournalController.cs new file mode 100644 index 00000000000..937d7995591 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Internal/IInternalJournalController.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; + +namespace DotNetNuke.Services.Journal.Internal +{ + public interface IInternalJournalController + { + IList GetJournalItemsByProfile (int portalId, int moduleId, int userID, int profileId, int currentIndex, int rows); + IList GetJournalItemsByGroup(int portalId, int moduleId, int userID, int socialGroupId, int currentIndex, int rows); + IList GetJournalItems(int portalId, int moduleId, int userID, int currentIndex, int rows); + + void DeleteFilters(int portalId, int moduleId); + void SaveFilters(int portalId, int moduleId, int toInt32); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Internal/InternalJournalController.cs b/DNN Platform/Library/Services/Journal/Internal/InternalJournalController.cs new file mode 100644 index 00000000000..c881b2d14a5 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Internal/InternalJournalController.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Framework; + +namespace DotNetNuke.Services.Journal.Internal +{ + public class InternalJournalController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new InternalJournalControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/Internal/InternalJournalControllerImpl.cs b/DNN Platform/Library/Services/Journal/Internal/InternalJournalControllerImpl.cs new file mode 100644 index 00000000000..585bc8dc7e6 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/Internal/InternalJournalControllerImpl.cs @@ -0,0 +1,84 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.Journal.Internal +{ + public class InternalJournalControllerImpl : IInternalJournalController + { + private readonly IJournalDataService _dataService; + + #region Constructors + + public InternalJournalControllerImpl() + { + _dataService = JournalDataService.Instance; + } + + #endregion + + public IList GetJournalItemsByProfile(int portalId, int moduleId, int currentUserId, int profileId, + int rowIndex, int maxRows) + { + return + CBO.FillCollection(_dataService.Journal_ListForProfile(portalId, moduleId, currentUserId, + profileId, rowIndex, maxRows)); + } + + public IList GetJournalItemsByGroup(int portalId, int moduleId, int currentUserId, int groupId, + int rowIndex, int maxRows) + { + return + CBO.FillCollection(_dataService.Journal_ListForGroup(portalId, moduleId, currentUserId, + groupId, rowIndex, maxRows)); + } + + public IList GetJournalItems(int portalId, int moduleId, int currentUserId, int rowIndex, + int maxRows) + { + return + CBO.FillCollection(_dataService.Journal_ListForSummary(portalId, moduleId, currentUserId, + rowIndex, maxRows)); + } + + public void DeleteFilters(int portalId, int moduleId) + { + _dataService.Journal_TypeFilters_Delete(portalId, moduleId); + } + + public void SaveFilters(int portalId, int moduleId, int journalTypeId) + { + _dataService.Journal_TypeFilters_Save(portalId, moduleId, journalTypeId); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/ItemData.cs b/DNN Platform/Library/Services/Journal/ItemData.cs new file mode 100644 index 00000000000..d98f9540243 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/ItemData.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using DotNetNuke.Services.Tokens; +namespace DotNetNuke.Services.Journal { + + public class ItemData : IPropertyAccess { + public string Url { get; set; } + public string Title { get; set; } + public string Description { get; set; } + public string ImageUrl { get; set; } + public CacheLevel Cacheability { + get { + return CacheLevel.fullyCacheable; + } + } + + public string GetProperty(string propertyName, string format, System.Globalization.CultureInfo formatProvider, Entities.Users.UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound) { + string OutputFormat = string.Empty; + if (format == string.Empty) { + OutputFormat = "g"; + } else { + OutputFormat = format; + } + propertyName = propertyName.ToLowerInvariant(); + switch (propertyName) { + case "url": + return PropertyAccess.FormatString(Url, format); + case "title": + return PropertyAccess.FormatString(Title, format); + case "description": + return PropertyAccess.FormatString(Description, format); + case "imageurl": + return PropertyAccess.FormatString(ImageUrl, format); + + + } + + propertyNotFound = true; + return string.Empty; + + } + } + + + + +} + diff --git a/DNN Platform/Library/Services/Journal/JournalController.cs b/DNN Platform/Library/Services/Journal/JournalController.cs new file mode 100644 index 00000000000..b4c8890e080 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/JournalController.cs @@ -0,0 +1,41 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Journal +{ + public class JournalController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new JournalControllerImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/JournalControllerImpl.cs b/DNN Platform/Library/Services/Journal/JournalControllerImpl.cs new file mode 100644 index 00000000000..e53cbee4a11 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/JournalControllerImpl.cs @@ -0,0 +1,626 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Web; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; + +namespace DotNetNuke.Services.Journal +{ + internal class JournalControllerImpl : IJournalController + { + private readonly IJournalDataService _dataService; + + #region Constructors + + public JournalControllerImpl() + { + _dataService = JournalDataService.Instance; + } + + #endregion + + #region Private Methods + + private XmlElement CreateElement(XmlDocument xDoc, string name, string value) + { + XmlElement xnode = xDoc.CreateElement(name); + XmlText xtext = xDoc.CreateTextNode(value); + xnode.AppendChild(xtext); + return xnode; + } + + private XmlElement CreateCDataElement(XmlDocument xDoc, string name, string value) + { + XmlElement xnode = xDoc.CreateElement(name); + XmlCDataSection xdata = xDoc.CreateCDataSection(value); + xnode.AppendChild(xdata); + return xnode; + } + + private void UpdateGroupStats(int portalId, int groupId) + { + RoleInfo role = TestableRoleController.Instance.GetRole(portalId, r => r.RoleID == groupId); + if (role == null) + { + return; + } + + for (var i = 0; i < role.Settings.Keys.Count; i++ ) + { + var key = role.Settings.Keys.ElementAt(i); + if(key.StartsWith("stat_")) + { + role.Settings[key] = "0"; + } + } + + using (IDataReader dr = _dataService.Journal_GetStatsForGroup(portalId, groupId)) + { + while (dr.Read()) + { + string settingName = "stat_" + dr["JournalType"]; + if (role.Settings.ContainsKey(settingName)) + { + role.Settings[settingName] = dr["JournalTypeCount"].ToString(); + } + else + { + role.Settings.Add(settingName, dr["JournalTypeCount"].ToString()); + } + } + dr.Close(); + } + TestableRoleController.Instance.UpdateRoleSettings(role, true); + } + + private void DeleteJournalItem(int portalId, int currentUserId, int journalId, bool softDelete) + { + var ji = GetJournalItem(portalId, currentUserId, journalId); + var groupId = ji.SocialGroupId; + + if (softDelete) + { + _dataService.Journal_SoftDelete(journalId); + } + else + { + _dataService.Journal_Delete(journalId); + } + + if (groupId > 0) + { + UpdateGroupStats(portalId, groupId); + } + } + + #endregion + + #region Public Methods + // Journal Items + public JournalItem GetJournalItem(int portalId, int currentUserId, int journalId) + { + return GetJournalItem(portalId, currentUserId, journalId, false, false); + } + public JournalItem GetJournalItem(int portalId, int currentUserId, int journalId, bool includeAllItems) + { + return GetJournalItem(portalId, currentUserId, journalId, includeAllItems, false); + } + public JournalItem GetJournalItem(int portalId, int currentUserId, int journalId, bool includeAllItems, bool isDeleted) + { + return CBO.FillObject(_dataService.Journal_Get(portalId, currentUserId, journalId, includeAllItems, isDeleted)); + } + public JournalItem GetJournalItemByKey(int portalId, string objectKey) + { + return GetJournalItemByKey(portalId, objectKey, false, false); + } + public JournalItem GetJournalItemByKey(int portalId, string objectKey, bool includeAllItems) + { + return GetJournalItemByKey(portalId, objectKey, includeAllItems, false); + } + public JournalItem GetJournalItemByKey(int portalId, string objectKey, bool includeAllItems, bool isDeleted) + { + if (string.IsNullOrEmpty(objectKey)) + { + return null; + } + return (JournalItem)CBO.FillObject(_dataService.Journal_GetByKey(portalId, objectKey, includeAllItems, isDeleted), typeof(JournalItem)); + } + + public void SaveJournalItem(JournalItem journalItem, int tabId) + { + if (journalItem.UserId < 1) + { + throw new ArgumentException("journalItem.UserId must be for a real user"); + } + UserInfo currentUser = UserController.GetUserById(journalItem.PortalId, journalItem.UserId); + if (currentUser == null) + { + throw new Exception("Unable to locate the current user"); + } + + string xml = null; + var portalSecurity = new PortalSecurity(); + if (!String.IsNullOrEmpty(journalItem.Title)) + { + journalItem.Title = portalSecurity.InputFilter(journalItem.Title, PortalSecurity.FilterFlag.NoMarkup); + } + if (!String.IsNullOrEmpty(journalItem.Summary)) + { + journalItem.Summary = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.Summary, PortalSecurity.FilterFlag.NoScripting)); + } + if (!String.IsNullOrEmpty(journalItem.Body)) + { + journalItem.Body = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.Body, PortalSecurity.FilterFlag.NoScripting)); + } + + if (!String.IsNullOrEmpty(journalItem.Body)) + { + var xDoc = new XmlDocument(); + XmlElement xnode = xDoc.CreateElement("items"); + XmlElement xnode2 = xDoc.CreateElement("item"); + xnode2.AppendChild(CreateElement(xDoc, "id", "-1")); + xnode2.AppendChild(CreateCDataElement(xDoc, "body", journalItem.Body)); + xnode.AppendChild(xnode2); + xDoc.AppendChild(xnode); + XmlDeclaration xDec = xDoc.CreateXmlDeclaration("1.0", null, null); + xDec.Encoding = "UTF-16"; + xDec.Standalone = "yes"; + XmlElement root = xDoc.DocumentElement; + xDoc.InsertBefore(xDec, root); + journalItem.JournalXML = xDoc; + xml = journalItem.JournalXML.OuterXml; + } + if (journalItem.ItemData != null) + { + if (!String.IsNullOrEmpty(journalItem.ItemData.Title)) + { + journalItem.ItemData.Title = portalSecurity.InputFilter(journalItem.ItemData.Title, PortalSecurity.FilterFlag.NoMarkup); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.Description)) + { + journalItem.ItemData.Description = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.ItemData.Description, PortalSecurity.FilterFlag.NoScripting)); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.Url)) + { + journalItem.ItemData.Url = portalSecurity.InputFilter(journalItem.ItemData.Url, PortalSecurity.FilterFlag.NoScripting); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.ImageUrl)) + { + journalItem.ItemData.ImageUrl = portalSecurity.InputFilter(journalItem.ItemData.ImageUrl, PortalSecurity.FilterFlag.NoScripting); + } + } + string journalData = journalItem.ItemData.ToJson(); + if (journalData == "null") + { + journalData = null; + } + if (String.IsNullOrEmpty(journalItem.SecuritySet)) + { + journalItem.SecuritySet = "E,"; + } + else if (!journalItem.SecuritySet.EndsWith(",")) + { + journalItem.SecuritySet += ","; + } + if (journalItem.SecuritySet == "F,") + { + journalItem.SecuritySet = "F" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + journalItem.SecuritySet += "P" + journalItem.ProfileId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.SecuritySet == "U,") + { + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.ProfileId > 0 && journalItem.UserId != journalItem.ProfileId) + { + if (!journalItem.SecuritySet.Contains("P" + journalItem.ProfileId.ToString(CultureInfo.InvariantCulture))) + { + journalItem.SecuritySet += "P" + journalItem.ProfileId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (!journalItem.SecuritySet.Contains("U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture))) + { + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + } + if (!journalItem.SecuritySet.Contains("U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture))) + { + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.SocialGroupId > 0) + { + JournalItem item = journalItem; + RoleInfo role = TestableRoleController.Instance.GetRole(journalItem.PortalId, r => r.SecurityMode != SecurityMode.SecurityRole && r.RoleID == item.SocialGroupId); + if (role != null) + { + if (currentUser.IsInRole(role.RoleName)) + { + journalItem.SecuritySet += "R" + journalItem.SocialGroupId.ToString(CultureInfo.InvariantCulture) + ","; + if (!role.IsPublic) + { + journalItem.SecuritySet = journalItem.SecuritySet.Replace("E,", String.Empty); + } + } + } + } + journalItem.JournalId = _dataService.Journal_Save(journalItem.PortalId, + journalItem.UserId, + journalItem.ProfileId, + journalItem.SocialGroupId, + journalItem.JournalId, + journalItem.JournalTypeId, + journalItem.Title, + journalItem.Summary, + journalItem.Body, + journalData, + xml, + journalItem.ObjectKey, + journalItem.AccessKey, + journalItem.SecuritySet, + journalItem.CommentsDisabled, + journalItem.CommentsHidden); + var updatedJournalItem = GetJournalItem(journalItem.PortalId, journalItem.UserId, journalItem.JournalId); + journalItem.DateCreated = updatedJournalItem.DateCreated; + journalItem.DateUpdated = updatedJournalItem.DateUpdated; + var cnt = new Content(); + if (journalItem.ContentItemId > 0) + { + cnt.UpdateContentItem(journalItem, tabId); + _dataService.Journal_UpdateContentItemId(journalItem.JournalId, journalItem.ContentItemId); + } + else + { + ContentItem ci = cnt.CreateContentItem(journalItem, tabId); + _dataService.Journal_UpdateContentItemId(journalItem.JournalId, ci.ContentItemId); + journalItem.ContentItemId = ci.ContentItemId; + } + if (journalItem.SocialGroupId > 0) + { + try + { + UpdateGroupStats(journalItem.PortalId, journalItem.SocialGroupId); + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + } + public void UpdateJournalItem(JournalItem journalItem, int tabId) + { + if (journalItem.UserId < 1) + { + throw new ArgumentException("journalItem.UserId must be for a real user"); + } + UserInfo currentUser = UserController.GetUserById(journalItem.PortalId, journalItem.UserId); + if (currentUser == null) + { + throw new Exception("Unable to locate the current user"); + } + string xml = null; + var portalSecurity = new PortalSecurity(); + if (!String.IsNullOrEmpty(journalItem.Title)) + { + journalItem.Title = portalSecurity.InputFilter(journalItem.Title, PortalSecurity.FilterFlag.NoMarkup); + } + if (!String.IsNullOrEmpty(journalItem.Summary)) + { + journalItem.Summary = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.Summary, PortalSecurity.FilterFlag.NoScripting)); + } + if (!String.IsNullOrEmpty(journalItem.Body)) + { + journalItem.Body = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.Body, PortalSecurity.FilterFlag.NoScripting)); + } + if (!String.IsNullOrEmpty(journalItem.Body)) + { + var xDoc = new XmlDocument(); + XmlElement xnode = xDoc.CreateElement("items"); + XmlElement xnode2 = xDoc.CreateElement("item"); + xnode2.AppendChild(CreateElement(xDoc, "id", "-1")); + xnode2.AppendChild(CreateCDataElement(xDoc, "body", journalItem.Body)); + xnode.AppendChild(xnode2); + xDoc.AppendChild(xnode); + XmlDeclaration xDec = xDoc.CreateXmlDeclaration("1.0", null, null); + xDec.Encoding = "UTF-16"; + xDec.Standalone = "yes"; + XmlElement root = xDoc.DocumentElement; + xDoc.InsertBefore(xDec, root); + journalItem.JournalXML = xDoc; + xml = journalItem.JournalXML.OuterXml; + } + if (journalItem.ItemData != null) + { + if (!String.IsNullOrEmpty(journalItem.ItemData.Title)) + { + journalItem.ItemData.Title = portalSecurity.InputFilter(journalItem.ItemData.Title, PortalSecurity.FilterFlag.NoMarkup); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.Description)) + { + journalItem.ItemData.Description = HttpUtility.HtmlDecode(portalSecurity.InputFilter(journalItem.ItemData.Description, PortalSecurity.FilterFlag.NoScripting)); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.Url)) + { + journalItem.ItemData.Url = portalSecurity.InputFilter(journalItem.ItemData.Url, PortalSecurity.FilterFlag.NoScripting); + } + if (!String.IsNullOrEmpty(journalItem.ItemData.ImageUrl)) + { + journalItem.ItemData.ImageUrl = portalSecurity.InputFilter(journalItem.ItemData.ImageUrl, PortalSecurity.FilterFlag.NoScripting); + } + } + string journalData = journalItem.ItemData.ToJson(); + if (journalData == "null") + { + journalData = null; + } + if (String.IsNullOrEmpty(journalItem.SecuritySet)) + { + journalItem.SecuritySet = "E,"; + } + else if (!journalItem.SecuritySet.EndsWith(",")) + { + journalItem.SecuritySet += ","; + } + if (journalItem.SecuritySet == "F,") + { + journalItem.SecuritySet = "F" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + journalItem.SecuritySet += "P" + journalItem.ProfileId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.SecuritySet == "U,") + { + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.ProfileId > 0 && journalItem.UserId != journalItem.ProfileId) + { + journalItem.SecuritySet += "P" + journalItem.ProfileId.ToString(CultureInfo.InvariantCulture) + ","; + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (!journalItem.SecuritySet.Contains("U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture))) + { + journalItem.SecuritySet += "U" + journalItem.UserId.ToString(CultureInfo.InvariantCulture) + ","; + } + if (journalItem.SocialGroupId > 0) + { + JournalItem item = journalItem; + RoleInfo role = TestableRoleController.Instance.GetRole(journalItem.PortalId, r => r.SecurityMode != SecurityMode.SecurityRole && r.RoleID == item.SocialGroupId); + if (role != null) + { + if (currentUser.IsInRole(role.RoleName)) + { + journalItem.SecuritySet += "R" + journalItem.SocialGroupId.ToString(CultureInfo.InvariantCulture) + ","; + if (!role.IsPublic) + { + journalItem.SecuritySet = journalItem.SecuritySet.Replace("E,", String.Empty); + } + } + } + } + journalItem.JournalId = _dataService.Journal_Save(journalItem.PortalId, + journalItem.UserId, + journalItem.ProfileId, + journalItem.SocialGroupId, + journalItem.JournalId, + journalItem.JournalTypeId, + journalItem.Title, + journalItem.Summary, + journalItem.Body, + journalData, + xml, + journalItem.ObjectKey, + journalItem.AccessKey, + journalItem.SecuritySet, + journalItem.CommentsDisabled, + journalItem.CommentsHidden); + + var updatedJournalItem = GetJournalItem(journalItem.PortalId, journalItem.UserId, journalItem.JournalId); + journalItem.DateCreated = updatedJournalItem.DateCreated; + journalItem.DateUpdated = updatedJournalItem.DateUpdated; + + var cnt = new Content(); + + if (journalItem.ContentItemId > 0) + { + cnt.UpdateContentItem(journalItem, tabId); + _dataService.Journal_UpdateContentItemId(journalItem.JournalId, journalItem.ContentItemId); + } + else + { + ContentItem ci = cnt.CreateContentItem(journalItem, tabId); + _dataService.Journal_UpdateContentItemId(journalItem.JournalId, ci.ContentItemId); + journalItem.ContentItemId = ci.ContentItemId; + } + if (journalItem.SocialGroupId > 0) + { + try + { + UpdateGroupStats(journalItem.PortalId, journalItem.SocialGroupId); + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + } + public void DisableComments(int portalId, int journalId) + { + _dataService.Journal_Comments_ToggleDisable(portalId, journalId, true); + } + public void EnableComments(int portalId, int journalId) + { + _dataService.Journal_Comments_ToggleDisable(portalId, journalId, false); + } + public void HideComments(int portalId, int journalId) + { + _dataService.Journal_Comments_ToggleHidden(portalId, journalId, true); + } + public void ShowComments(int portalId, int journalId) + { + _dataService.Journal_Comments_ToggleHidden(portalId, journalId, false); + } + // Delete Journal Items + /// + /// HARD deletes journal items. + /// + /// + /// + /// + public void DeleteJournalItem(int portalId, int currentUserId, int journalId) + { + DeleteJournalItem(portalId, currentUserId, journalId, false); + } + /// + /// HARD deletes journal items based on item key + /// + /// + /// + public void DeleteJournalItemByKey(int portalId, string objectKey) + { + _dataService.Journal_DeleteByKey(portalId, objectKey); + } + /// + /// HARD deletes journal items based on group Id + /// + /// + /// + public void DeleteJournalItemByGroupId(int portalId, int groupId) + { + _dataService.Journal_DeleteByGroupId(portalId, groupId); + } + /// + /// SOFT deletes journal items. + /// + /// + /// + /// + public void SoftDeleteJournalItem(int portalId, int currentUserId, int journalId) + { + DeleteJournalItem(portalId, currentUserId, journalId, true); + } + /// + /// SOFT deletes journal items based on item key + /// + /// + /// + public void SoftDeleteJournalItemByKey(int portalId, string objectKey) + { + _dataService.Journal_SoftDeleteByKey(portalId, objectKey); + } + /// + /// SOFT deletes journal items based on group Id + /// + /// + /// + public void SoftDeleteJournalItemByGroupId(int portalId, int groupId) + { + _dataService.Journal_SoftDeleteByGroupId(portalId, groupId); + } + + // Journal Comments + public IList GetCommentsByJournalIds(List journalIdList) + { + var journalIds = journalIdList.Aggregate("", (current, journalId) => current + journalId + ";"); + return CBO.FillCollection(_dataService.Journal_Comment_ListByJournalIds(journalIds)); + } + + public void LikeJournalItem(int journalId, int userId, string displayName) + { + _dataService.Journal_Like(journalId, userId, displayName); + } + + public void SaveComment(CommentInfo comment) + { + var portalSecurity = new PortalSecurity(); + if (!String.IsNullOrEmpty(comment.Comment)) + { + comment.Comment = + HttpUtility.HtmlDecode(portalSecurity.InputFilter(comment.Comment, + PortalSecurity.FilterFlag.NoScripting)); + comment.Comment = portalSecurity.InputFilter(comment.Comment, PortalSecurity.FilterFlag.NoMarkup); + } + //TODO: enable once the profanity filter is working properly. + //objCommentInfo.Comment = portalSecurity.Remove(objCommentInfo.Comment, DotNetNuke.Security.PortalSecurity.ConfigType.ListController, "ProfanityFilter", DotNetNuke.Security.PortalSecurity.FilterScope.PortalList); + + if (comment.Comment != null && comment.Comment.Length > 2000) + { + comment.Comment = comment.Comment.Substring(0, 1999); + } + string xml = null; + if (comment.CommentXML != null) + { + xml = comment.CommentXML.OuterXml; + } + + comment.CommentId = _dataService.Journal_Comment_Save(comment.JournalId, comment.CommentId, comment.UserId, + comment.Comment, xml); + CommentInfo newComment = GetComment(comment.CommentId); + comment.DateCreated = newComment.DateCreated; + comment.DateUpdated = newComment.DateUpdated; + } + + public CommentInfo GetComment(int commentId) + { + return CBO.FillObject(_dataService.Journal_Comment_Get(commentId)); + } + + public void DeleteComment(int journalId, int commentId) + { + _dataService.Journal_Comment_Delete(journalId, commentId); + } + + public void LikeComment(int journalId, int commentId, int userId, string displayName) + { + _dataService.Journal_Comment_Like(journalId, commentId, userId, displayName); + } + + #endregion + + #region Journal Types + + public JournalTypeInfo GetJournalType(string journalType) + { + return CBO.FillObject(_dataService.Journal_Types_Get(journalType)); + } + + public JournalTypeInfo GetJournalTypeById(int journalTypeId) + { + return CBO.FillObject(_dataService.Journal_Types_GetById(journalTypeId)); + } + + public IEnumerable GetJournalTypes(int portalId) + { + return CBO.FillCollection(_dataService.Journal_Types_List(portalId)); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Journal/JournalEntity.cs b/DNN Platform/Library/Services/Journal/JournalEntity.cs new file mode 100644 index 00000000000..db2d6a8b177 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/JournalEntity.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using DotNetNuke.Services.Tokens; +namespace DotNetNuke.Services.Journal { + public class JournalEntity :IPropertyAccess { + public int Id {get;set;} + public string Name {get;set;} + public string Vanity {get; set;} + public string Avatar { get; set; } + public JournalEntity() { + } + public JournalEntity(string entityXML) { + if (!string.IsNullOrEmpty(entityXML)) { + System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument(); + xDoc.LoadXml(entityXML); + if ((xDoc != null)) { + System.Xml.XmlNode xRoot = xDoc.DocumentElement; + System.Xml.XmlNode xNode = null; + xNode = xRoot.SelectSingleNode("//entity"); + if ((xNode != null)) { + Id = int.Parse(xNode["id"].InnerText); + Name = xNode["name"].InnerText.ToString(); + if ((xNode["vanity"] != null)) { + Vanity= xNode["vanity"].InnerText.ToString(); + } + + } + } + } + } + + public CacheLevel Cacheability { + get { return CacheLevel.fullyCacheable; } + } + + public string GetProperty(string propertyName, string format, System.Globalization.CultureInfo formatProvider, Entities.Users.UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound) { + string OutputFormat = string.Empty; + if (format == string.Empty) { + OutputFormat = "g"; + } else { + OutputFormat = format; + } + propertyName = propertyName.ToLowerInvariant(); + switch (propertyName) { + case "id": + return PropertyAccess.FormatString(Id.ToString(), format); + case "name": + return PropertyAccess.FormatString(Name.ToString(), format); + case "vanity": + return PropertyAccess.FormatString(Vanity.ToString(), format); + case "avatar": + return PropertyAccess.FormatString(Avatar.ToString(), format); + + + } + + propertyNotFound = true; + return string.Empty; + } + } +} diff --git a/DNN Platform/Library/Services/Journal/JournalItem.cs b/DNN Platform/Library/Services/Journal/JournalItem.cs new file mode 100644 index 00000000000..b49c56e2e66 --- /dev/null +++ b/DNN Platform/Library/Services/Journal/JournalItem.cs @@ -0,0 +1,167 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Security; +using System.Xml; +using System.Xml.Serialization; +using DotNetNuke.Services.Tokens; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Web.Script.Serialization; + +#endregion + +namespace DotNetNuke.Services.Journal { + public class JournalItem : IHydratable, IPropertyAccess { + public int JournalId { get; set; } + public int JournalTypeId { get; set; } + public int PortalId { get; set; } + public int UserId { get; set; } + public int ProfileId { get; set; } + public int SocialGroupId { get; set; } + public string Title { get; set; } + public string Summary { get; set; } + public string Body { get; set; } + public ItemData ItemData { get; set; } + public XmlDocument JournalXML { get; set; } + public DateTime DateCreated { get; set; } + public DateTime DateUpdated { get; set; } + public string ObjectKey { get; set; } + public Guid AccessKey { get; set; } + public string SecuritySet { get; set; } + public int ContentItemId { get; set; } + public JournalEntity JournalAuthor { get; set; } + public JournalEntity JournalOwner { get; set; } + public string TimeFrame { get; set; } + public bool CurrentUserLikes { get; set; } + public string JournalType { get; set; } + public bool IsDeleted { get; set; } + public bool CommentsDisabled { get; set; } + public bool CommentsHidden { get; set; } + + /// + /// Gets or sets the key ID. + /// + /// + /// The key ID. + /// + /// + /// If you derive class has its own key id, please override this property and set the value to your own key id. + /// + [XmlIgnore] + public virtual int KeyID { + get { + return JournalId; + } + set { + JournalId = value; + } + } + + public void Fill(IDataReader dr) { + JournalId = Null.SetNullInteger(dr["JournalId"]); + JournalTypeId = Null.SetNullInteger(dr["JournalTypeId"]); + PortalId = Null.SetNullInteger(dr["PortalId"]); + UserId = Null.SetNullInteger(dr["UserId"]); + ProfileId = Null.SetNullInteger(dr["ProfileId"]); + SocialGroupId = Null.SetNullInteger(dr["GroupId"]); + if (!String.IsNullOrEmpty(Null.SetNullString(dr["JournalXML"]))) { + JournalXML = new XmlDocument(); + JournalXML.LoadXml(dr["JournalXML"].ToString()); + XmlNode xRoot = JournalXML.DocumentElement; + XmlNode xNode = xRoot.SelectSingleNode("//items/item/body"); + if (xNode != null) { + Body = xNode.InnerText; + } + } + DateCreated = Null.SetNullDateTime(dr["DateCreated"]); + DateUpdated = Null.SetNullDateTime(dr["DateUpdated"]); + ObjectKey = Null.SetNullString(dr["ObjectKey"]); + AccessKey = Null.SetNullGuid(dr["AccessKey"]); + Title = Null.SetNullString(dr["Title"]); + Summary = Null.SetNullString(dr["Summary"]); + string itemd = Null.SetNullString(dr["ItemData"]); + ItemData = new ItemData(); + if (!string.IsNullOrEmpty(itemd)) { + ItemData = itemd.FromJson(); + } + ContentItemId = Null.SetNullInteger(dr["ContentItemId"]); + JournalAuthor = new JournalEntity(dr["JournalAuthor"].ToString()); + JournalOwner = new JournalEntity(dr["JournalOwner"].ToString()); + JournalType = Null.SetNullString(dr["JournalType"]); + + IsDeleted = Null.SetNullBoolean(dr["IsDeleted"]); + CommentsDisabled = Null.SetNullBoolean(dr["CommentsDisabled"]); + CommentsHidden = Null.SetNullBoolean(dr["CommentsHidden"]); + } + public CacheLevel Cacheability { + get { + return CacheLevel.fullyCacheable; + } + } + + public string GetProperty(string propertyName, string format, System.Globalization.CultureInfo formatProvider, Entities.Users.UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound) { + string OutputFormat = string.Empty; + if (format == string.Empty) { + OutputFormat = "g"; + } else { + OutputFormat = format; + } + propertyName = propertyName.ToLowerInvariant(); + switch (propertyName) { + case "journalid": + return PropertyAccess.FormatString(JournalId.ToString(), format); + case "journaltypeid": + return PropertyAccess.FormatString(JournalTypeId.ToString(), format); + case "profileid": + return PropertyAccess.FormatString(ProfileId.ToString(), format); + case "socialgroupid": + return PropertyAccess.FormatString(SocialGroupId.ToString(), format); + case "datecreated": + return PropertyAccess.FormatString(DateCreated.ToString(), format); + case "title": + return PropertyAccess.FormatString(Title, format); + case "summary": + return PropertyAccess.FormatString(Summary, format); + case "body": + return PropertyAccess.FormatString(Body, format); + case "timeframe": + return PropertyAccess.FormatString(TimeFrame, format); + case "isdeleted": + return IsDeleted.ToString(); + } + + propertyNotFound = true; + return string.Empty; + + } + } +} diff --git a/DNN Platform/Library/Services/Journal/JournalTypeInfo.cs b/DNN Platform/Library/Services/Journal/JournalTypeInfo.cs new file mode 100644 index 00000000000..05bc7365a0a --- /dev/null +++ b/DNN Platform/Library/Services/Journal/JournalTypeInfo.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Common.Utilities; + +namespace DotNetNuke.Services.Journal { + public class JournalTypeInfo : IHydratable { + public int JournalTypeId { get; set; } + public int PortalId { get; set; } + public string JournalType { get; set; } + public string icon { get; set; } + public bool AppliesToProfile { get; set; } + public bool AppliesToGroup { get; set; } + public bool AppliesToStream { get; set; } + public bool SupportsNotify { get; set; } + public string Options { get; set; } + public bool IsEnabled { get; set; } + public bool EnableComments { get; set; } + public int KeyID { + get { + return JournalTypeId; + } + set { + JournalTypeId = value; + } + } + + public void Fill(System.Data.IDataReader dr) { + JournalTypeId = Null.SetNullInteger(dr["JournalTypeId"]); + PortalId = Null.SetNullInteger(dr["PortalId"]); + JournalType = Null.SetNullString(dr["JournalType"]); + icon = Null.SetNullString(dr["icon"]); + AppliesToProfile = Null.SetNullBoolean(dr["AppliesToProfile"]); + AppliesToGroup = Null.SetNullBoolean(dr["AppliesToGroup"]); + AppliesToStream = Null.SetNullBoolean(dr["AppliesToStream"]); + SupportsNotify = Null.SetNullBoolean(dr["SupportsNotify"]); + Options = Null.SetNullString(dr["Options"]); + IsEnabled = Null.SetNullBoolean(dr["IsEnabled"]); + EnableComments = Null.SetNullBoolean(dr["EnableComments"]); + } + } +} diff --git a/DNN Platform/Library/Services/Localization/CultureInfoComparer.cs b/DNN Platform/Library/Services/Localization/CultureInfoComparer.cs new file mode 100644 index 00000000000..e8460efed37 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/CultureInfoComparer.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.Globalization; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + public class CultureInfoComparer : IComparer + { + private readonly string _compare; + + public CultureInfoComparer(string compareBy) + { + _compare = compareBy; + } + + #region IComparer Members + + public int Compare(object x, object y) + { + switch (_compare.ToUpperInvariant()) + { + case "ENGLISH": + return ((CultureInfo) x).EnglishName.CompareTo(((CultureInfo) y).EnglishName); + case "NATIVE": + return ((CultureInfo) x).NativeName.CompareTo(((CultureInfo) y).NativeName); + default: + return ((CultureInfo) x).Name.CompareTo(((CultureInfo) y).Name); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/ILocaleController.cs b/DNN Platform/Library/Services/Localization/ILocaleController.cs new file mode 100644 index 00000000000..326b914b5a9 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/ILocaleController.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Globalization; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + public interface ILocaleController + { + bool CanDeleteLanguage(int languageId); + + List GetCultures(Dictionary locales); + + Locale GetCurrentLocale(int PortalId); + + Locale GetDefaultLocale(int portalId); + + Locale GetLocale(string code); + + Locale GetLocale(int portalID, string code); + + Locale GetLocale(int languageID); + + Dictionary GetLocales(int portalID); + + Dictionary GetPublishedLocales(int portalID); + + bool IsEnabled(ref string localeCode, int portalId); + + void UpdatePortalLocale(Locale locale); + + bool IsDefaultLanguage(string code); + + void PublishLanguage(int portalid, string cultureCode, bool publish); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/ILocalizationProvider.cs b/DNN Platform/Library/Services/Localization/ILocalizationProvider.cs new file mode 100644 index 00000000000..be086762897 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/ILocalizationProvider.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.Localization +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface ILocalizationProvider + { + string GetString(string key, string resourceFileRoot); + string GetString(string key, string resourceFileRoot, string language); + string GetString(string key, string resourceFileRoot, string language, PortalSettings portalSettings); + string GetString(string key, string resourceFileRoot, string language, PortalSettings portalSettings, bool disableShowMissingKeys); + } +} diff --git a/DNN Platform/Library/Services/Localization/Internal/ILocalization.cs b/DNN Platform/Library/Services/Localization/Internal/ILocalization.cs new file mode 100644 index 00000000000..1d968a407f9 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/Internal/ILocalization.cs @@ -0,0 +1,71 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Globalization; +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.Localization.Internal +{ + public interface ILocalization + { + /// + /// Inspect the browser supplied language headers and find the best match from the supplied list + /// + /// The codes to search for a match + /// The code to return if no good match is found + /// Best matching culture code, or fallback if no good match found + string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes, string fallback); + + /// + /// Inspect the browser supplied language headers and find the best match from the supplied list + /// + /// The codes to search for a match + /// Best matching culture code, or SystemLocale if no good match found + string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes); + + /// + /// Detects the current language for the request. + /// The order in which the language is being detect is: + /// 1. QueryString + /// 2. Cookie + /// 3. User profile (if request is authenticated) + /// 4. Browser preference (if portal has this option enabled) + /// 5. Portal default + /// 6. System default (en-US) + /// At any point, if a valid language is detected nothing else should be done + /// + /// Current PortalSettings + /// A valid CultureInfo + CultureInfo GetPageLocale(PortalSettings portalSettings); + + /// + /// Sets the culture codes on the current Thread + /// + /// Culture Info for the current page + /// The current portalSettings + /// + /// This method will configure the Thread culture codes. Any page which does not derive from PageBase should + /// be sure to call this method in OnInit to ensure localiztion works correctly. See the TelerikDialogHandler for an example. + /// + void SetThreadCultures(CultureInfo cultureInfo, PortalSettings portalSettings); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/Internal/LocalizationImpl.cs b/DNN Platform/Library/Services/Localization/Internal/LocalizationImpl.cs new file mode 100644 index 00000000000..4971d0421e5 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/Internal/LocalizationImpl.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.Localization.Internal +{ + internal class LocalizationImpl : ILocalization + { + public string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes, string fallback) + { + if(cultureCodes == null) + { + throw new ArgumentException("cultureCodes cannot be null"); + } + + if (fallback == null) + { + throw new ArgumentException("fallback cannot be null"); + } + + var values = cultureCodes.ToList(); + + foreach (string langHeader in HttpContextSource.Current.Request.UserLanguages ?? new string[0]) + { + string lang = langHeader; + //strip any ;q=xx + lang = lang.Split(';')[0]; + + //check for exact match e.g. de-DE == de-DE + if (lang.Contains('-')) + { + var match = values.FirstOrDefault(x => x == lang); + if(match != null) + { + return match; + } + } + + //only keep the initial language value + if (lang.Length > 1) + { + lang = lang.Substring(0, 2); + + //check for language match e.g. en-GB == en-US because en == en + var match = values.FirstOrDefault(x => x.StartsWith(lang)); + if (match != null) + { + return match; + } + } + } + + return fallback; + } + + public string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes) + { + return BestCultureCodeBasedOnBrowserLanguages(cultureCodes, Localization.SystemLocale); + } + + public CultureInfo GetPageLocale(PortalSettings portalSettings) + { + return Localization.GetPageLocale(portalSettings); + } + + public void SetThreadCultures(CultureInfo cultureInfo, PortalSettings portalSettings) + { + Localization.SetThreadCultures(cultureInfo, portalSettings); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/Internal/TestableLocalization.cs b/DNN Platform/Library/Services/Localization/Internal/TestableLocalization.cs new file mode 100644 index 00000000000..75abb8a5c98 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/Internal/TestableLocalization.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using DotNetNuke.Framework; + +namespace DotNetNuke.Services.Localization.Internal +{ + public class TestableLocalization : ServiceLocator + { + protected override Func GetFactory() + { + return () => new LocalizationImpl(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LanguagePackController.cs b/DNN Platform/Library/Services/Localization/LanguagePackController.cs new file mode 100644 index 00000000000..900794f560e --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LanguagePackController.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + public class LanguagePackController + { + public static void DeleteLanguagePack(LanguagePackInfo languagePack) + { + // fix DNN-26330 Removing a language pack extension removes the language + // we should not delete language when deleting language pack, as there is just a loose relationship + + //if (languagePack.PackageType == LanguagePackType.Core) + //{ + // Locale language = LocaleController.Instance.GetLocale(languagePack.LanguageID); + // if (language != null) + // { + // Localization.DeleteLanguage(language); + // } + //} + + DataProvider.Instance().DeleteLanguagePack(languagePack.LanguagePackID); + var objEventLog = new EventLogController(); + objEventLog.AddLog(languagePack, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGEPACK_DELETED); + } + + public static LanguagePackInfo GetLanguagePackByPackage(int packageID) + { + return CBO.FillObject(DataProvider.Instance().GetLanguagePackByPackage(packageID)); + } + + public static void SaveLanguagePack(LanguagePackInfo languagePack) + { + var objEventLog = new EventLogController(); + if (languagePack.LanguagePackID == Null.NullInteger) + { + //Add Language Pack + languagePack.LanguagePackID = DataProvider.Instance().AddLanguagePack(languagePack.PackageID, + languagePack.LanguageID, + languagePack.DependentPackageID, + UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(languagePack, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGEPACK_CREATED); + } + else + { + //Update LanguagePack + DataProvider.Instance().UpdateLanguagePack(languagePack.LanguagePackID, + languagePack.PackageID, + languagePack.LanguageID, + languagePack.DependentPackageID, + UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(languagePack, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGEPACK_UPDATED); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LanguagePackInfo.cs b/DNN Platform/Library/Services/Localization/LanguagePackInfo.cs new file mode 100644 index 00000000000..cb12a56e3f7 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LanguagePackInfo.cs @@ -0,0 +1,139 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + [Serializable] + public class LanguagePackInfo : BaseEntityInfo, IHydratable + { + #region "Private Members" + + private int _DependentPackageID = Null.NullInteger; + private int _LanguageID = Null.NullInteger; + private int _LanguagePackID = Null.NullInteger; + private int _PackageID = Null.NullInteger; + + #endregion + + #region "Public Properties" + + public int LanguagePackID + { + get + { + return _LanguagePackID; + } + set + { + _LanguagePackID = value; + } + } + + public int LanguageID + { + get + { + return _LanguageID; + } + set + { + _LanguageID = value; + } + } + + public int PackageID + { + get + { + return _PackageID; + } + set + { + _PackageID = value; + } + } + + public int DependentPackageID + { + get + { + return _DependentPackageID; + } + set + { + _DependentPackageID = value; + } + } + + public LanguagePackType PackageType + { + get + { + if (DependentPackageID == -2) + { + return LanguagePackType.Core; + } + else + { + return LanguagePackType.Extension; + } + } + } + + #endregion + + #region IHydratable Members + + public void Fill(IDataReader dr) + { + LanguagePackID = Null.SetNullInteger(dr["LanguagePackID"]); + LanguageID = Null.SetNullInteger(dr["LanguageID"]); + PackageID = Null.SetNullInteger(dr["PackageID"]); + DependentPackageID = Null.SetNullInteger(dr["DependentPackageID"]); + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + } + + public int KeyID + { + get + { + return LanguagePackID; + } + set + { + LanguagePackID = value; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LanguagePackType.cs b/DNN Platform/Library/Services/Localization/LanguagePackType.cs new file mode 100644 index 00000000000..8a74e320f32 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LanguagePackType.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Localization +{ + public enum LanguagePackType + { + Core, + Extension + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LanguagesListType.cs b/DNN Platform/Library/Services/Localization/LanguagesListType.cs new file mode 100644 index 00000000000..1f8464f377b --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LanguagesListType.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Localization +{ + /// ----------------------------------------------------------------------------- + /// + /// Enumeration that determines the type of Languages List + /// + /// + /// [cnurse] 2/19/2008 Created + /// + /// ----------------------------------------------------------------------------- + public enum LanguagesListType + { + All, + Supported, + Enabled + } +} diff --git a/DNN Platform/Library/Services/Localization/Locale.cs b/DNN Platform/Library/Services/Localization/Locale.cs new file mode 100644 index 00000000000..e2a91a2ffe0 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/Locale.cs @@ -0,0 +1,149 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Globalization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + /// + /// The Locale class is a custom business object that represents a locale, which is the language and country combination. + /// + [Serializable] + public class Locale : BaseEntityInfo, IHydratable + { + public Locale() + { + PortalId = Null.NullInteger; + LanguageId = Null.NullInteger; + IsPublished = Null.NullBoolean; + } + + #region Public Properties + + public string Code { get; set; } + + public CultureInfo Culture + { + get + { + return CultureInfo.CreateSpecificCulture(Code); + } + } + + public string EnglishName + { + get + { + string _Name = Null.NullString; + if (Culture != null) + { + _Name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Culture.EnglishName); + } + return _Name; + } + } + + public string Fallback { get; set; } + + public Locale FallBackLocale + { + get + { + Locale _FallbackLocale = null; + if (!string.IsNullOrEmpty(Fallback)) + { + _FallbackLocale = LocaleController.Instance.GetLocale(PortalId, Fallback); + } + return _FallbackLocale; + } + } + + public bool IsPublished { get; set; } + + public int LanguageId { get; set; } + + public string NativeName + { + get + { + string _Name = Null.NullString; + if (Culture != null) + { + _Name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Culture.NativeName); + } + return _Name; + } + } + + public int PortalId { get; set; } + + public string Text { get; set; } + + #endregion + + #region IHydratable Implementation + + public void Fill(IDataReader dr) + { + LanguageId = Null.SetNullInteger(dr["LanguageID"]); + Code = Null.SetNullString(dr["CultureCode"]); + Text = Null.SetNullString(dr["CultureName"]); + Fallback = Null.SetNullString(dr["FallbackCulture"]); + + //These fields may not be populated (for Host level locales) + DataTable schemaTable = dr.GetSchemaTable(); + bool hasColumns = schemaTable.Select("ColumnName = 'IsPublished' Or ColumnName = 'PortalID'").Length == 2; + + if(hasColumns) + { + IsPublished = Null.SetNullBoolean(dr["IsPublished"]); + PortalId = Null.SetNullInteger(dr["PortalID"]); + } + + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + } + + public int KeyID + { + get + { + return LanguageId; + } + set + { + LanguageId = value; + } + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Localization/LocaleCollection.cs b/DNN Platform/Library/Services/Localization/LocaleCollection.cs new file mode 100644 index 00000000000..7d83208ddf3 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LocaleCollection.cs @@ -0,0 +1,100 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Specialized; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + /// + /// The LocaleCollection class is a collection of Locale objects. It stores the supported locales. + /// + public class LocaleCollection : NameObjectCollectionBase + { + private DictionaryEntry _de; + + public DictionaryEntry this[int index] + { + get + { + _de.Key = BaseGetKey(index); + _de.Value = BaseGet(index); + return _de; + } + } + + //Gets or sets the value associated with the specified key. + public Locale this[string key] + { + get + { + return (Locale) BaseGet(key); + } + set + { + BaseSet(key, value); + } + } + + //Gets a String array that contains all the keys in the collection. + public string[] AllKeys + { + get + { + return BaseGetAllKeys(); + } + } + + //Gets an Object array that contains all the values in the collection. + public Array AllValues + { + get + { + return BaseGetAllValues(); + } + } + + //Gets a value indicating if the collection contains keys that are not null. + public Boolean HasKeys + { + get + { + return BaseHasKeys(); + } + } + + //Adds an entry to the collection. + public void Add(String key, Object value) + { + BaseAdd(key, value); + } + + //Removes an entry with the specified key from the collection. + public void Remove(String key) + { + BaseRemove(key); + } + } +} diff --git a/DNN Platform/Library/Services/Localization/LocaleCollectionWrapper.cs b/DNN Platform/Library/Services/Localization/LocaleCollectionWrapper.cs new file mode 100644 index 00000000000..83ccef256fd --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LocaleCollectionWrapper.cs @@ -0,0 +1,101 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + /// ----------------------------------------------------------------------------- + /// + /// The LocaleCollectionWrapper class provides a simple wrapper around a + /// . + /// + /// + /// The class + /// implements a custom dictionary class which does not provide for simple databinding. + /// This wrapper class exposes the individual objects of the underlying dictionary class + /// thereby allowing for simple databinding to the colleciton of objects. + /// + /// + /// [jbrinkman] 11/17/2004 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 5.0.")] + public class LocaleCollectionWrapper : IEnumerator, IEnumerable + { + private readonly LocaleCollection _locales; + private int _index; + + /// ----------------------------------------------------------------------------- + /// + /// Initializes a new instance of the + /// class containing the specified collection objects. + /// + /// A object + /// which is wrapped by the collection. + /// This overloaded constructor copies the s + /// from the indicated array. + /// + /// [jbrinkman] 11/17/2004 Created + /// + /// ----------------------------------------------------------------------------- + public LocaleCollectionWrapper(LocaleCollection Locales) + { + _locales = Locales; + } + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return this; + } + + #endregion + + #region IEnumerator Members + + public object Current + { + get + { + return _locales[_index]; + } + } + + public bool MoveNext() + { + _index += 1; + return _index < _locales.Keys.Count; + } + + public void Reset() + { + _index = 0; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Localization/LocaleController.cs b/DNN Platform/Library/Services/Localization/LocaleController.cs new file mode 100644 index 00000000000..97815ddb1bf --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LocaleController.cs @@ -0,0 +1,302 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Installer.Packages; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + /// + /// LocaleContrller provides method to manage all pages with localization content. + /// + /// + /// Content localization in DotNetNuke will allow you to easily manage your web pages in a primary language + /// and then utilize translators to keep the content synchronized in multiple secondary languages. + /// Whether you are maintaining your site in a single language or dozens of languages, the content localization system + /// will help guide your content editors and translators through the process. Although content localization required + /// extensive changes to the core platform, we have been able to add this new feature while still improving overall system performance. + /// + public class LocaleController : ComponentBase, ILocaleController + { + #region Private Shared Methods + + private static object GetLocalesCallBack(CacheItemArgs cacheItemArgs) + { + var portalID = (int)cacheItemArgs.ParamList[0]; + Dictionary locales = CBO.FillDictionary("CultureCode", portalID > Null.NullInteger + ? DataProvider.Instance().GetLanguagesByPortal(portalID) + : DataProvider.Instance().GetLanguages(), new Dictionary()); + return locales; + } + + #endregion + + #region Public Methods + + /// + /// Determines whether the language can be delete. + /// + /// The language id. + /// + /// true if the language can be delete; otherwise, false. + /// + public bool CanDeleteLanguage(int languageId) + { + return PackageController.GetPackagesByType("CoreLanguagePack") + .Select(package => LanguagePackController.GetLanguagePackByPackage(package.PackageID)) + .All(languagePack => languagePack.LanguageID != languageId); + } + + /// + /// Gets the cultures from local list. + /// + /// The locales. + /// culture list. + public List GetCultures(Dictionary locales) + { + return locales.Values.Select(locale => new CultureInfo(locale.Code)).ToList(); + } + + /// + /// Gets the current locale for current request to the portal. + /// + /// The portal id. + /// + public Locale GetCurrentLocale(int PortalId) + { + Locale locale = null; + + if (HttpContext.Current != null && !string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["language"])) + { + locale = GetLocale(HttpContext.Current.Request.QueryString["language"]); + } + return locale ?? ((PortalId == Null.NullInteger) + ? GetLocale(Localization.SystemLocale) + : GetDefaultLocale(PortalId)); + } + + /// + /// Gets the default locale of the portal. + /// + /// The portal id. + /// + public Locale GetDefaultLocale(int portalId) + { + PortalInfo portal = new PortalController().GetPortal(portalId); + Locale locale = null; + if (portal != null) + { + Dictionary locales = GetLocales(portal.PortalID); + if (locales != null && locales.ContainsKey(portal.DefaultLanguage)) + { + locale = locales[portal.DefaultLanguage]; + } + } + return locale ?? (GetLocale(Localization.SystemLocale)); + } + + /// + /// Gets the locale by code. + /// + /// The code. + /// + public Locale GetLocale(string code) + { + return GetLocale(Null.NullInteger, code); + } + + /// + /// Gets the locale included in the portal. + /// + /// The portal ID. + /// The code. + /// + public Locale GetLocale(int portalID, string code) + { + Dictionary dicLocales = GetLocales(portalID); + Locale locale = null; + + if (dicLocales != null) + { + dicLocales.TryGetValue(code, out locale); + } + + return locale; + } + + /// + /// Gets the locale. + /// + /// The language ID. + /// + public Locale GetLocale(int languageID) + { + Dictionary dicLocales = GetLocales(Null.NullInteger); + + return (from kvp in dicLocales where kvp.Value.LanguageId == languageID select kvp.Value).FirstOrDefault(); + } + + /// + /// Gets the locales. + /// + /// The portal ID. + /// + public Dictionary GetLocales(int portalID) + { + if (Globals.Status != Globals.UpgradeStatus.Error) + { + Dictionary locales; + if (Globals.Status != Globals.UpgradeStatus.Install) + { + string cacheKey = string.Format(DataCache.LocalesCacheKey, portalID); + locales = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.LocalesCacheTimeOut, DataCache.LocalesCachePriority, portalID), GetLocalesCallBack, true); + } + else + { + locales = CBO.FillDictionary("CultureCode", DataProvider.Instance().GetLanguages(), new Dictionary()); + } + return locales; + } + + return null; + } + + /// + /// Gets the published locales. + /// + /// The portal ID. + /// + public Dictionary GetPublishedLocales(int portalID) + { + return GetLocales(portalID).Where(kvp => kvp.Value.IsPublished).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } + + /// + /// Determines whether the specified locale code is enabled. + /// + /// The locale code. + /// The portal id. + /// + /// true if the specified locale code is enabled; otherwise, false. + /// + public bool IsEnabled(ref string localeCode, int portalId) + { + try + { + bool enabled = false; + Dictionary dicLocales = GetLocales(portalId); + + if ((!dicLocales.ContainsKey(localeCode))) + { + //if localecode is neutral (en, es,...) try to find a locale that has the same language + if (localeCode.IndexOf("-", StringComparison.Ordinal) == -1) + { + foreach (string strLocale in dicLocales.Keys) + { + if (strLocale.Split('-')[0] == localeCode) + { + //set the requested _localecode to the full locale + localeCode = strLocale; + enabled = true; + break; + } + } + } + } + else + { + enabled = true; + } + return enabled; + } + catch (Exception ex) + { + //item could not be retrieved or error + Exceptions.Exceptions.LogException(ex); + return false; + } + } + + /// + /// Updates the portal locale. + /// + /// The locale. + public void UpdatePortalLocale(Locale locale) + { + DataProvider.Instance().UpdatePortalLanguage(locale.PortalId, locale.LanguageId, locale.IsPublished, UserController.GetCurrentUserInfo().UserID); + DataCache.RemoveCache(string.Format(DataCache.LocalesCacheKey, locale.PortalId)); + } + + /// + /// Determines the language whether is default language. + /// + /// The code. + /// + /// true if the language is default language; otherwise, false. + /// + public bool IsDefaultLanguage(string code) + { + bool returnValue = code == PortalController.GetCurrentPortalSettings().DefaultLanguage; + return returnValue; + } + + /// + /// Publishes the language. + /// + /// The portalid. + /// The culture code. + /// if set to true will publishthe language. + public void PublishLanguage(int portalid, string cultureCode, bool publish) + { + Dictionary enabledLanguages = Instance.GetLocales(portalid); + Locale enabledlanguage; + if (enabledLanguages.TryGetValue(cultureCode, out enabledlanguage)) + { + enabledlanguage.IsPublished = publish; + Instance.UpdatePortalLocale(enabledlanguage); + if (publish) + { + // only publish tabs if we actually need to do that + // we cannot "unpublish" + var tabCtrl = new TabController(); + tabCtrl.PublishTabs(TabController.GetTabsBySortOrder(portalid, cultureCode, false)); + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/Localization.cs b/DNN Platform/Library/Services/Localization/Localization.cs new file mode 100644 index 00000000000..deab387fb88 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/Localization.cs @@ -0,0 +1,2295 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Web; +using System.Web.Hosting; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Cache; +using DotNetNuke.Services.Localization.Internal; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Tokens; +using DotNetNuke.UI.Modules; +using System.Text.RegularExpressions; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + /// + /// CultureDropDownTypes allows the user to specify which culture name is displayed in the drop down list that is filled + /// by using one of the helper methods. + /// + [Serializable] + public enum CultureDropDownTypes + { + /// + /// Displays the culture name in the format "<languagefull> (<country/regionfull>) in the .NET Framework language + /// + DisplayName, + /// + /// Displays the culture name in the format "<languagefull> (<country/regionfull>) in English + /// + EnglishName, + /// + /// Displays the culture identifier + /// + Lcid, + /// + /// Displays the culture name in the format "<languagecode2> (<country/regioncode2>) + /// + Name, + /// + /// Displays the culture name in the format "<languagefull> (<country/regionfull>) in the language that the culture is set to display + /// + NativeName, + /// + /// Displays the IS0 639-1 two letter code + /// + TwoLetterIsoCode, + /// + /// Displays the ISO 629-2 three letter code "<languagefull> (<country/regionfull>) + /// + ThreeLetterIsoCode + } + + /// + /// Localization class support localization in system. + /// + /// + /// As DNN is used in more and more countries it is very important to provide modules with + /// good support for international users. Otherwise we are limiting our potential user base to + /// that using English as their base language. + /// + /// You can store the muti language content in resource files and use the api below to get localization content. + /// Resouces files named as: Control(Page)Name + Extension (.aspx/.ascx ) + Language + ".resx" + /// e.g: Installwizard.aspx.de-DE.resx + /// + /// + /// + /// + /// pageCreationProgressArea.Localization.Total = Localization.GetString("TotalLanguages", LocalResourceFile); + /// pageCreationProgressArea.Localization.TotalFiles = Localization.GetString("TotalPages", LocalResourceFile); + /// pageCreationProgressArea.Localization.Uploaded = Localization.GetString("TotalProgress", LocalResourceFile); + /// pageCreationProgressArea.Localization.UploadedFiles = Localization.GetString("Progress", LocalResourceFile); + /// pageCreationProgressArea.Localization.CurrentFileName = Localization.GetString("Processing", LocalResourceFile); + /// + /// + public class Localization + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Localization)); + #region Private Members + + private static string _defaultKeyName = "resourcekey"; + //private static readonly ILocaleController LocaleController.Instance = LocaleController.Instance; + //private static readonly ILocalizationProvider _localizationProvider = LocalizationProvider.Instance; + private static Nullable _showMissingKeys; + + #endregion + + #region Public Shared Properties + + public static string ApplicationResourceDirectory + { + get + { + return "~/App_GlobalResources"; + } + } + + public static string ExceptionsResourceFile + { + get + { + return ApplicationResourceDirectory + "/Exceptions.resx"; + } + } + + public static string GlobalResourceFile + { + get + { + return ApplicationResourceDirectory + "/GlobalResources.resx"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The KeyName property returns and caches the name of the key attribute used to lookup resources. + /// This can be configured by setting ResourceManagerKey property in the web.config file. The default value for this property + /// is 'key'. + /// + /// ----------------------------------------------------------------------------- + public static string KeyName + { + get + { + return _defaultKeyName; + } + set + { + _defaultKeyName = value; + if (String.IsNullOrEmpty(_defaultKeyName)) + { + _defaultKeyName = "resourcekey"; + } + } + } + + public static string LocalResourceDirectory + { + get + { + return "App_LocalResources"; + } + } + + public static string LocalSharedResourceFile + { + get + { + return "SharedResources.resx"; + } + } + + public static string SharedResourceFile + { + get + { + return ApplicationResourceDirectory + "/SharedResources.resx"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The ShowMissingKeys property returns the web.config setting that determines + /// whether to render a visual indicator that a key is missing + /// is 'key'. + /// + /// + /// + /// + /// [cnurse] 11/20/2006 Documented + /// + /// ----------------------------------------------------------------------------- + public static bool ShowMissingKeys + { + get + { + if (_showMissingKeys == null) + { + if (Config.GetSetting("ShowMissingKeys") == null) + { + _showMissingKeys = false; + } + else + { + _showMissingKeys = bool.Parse(Config.GetSetting("ShowMissingKeys".ToLower())); + } + } + + return _showMissingKeys.Value; + } + } + + public static string SupportedLocalesFile + { + get + { + return ApplicationResourceDirectory + "/Locales.xml"; + } + } + + public static string SystemLocale + { + get + { + return "en-US"; + } + } + + public static string SystemTimeZone + { + get + { + return "Pacific Standard Time"; + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// The CurrentCulture returns the current Culture being used + /// is 'key'. + /// + /// ----------------------------------------------------------------------------- + public string CurrentCulture + { + get + { + //_CurrentCulture + return Thread.CurrentThread.CurrentCulture.ToString(); + } + } + + /// + /// The CurrentUICulture for the Thread + /// + public string CurrentUICulture + { + // _CurrentCulture + get + { + return Thread.CurrentThread.CurrentUICulture.ToString(); + } + } + + #endregion + + #region Private Shared Methods + + private static void LocalizeDataControlField(DataControlField controlField, string resourceFile) + { + string localizedText; + + //Localize Header Text + if (!string.IsNullOrEmpty(controlField.HeaderText)) + { + localizedText = GetString((controlField.HeaderText + ".Header"), resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + controlField.HeaderText = localizedText; + controlField.AccessibleHeaderText = controlField.HeaderText; + } + } + if (controlField is TemplateField) + { + //do nothing + } + else if (controlField is ButtonField) + { + var button = (ButtonField)controlField; + localizedText = GetString(button.Text, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + button.Text = localizedText; + } + } + else if (controlField is CheckBoxField) + { + var checkbox = (CheckBoxField)controlField; + localizedText = GetString(checkbox.Text, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + checkbox.Text = localizedText; + } + } + else if (controlField is CommandField) + { + var commands = (CommandField)controlField; + localizedText = GetString(commands.CancelText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.CancelText = localizedText; + } + localizedText = GetString(commands.DeleteText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.DeleteText = localizedText; + } + localizedText = GetString(commands.EditText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.EditText = localizedText; + } + localizedText = GetString(commands.InsertText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.InsertText = localizedText; + } + localizedText = GetString(commands.NewText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.NewText = localizedText; + } + localizedText = GetString(commands.SelectText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.SelectText = localizedText; + } + localizedText = GetString(commands.UpdateText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + commands.UpdateText = localizedText; + } + } + else if (controlField is HyperLinkField) + { + var link = (HyperLinkField)controlField; + localizedText = GetString(link.Text, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + link.Text = localizedText; + } + } + else if (controlField is ImageField) + { + var image = (ImageField)controlField; + localizedText = GetString(image.AlternateText, resourceFile); + if (!string.IsNullOrEmpty(localizedText)) + { + image.AlternateText = localizedText; + } + } + } + + #endregion + + #region Public Methods + + public static int ActiveLanguagesByPortalID(int portalID) + { + //Default to 1 (maybe called during portal creation before languages are enabled for portal) + + int count = 1; + Dictionary locales = LocaleController.Instance.GetLocales(portalID); + if (locales != null) + { + count = locales.Count; + } + return count; + } + + public static void AddLanguageToPortal(int portalID, int languageID, bool clearCache) + { + + // try to get valid locale reference + var newLocale = LocaleController.Instance.GetLocale(languageID); + + // we can only add a valid locale + if (newLocale != null) + { + // check if locale has not been added to portal already + var portalLocale = LocaleController.Instance.GetLocale(portalID, newLocale.Code); + + // locale needs to be added + if (portalLocale == null) + { + //We need to add a translator role for the language + bool contentLocalizationEnabled = PortalController.GetPortalSettingAsBoolean("ContentLocalizationEnabled", portalID, false); + if (contentLocalizationEnabled) + { + //Create new Translator Role + AddTranslatorRole(portalID, newLocale); + } + + DataProvider.Instance().AddPortalLanguage(portalID, languageID, false, UserController.GetCurrentUserInfo().UserID); + string cacheKey = string.Format(DataCache.LocalesCacheKey, portalID); + DataCache.RemoveCache(cacheKey); + + var objEventLog = new EventLogController(); + objEventLog.AddLog("portalID/languageID", + portalID + "/" + languageID, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.LANGUAGETOPORTAL_CREATED); + + var portalInfo = new PortalController().GetPortal(portalID); + if (portalInfo != null && newLocale.Code != portalInfo.DefaultLanguage) + { + // check to see if this is the first extra language being added to the portal + var portalLocales = LocaleController.Instance.GetLocales(portalID); + var firstExtraLanguage = (portalLocales != null) && portalLocales.Count == 2; + + if (firstExtraLanguage) + { + AddLanguageHttpAlias(portalID, LocaleController.Instance.GetLocale(portalID, portalInfo.DefaultLanguage)); + } + AddLanguageHttpAlias(portalID, newLocale); + } + + if (clearCache) + { + DataCache.ClearPortalCache(portalID, false); + } + } + } + } + + + private static void AddLanguageHttpAlias(int portalId, Locale locale) + { + string message = ""; + if (Config.GetFriendlyUrlProvider() == "advanced") + { + // create new HTTPAlias for language + var portalInfo = new PortalController().GetPortal(portalId); + PortalAliasInfo currentAlias = null; + string httpAlias = null; + + var portalAliasses = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalId); + var portalAliasInfos = portalAliasses as IList ?? portalAliasses.ToList(); + if (portalAliasses != null && portalAliasInfos.Any()) + { + currentAlias = portalAliasInfos.First(); + httpAlias = currentAlias.HTTPAlias; + } + + if (currentAlias != null && !string.IsNullOrEmpty(httpAlias) && portalInfo != null) + { + + if (!string.IsNullOrEmpty(currentAlias.CultureCode)) + { + // the portal alias is culture specific + if (currentAlias.CultureCode == portalInfo.CultureCode) + { + // remove the culture from the alias + httpAlias = httpAlias.Substring(0, httpAlias.LastIndexOf("/", StringComparison.Ordinal)); + } + } + + var alias = GetValidLanguageURL(portalId, httpAlias, locale.Code.ToLowerInvariant()); + if (!String.IsNullOrEmpty(alias)) + { + var newAlias = new PortalAliasInfo(currentAlias) + { + IsPrimary = true, + CultureCode = locale.Code, + HTTPAlias = GetValidLanguageURL(portalId, httpAlias, locale.Code.ToLowerInvariant()) + }; + + TestablePortalAliasController.Instance.AddPortalAlias(newAlias); + } + } + } + } + + private static string GetValidLanguageURL(int portalId, string httpAlias, string locale) + { + string alias; + + bool isValid; + int counter = 0; + do + { + string modifiedLocale = locale; + if (counter > 0) + { + modifiedLocale += counter.ToString(CultureInfo.InvariantCulture); + } + + alias = String.Format("{0}/{1}", httpAlias, modifiedLocale); + + var tab = new TabController().GetTabByName(modifiedLocale, portalId); + isValid = (tab == null); + + if (isValid) + { + var user = UserController.GetUserByVanityUrl(portalId, modifiedLocale); + isValid = (user == null); + } + + if (isValid) + { + PortalAliasInfo existingAlias; + TestablePortalAliasController.Instance.GetPortalAliases().TryGetValue(alias, out existingAlias); + + isValid = (existingAlias == null); + } + + if (isValid) + { + isValid = PortalAliasController.ValidateAlias(alias, false); + } + + counter++; + } while (!isValid); + + return alias; + } + + public static void AddLanguagesToPortal(int portalID) + { + foreach (Locale language in LocaleController.Instance.GetLocales(Null.NullInteger).Values) + { + //Add Portal/Language to PortalLanguages + AddLanguageToPortal(portalID, language.LanguageId, false); + } + DataCache.RemoveCache(String.Format(DataCache.LocalesCacheKey, portalID)); + } + + public static void AddLanguageToPortals(int languageID) + { + var controller = new PortalController(); + foreach (PortalInfo portal in controller.GetPortals()) + { + //Add Portal/Language to PortalLanguages + AddLanguageToPortal(portal.PortalID, languageID, false); + + DataCache.RemoveCache(String.Format(DataCache.LocalesCacheKey, portal.PortalID)); + } + } + + public static void AddTranslatorRole(int portalID, Locale language) + { + //Create new Translator Role + string roleName = string.Format("Translator ({0})", language.Code); + RoleInfo role = TestableRoleController.Instance.GetRole(portalID, r => r.RoleName == roleName); + + if (role == null) + { + role = new RoleInfo(); + role.RoleGroupID = Null.NullInteger; + role.PortalID = portalID; + role.RoleName = roleName; + role.Description = string.Format("A role for {0} translators", language.EnglishName); + role.SecurityMode = SecurityMode.SecurityRole; + role.Status = RoleStatus.Approved; + TestableRoleController.Instance.AddRole(role); + } + + string roles = string.Format("Administrators;{0}", string.Format("Translator ({0})", language.Code)); + + PortalController.UpdatePortalSetting(portalID, string.Format("DefaultTranslatorRoles-{0}", language.Code), roles); + } + + /// + /// Converts old TimeZoneOffset to new TimeZoneInfo. + /// + /// An offset in minutes, e.g. -480 (-8 times 60) for Pasicif Time Zone + /// TimeZoneInfo is returned if timeZoneOffsetInMinutes is valid, otherwise TimeZoneInfo.Local is returned. + /// Initial mapping is based on hard-coded rules. These rules are hard-coded from old standard TimeZones.xml data. + /// When offset is not found hard-coded mapping, a lookup is performed in timezones defined in the system. The first found entry is returned. + /// When mapping is not found, a default TimeZoneInfo.Local us returned. + public static TimeZoneInfo ConvertLegacyTimeZoneOffsetToTimeZoneInfo(int timeZoneOffsetInMinutes) + { + TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local; + + //lookup existing mapping + switch (timeZoneOffsetInMinutes) + { + case -720: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Dateline Standard Time"); + break; + case -660: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Samoa Standard Time"); + break; + case -600: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time"); + break; + case -540: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Alaskan Standard Time"); + break; + case -480: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); + break; + case -420: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time"); + break; + case -360: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); + break; + case -300: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); + break; + case -240: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Atlantic Standard Time"); + break; + case -210: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Newfoundland Standard Time"); + break; + case -180: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Argentina Standard Time"); + break; + case -120: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Mid-Atlantic Standard Time"); + break; + case -60: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Cape Verde Standard Time"); + break; + case 0: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); + break; + case 60: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); + break; + case 120: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time"); + break; + case 180: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"); + break; + case 210: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Iran Standard Time"); + break; + case 240: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Arabian Standard Time"); + break; + case 270: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Afghanistan Standard Time"); + break; + case 300: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pakistan Standard Time"); + break; + case 330: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time"); + break; + case 345: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Nepal Standard Time"); + break; + case 360: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Asia Standard Time"); + break; + case 390: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Myanmar Standard Time"); + break; + case 420: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time"); + break; + case 480: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"); + break; + case 540: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); + break; + case 570: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Cen. Australia Standard Time"); + break; + case 600: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time"); + break; + case 660: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Magadan Standard Time"); + break; + case 720: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("New Zealand Standard Time"); + break; + case 780: + timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Tonga Standard Time"); + break; + default: + foreach (TimeZoneInfo timeZone in TimeZoneInfo.GetSystemTimeZones()) + { + if (timeZone.BaseUtcOffset.TotalMinutes == timeZoneOffsetInMinutes) + { + timeZoneInfo = timeZone; + break; + } + } + break; + } + + return timeZoneInfo; + } + + public static void DeleteLanguage(Locale language) + { + //remove languages from all portals + RemoveLanguageFromPortals(language.LanguageId); + + DataProvider.Instance().DeleteLanguage(language.LanguageId); + var objEventLog = new EventLogController(); + objEventLog.AddLog(language, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGE_DELETED); + DataCache.ClearHostCache(true); + } + + + public static string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes, string fallback) + { + return TestableLocalization.Instance.BestCultureCodeBasedOnBrowserLanguages(cultureCodes, fallback); + } + + public static string BestCultureCodeBasedOnBrowserLanguages(IEnumerable cultureCodes) + { + return TestableLocalization.Instance.BestCultureCodeBasedOnBrowserLanguages(cultureCodes); + } + + #region GetExceptionMessage + + public static string GetExceptionMessage(string key, string defaultValue) + { + if (HttpContext.Current == null) + { + return defaultValue; + } + return GetString(key, ExceptionsResourceFile); + } + + public static string GetExceptionMessage(string key, string defaultValue, params object[] @params) + { + if (HttpContext.Current == null) + { + return string.Format(defaultValue, @params); + } + var content = GetString(key, ExceptionsResourceFile); + return string.Format(String.IsNullOrEmpty(content) ? defaultValue : GetString(key, ExceptionsResourceFile), @params); + } + + #endregion + + public string GetFixedCurrency(decimal expression, string culture, int numDigitsAfterDecimal) + { + string oldCurrentCulture = CurrentUICulture; + var newCulture = new CultureInfo(culture); + Thread.CurrentThread.CurrentUICulture = newCulture; + string currencyStr = expression.ToString(newCulture.NumberFormat.CurrencySymbol); + var oldCulture = new CultureInfo(oldCurrentCulture); + Thread.CurrentThread.CurrentUICulture = oldCulture; + return currencyStr; + } + + public string GetFixedDate(DateTime expression, string culture) + { + string oldCurrentCulture = CurrentUICulture; + var newCulture = new CultureInfo(culture); + Thread.CurrentThread.CurrentUICulture = newCulture; + string dateStr = expression.ToString(newCulture.DateTimeFormat.FullDateTimePattern); + var oldCulture = new CultureInfo(oldCurrentCulture); + Thread.CurrentThread.CurrentUICulture = oldCulture; + return dateStr; + } + + public static string GetLanguageDisplayMode(int portalId) + { + string viewTypePersonalizationKey = "ViewType" + portalId; + string viewType = Convert.ToString(Personalization.Personalization.GetProfile("LanguageDisplayMode", viewTypePersonalizationKey)); + if (string.IsNullOrEmpty(viewType)) + { + viewType = "NATIVE"; + } + return viewType; + } + + public static string GetLocaleName(string code, CultureDropDownTypes displayType) + { + string name; + + // Create a CultureInfo class based on culture + CultureInfo info = CultureInfo.CreateSpecificCulture(code); + + // Based on the display type desired by the user, select the correct property + switch (displayType) + { + case CultureDropDownTypes.EnglishName: + name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(info.EnglishName); + break; + case CultureDropDownTypes.Lcid: + name = info.LCID.ToString(); + break; + case CultureDropDownTypes.Name: + name = info.Name; + break; + case CultureDropDownTypes.NativeName: + name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(info.NativeName); + break; + case CultureDropDownTypes.TwoLetterIsoCode: + name = info.TwoLetterISOLanguageName; + break; + case CultureDropDownTypes.ThreeLetterIsoCode: + name = info.ThreeLetterISOLanguageName; + break; + default: + name = info.DisplayName; + break; + } + + return name; + } + + #region Language detection + /// + /// Detects the current language for the request. + /// The order in which the language is being detect is: + /// 1. QueryString + /// 2. Cookie + /// 3. User profile (if request is authenticated) + /// 4. Browser preference (if portal has this option enabled) + /// 5. Portal default + /// 6. System default (en-US) + /// At any point, if a valid language is detected nothing else should be done + /// + /// Current PortalSettings + /// A valid CultureInfo + public static CultureInfo GetPageLocale(PortalSettings portalSettings) + { + CultureInfo pageCulture = null; + + // 1. querystring + if (portalSettings != null) + pageCulture = GetCultureFromQs(portalSettings); + + // 2. cookie + if (portalSettings != null && pageCulture == null) + pageCulture = GetCultureFromCookie(portalSettings); + + // 3. user preference + if (portalSettings != null && pageCulture == null) + pageCulture = GetCultureFromProfile(portalSettings); + + // 4. browser + if (portalSettings != null && pageCulture == null) + pageCulture = GetCultureFromBrowser(portalSettings); + + // 5. portal default + if (portalSettings != null && pageCulture == null) + pageCulture = GetCultureFromPortal(portalSettings); + + // 6. system default + if (pageCulture == null) + pageCulture = new CultureInfo(SystemLocale); + + // finally set the cookie + SetLanguage(pageCulture.Name); + return pageCulture; + } + + /// + /// Tries to get a valid language from the querystring + /// + /// Current PortalSettings + /// A valid CultureInfo if any is found + private static CultureInfo GetCultureFromQs(PortalSettings portalSettings) + { + if (HttpContext.Current == null || HttpContext.Current.Request["language"] == null) + return null; + + string language = HttpContext.Current.Request["language"]; + CultureInfo culture = GetCultureFromString(portalSettings.PortalId, language); + return culture; + } + + /// + /// Tries to get a valid language from the cookie + /// + /// Current PortalSettings + /// A valid CultureInfo if any is found + private static CultureInfo GetCultureFromCookie(PortalSettings portalSettings) + { + CultureInfo culture; + if (HttpContext.Current == null || HttpContext.Current.Request.Cookies["language"] == null) + return null; + + string language = HttpContext.Current.Request.Cookies["language"].Value; + culture = GetCultureFromString(portalSettings.PortalId, language); + return culture; + } + + /// + /// Tries to get a valid language from the user profile + /// + /// Current PortalSettings + /// A valid CultureInfo if any is found + private static CultureInfo GetCultureFromProfile(PortalSettings portalSettings) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + + if (HttpContext.Current == null || !HttpContext.Current.Request.IsAuthenticated || objUserInfo.UserID == -1) + return null; + + string language = objUserInfo.Profile.PreferredLocale; + CultureInfo culture = GetCultureFromString(portalSettings.PortalId, language); + return culture; + } + + /// + /// Tries to get a valid language from the browser preferences if the portal has the setting + /// to use browser languages enabled. + /// + /// Current PortalSettings + /// A valid CultureInfo if any is found + private static CultureInfo GetCultureFromBrowser(PortalSettings portalSettings) + { + if (!portalSettings.EnableBrowserLanguage) + return null; + else + return GetBrowserCulture(portalSettings.PortalId); + } + + /// + /// Tries to get a valid language from the portal default preferences + /// + /// Current PortalSettings + /// A valid CultureInfo if any is found + private static CultureInfo GetCultureFromPortal(PortalSettings portalSettings) + { + CultureInfo culture = null; + if (!String.IsNullOrEmpty(portalSettings.DefaultLanguage)) + { + // As the portal default language can never be disabled, we know this language is available and enabled + culture = new CultureInfo(portalSettings.DefaultLanguage); + } + else + { + // Get the first enabled locale on the portal + Dictionary enabledLocales = new Dictionary(); + if (portalSettings.PortalId > Null.NullInteger) + enabledLocales = LocaleController.Instance.GetLocales(portalSettings.PortalId); + + if (enabledLocales.Count > 0) + { + foreach (string localeCode in enabledLocales.Keys) + { + culture = new CultureInfo(localeCode); + break; + } + } + } + return culture; + } + + /// + /// Tries to get a valid language from the browser preferences + /// + /// Id of the current portal + /// A valid CultureInfo if any is found + public static CultureInfo GetBrowserCulture(int portalId) + { + if (HttpContext.Current == null || HttpContext.Current.Request == null || HttpContext.Current.Request.UserLanguages == null) + return null; + + CultureInfo culture = null; + foreach (string userLang in HttpContext.Current.Request.UserLanguages) + { + //split userlanguage by ";"... all but the first language will contain a preferrence index eg. ;q=.5 + string language = userLang.Split(';')[0]; + culture = GetCultureFromString(portalId, language); + if (culture != null) + break; + } + return culture; + } + + /// + /// Parses the language parameter into a valid and enabled language in the current portal. + /// If an exact match is not found (language-region), it will try to find a match for the language only. + /// Ex: requested locale is "en-GB", requested language is "en", enabled locale is "en-US", so "en" is a match for "en-US". + /// + /// Id of current portal + /// Language to be parsed + /// A valid and enabled CultureInfo that matches the language passed if any. + private static CultureInfo GetCultureFromString(int portalId, string language) + { + CultureInfo culture = null; + if (!String.IsNullOrEmpty(language)) + { + if (LocaleController.Instance.IsEnabled(ref language, portalId)) + culture = new CultureInfo(language); + else + { + string preferredLanguage = language.Split('-')[0]; + + Dictionary enabledLocales = new Dictionary(); + if (portalId > Null.NullInteger) + enabledLocales = LocaleController.Instance.GetLocales(portalId); + + foreach (string localeCode in enabledLocales.Keys) + { + if (localeCode.Split('-')[0] == preferredLanguage.Split('-')[0]) + { + culture = new CultureInfo(localeCode); + break; + } + } + } + } + return culture; + } + #endregion + + public static string GetResourceFileName(string resourceFileName, string language, string mode, int portalId) + { + if (!resourceFileName.EndsWith(".resx")) + { + resourceFileName += ".resx"; + } + if (language != SystemLocale) + { + if (resourceFileName.ToLowerInvariant().EndsWith(".en-us.resx")) + { + resourceFileName = resourceFileName.Substring(0, resourceFileName.Length - 11) + "." + language + ".resx"; + } + else + { + resourceFileName = resourceFileName.Substring(0, resourceFileName.Length - 5) + "." + language + ".resx"; + } + } + if (mode == "Host") + { + resourceFileName = resourceFileName.Substring(0, resourceFileName.Length - 5) + "." + "Host.resx"; + } + else if (mode == "Portal") + { + resourceFileName = resourceFileName.Substring(0, resourceFileName.Length - 5) + "." + "Portal-" + portalId + ".resx"; + } + return resourceFileName; + } + + public static string GetResourceFile(Control control, string fileName) + { + return control.TemplateSourceDirectory + "/" + LocalResourceDirectory + "/" + fileName; + } + + #region GetString + + public static string GetString(string key, Control ctrl) + { + //We need to find the parent module + Control parentControl = ctrl.Parent; + string localizedText; + var moduleControl = parentControl as IModuleControl; + if (moduleControl == null) + { + PropertyInfo pi = parentControl.GetType().GetProperty("LocalResourceFile"); + if (pi != null) + { + //If control has a LocalResourceFile property use this + localizedText = GetString(key, pi.GetValue(parentControl, null).ToString()); + } + else + { + //Drill up to the next level + localizedText = GetString(key, parentControl); + } + } + else + { + //We are at the Module Level so return key + //Get Resource File Root from Parents LocalResourceFile Property + localizedText = GetString(key, moduleControl.LocalResourceFile); + } + return localizedText; + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resource key + /// + /// The resource key to find + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key) + { + return GetString(key, null, PortalController.GetCurrentPortalSettings(), null, false); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The current portals Portal Settings + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, PortalSettings portalSettings) + { + return LocalizationProvider.Instance.GetString(key, null, null, portalSettings); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Local Resource root + /// Disable to show missing key. + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, string resourceFileRoot, bool disableShowMissingKeys) + { + return GetString(key, resourceFileRoot, PortalController.GetCurrentPortalSettings(), null, disableShowMissingKeys); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Resource File Name. + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, string resourceFileRoot) + { + return LocalizationProvider.Instance.GetString(key, resourceFileRoot); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Local Resource root + /// A specific language to lookup the string + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, string resourceFileRoot, string language) + { + return LocalizationProvider.Instance.GetString(key, resourceFileRoot, language); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Local Resource root + /// The current portals Portal Settings + /// A specific language to lookup the string + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, string resourceFileRoot, PortalSettings portalSettings, string language) + { + return GetString(key, resourceFileRoot, portalSettings, language, false); + } + + /// ----------------------------------------------------------------------------- + /// One of six overloads + /// + /// GetString gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Local Resource root + /// The current portals Portal Settings + /// A specific language to lookup the string + /// Disables the show missing keys flag + /// The localized Text + /// + /// [cnurse] 10/06/2004 Documented + /// [cnurse] 01/30/2008 Refactored to use Dictionaries and to cahe the portal and host + /// customisations and language versions separately + /// + /// ----------------------------------------------------------------------------- + public static string GetString(string key, string resourceFileRoot, PortalSettings portalSettings, string language, bool disableShowMissingKeys) + { + return LocalizationProvider.Instance.GetString(key, resourceFileRoot, language, portalSettings, disableShowMissingKeys); + } + + #endregion + + #region GetStringUrl + + /// ----------------------------------------------------------------------------- + /// + /// GetStringUrl gets the localized string corresponding to the resourcekey + /// + /// The resourcekey to find + /// The Local Resource root + /// The localized Text + /// + /// This function should be used to retrieve strings to be used on URLs. + /// It is the same as GetString(name,ResourceFileRoot) method + /// but it disables the ShowMissingKey flag, so even it testing scenarios, the correct string + /// is returned + /// + /// ----------------------------------------------------------------------------- + public static string GetStringUrl(string key, string resourceFileRoot) + { + return GetString(key, resourceFileRoot, PortalController.GetCurrentPortalSettings(), null, true); + } + + #endregion + + #region GetSafeJSString + + /// + /// this function will escape reserved character fields to their "safe" javascript equivalents + /// + /// The string to be parsed for unsafe characters + /// the string that is safe to use in a javascript function + public static string GetSafeJSString(string unsafeString) + { + return !string.IsNullOrEmpty(unsafeString) && unsafeString.Length > 0 ? Regex.Replace(unsafeString, "(['\"\\\\])", "\\$1") : unsafeString; + } + + /// + /// this function will escape reserved character fields to their "safe" javascript equivalents + /// + /// localization key + /// file for localization key + /// the string that is safe to use in a javascript function + public static string GetSafeJSString(string key, string resourceFileRoot) + { + var unsafeString = GetString(key, resourceFileRoot); + return GetSafeJSString(unsafeString); + } + + #endregion + + #region Get System Message + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// The message body with all tags replaced. + /// + /// Supported tags: + /// - All fields from HostSettings table in the form of: [Host:field] + /// - All properties defined in in the form of: [Portal:property] + /// - [Portal:URL]: The base URL for the portal + /// - All properties defined in in the form of: [User:property] + /// - All values stored in the user profile in the form of: [Profile:key] + /// - [User:VerificationCode]: User verification code for verified registrations + /// - [Date:Current]: Current date + /// + /// + /// [Vicen] 05/07/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName) + { + return GetSystemMessage(null, portalSettings, messageName, null, GlobalResourceFile, null); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The message body with all tags replaced. + /// + /// Supported tags: + /// - All fields from HostSettings table in the form of: [Host:field] + /// - All properties defined in in the form of: [Portal:property] + /// - [Portal:URL]: The base URL for the portal + /// - All properties defined in in the form of: [User:property] + /// - All values stored in the user profile in the form of: [Profile:key] + /// - [User:VerificationCode]: User verification code for verified registrations + /// - [Date:Current]: Current date + /// + /// + /// [Vicen] 05/07/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName, UserInfo userInfo) + { + return GetSystemMessage(null, portalSettings, messageName, userInfo, GlobalResourceFile, null); + } + + /// ----------------------------------------------------------------------------- + /// + /// /// Gets a SystemMessage. + /// + /// A specific language to get the SystemMessage for. + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The message body with all tags replaced. + /// + /// Supported tags: + /// - All fields from HostSettings table in the form of: [Host:field] + /// - All properties defined in in the form of: [Portal:property] + /// - [Portal:URL]: The base URL for the portal + /// - All properties defined in in the form of: [User:property] + /// - All values stored in the user profile in the form of: [Profile:key] + /// - [User:VerificationCode]: User verification code for verified registrations + /// - [Date:Current]: Current date + /// + /// + /// [Vicen] 05/07/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(string strLanguage, PortalSettings portalSettings, string messageName, UserInfo userInfo) + { + return GetSystemMessage(strLanguage, portalSettings, messageName, userInfo, GlobalResourceFile, null); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// The root name of the Resource File where the localized + /// text can be found + /// The message body with all tags replaced. + /// + /// Supported tags: + /// - All fields from HostSettings table in the form of: [Host:field] + /// - All properties defined in in the form of: [Portal:property] + /// - [Portal:URL]: The base URL for the portal + /// - All properties defined in in the form of: [User:property] + /// - All values stored in the user profile in the form of: [Profile:key] + /// - [User:VerificationCode]: User verification code for verified registrations + /// - [Date:Current]: Current date + /// + /// + /// [Vicen] 05/07/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName, string resourceFile) + { + return GetSystemMessage(null, portalSettings, messageName, null, resourceFile, null); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The root name of the Resource File where the localized + /// text can be found + /// The message body with all tags replaced. + /// + /// Supported tags: + /// - All fields from HostSettings table in the form of: [Host:field] + /// - All properties defined in in the form of: [Portal:property] + /// - [Portal:URL]: The base URL for the portal + /// - All properties defined in in the form of: [User:property] + /// - All values stored in the user profile in the form of: [Profile:key] + /// - [User:VerificationCode]: User verification code for verified registrations + /// - [Date:Current]: Current date + /// + /// + /// [Vicen] 05/07/2004 Documented + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName, UserInfo userInfo, string resourceFile) + { + return GetSystemMessage(null, portalSettings, messageName, userInfo, resourceFile, null); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage passing extra custom parameters to personalize. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// The root name of the Resource File where the localized + /// text can be found + /// An ArrayList with replacements for custom tags. + /// The message body with all tags replaced. + /// + /// Custom tags are of the form [Custom:n], where n is the zero based index which + /// will be used to find the replacement value in Custom parameter. + /// + /// + /// [Vicen] 05/07/2004 Documented + /// [cnurse] 10/06/2004 Moved from SystemMessages to Localization + /// [DanCaron] 10/27/2004 Simplified Profile replacement, added Membership replacement + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName, string resourceFile, ArrayList custom) + { + return GetSystemMessage(null, portalSettings, messageName, null, resourceFile, custom); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage passing extra custom parameters to personalize. + /// + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The root name of the Resource File where the localized + /// text can be found + /// An ArrayList with replacements for custom tags. + /// The message body with all tags replaced. + /// + /// Custom tags are of the form [Custom:n], where n is the zero based index which + /// will be used to find the replacement value in Custom parameter. + /// + /// + /// [Vicen] 05/07/2004 Documented + /// [cnurse] 10/06/2004 Moved from SystemMessages to Localization + /// [DanCaron] 10/27/2004 Simplified Profile replacement, added Membership replacement + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(PortalSettings portalSettings, string messageName, UserInfo userInfo, string resourceFile, ArrayList custom) + { + return GetSystemMessage(null, portalSettings, messageName, userInfo, resourceFile, custom); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage passing extra custom parameters to personalize. + /// + /// A specific language to get the SystemMessage for. + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The root name of the Resource File where the localized + /// text can be found + /// An ArrayList with replacements for custom tags. + /// The message body with all tags replaced. + /// + /// Custom tags are of the form [Custom:n], where n is the zero based index which + /// will be used to find the replacement value in Custom parameter. + /// + /// + /// [Vicen] 05/07/2004 Documented + /// [cnurse] 10/06/2004 Moved from SystemMessages to Localization + /// [DanCaron] 10/27/2004 Simplified Profile replacement, added Membership replacement + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(string strLanguage, PortalSettings portalSettings, string messageName, UserInfo userInfo, string resourceFile, ArrayList custom) + { + return GetSystemMessage(strLanguage, portalSettings, messageName, userInfo, resourceFile, custom, null, "", -1); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage passing extra custom parameters to personalize. + /// + /// A specific language to get the SystemMessage for. + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The root name of the Resource File where the localized + /// text can be found + /// An ArrayList with replacements for custom tags. + /// prefix for custom tags + /// UserID of the user accessing the system message + /// The message body with all tags replaced. + /// + /// Custom tags are of the form [Custom:n], where n is the zero based index which + /// will be used to find the replacement value in Custom parameter. + /// + /// + /// [Vicen] 05/07/2004 Documented + /// [cnurse] 10/06/2004 Moved from SystemMessages to Localization + /// [DanCaron] 10/27/2004 Simplified Profile replacement, added Membership replacement + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(string strLanguage, PortalSettings portalSettings, string messageName, UserInfo userInfo, string resourceFile, ArrayList custom, string customCaption, + int accessingUserID) + { + return GetSystemMessage(strLanguage, portalSettings, messageName, userInfo, resourceFile, custom, null, customCaption, accessingUserID); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a SystemMessage passing extra custom parameters to personalize. + /// + /// A specific language to get the SystemMessage for. + /// The portal settings for the portal to which the message will affect. + /// The message tag which identifies the SystemMessage. + /// Reference to the user used to personalize the message. + /// The root name of the Resource File where the localized + /// text can be found + /// An ArrayList with replacements for custom tags. + /// An IDictionary with replacements for custom tags. + /// prefix for custom tags + /// UserID of the user accessing the system message + /// The message body with all tags replaced. + /// + /// Custom tags are of the form [Custom:n], where n is the zero based index which + /// will be used to find the replacement value in Custom parameter. + /// + /// + /// [cnurse] 09/09/2009 created + /// + /// ----------------------------------------------------------------------------- + public static string GetSystemMessage(string strLanguage, PortalSettings portalSettings, string messageName, UserInfo userInfo, string resourceFile, ArrayList customArray, + IDictionary customDictionary, string customCaption, int accessingUserID) + { + string strMessageValue = GetString(messageName, resourceFile, portalSettings, strLanguage); + if (!String.IsNullOrEmpty(strMessageValue)) + { + if (String.IsNullOrEmpty(customCaption)) + { + customCaption = "Custom"; + } + var objTokenReplace = new TokenReplace(Scope.SystemMessages, strLanguage, portalSettings, userInfo); + if ((accessingUserID != -1) && (userInfo != null)) + { + if (userInfo.UserID != accessingUserID) + { + objTokenReplace.AccessingUser = new UserController().GetUser(portalSettings.PortalId, accessingUserID); + } + } + if (customArray != null) + { + strMessageValue = objTokenReplace.ReplaceEnvironmentTokens(strMessageValue, customArray, customCaption); + } + else + { + strMessageValue = objTokenReplace.ReplaceEnvironmentTokens(strMessageValue, customDictionary, customCaption); + } + } + return strMessageValue; + } + + #endregion + + #region LoadCultureDropDownList + + /// + /// LoadCultureDropDownList loads a DropDownList with the list of supported cultures + /// based on the languages defined in the supported locales file, for the current portal + /// + /// DropDownList to load + /// Format of the culture to display. Must be one the CultureDropDownTypes values. + /// for list of allowable values + /// Name of the default culture to select + public static void LoadCultureDropDownList(DropDownList list, CultureDropDownTypes displayType, string selectedValue) + { + LoadCultureDropDownList(list, displayType, selectedValue, "", false); + } + + /// + /// LoadCultureDropDownList loads a DropDownList with the list of supported cultures + /// based on the languages defined in the supported locales file. + /// This overload allows us to display all installed languages. To do so, pass the value True to the Host parameter + /// + /// DropDownList to load + /// Format of the culture to display. Must be one the CultureDropDownTypes values. + /// for list of allowable values + /// Name of the default culture to select + /// Boolean that defines wether or not to load host (ie. all available) locales + public static void LoadCultureDropDownList(DropDownList list, CultureDropDownTypes displayType, string selectedValue, bool loadHost) + { + LoadCultureDropDownList(list, displayType, selectedValue, "", loadHost); + } + + /// + /// LoadCultureDropDownList loads a DropDownList with the list of supported cultures + /// based on the languages defined in the supported locales file + /// This overload allows us to filter a language from the dropdown. To do so pass a language code to the Filter parameter + /// This overload allows us to display all installed languages. To do so, pass the value True to the Host parameter + /// + /// DropDownList to load + /// Format of the culture to display. Must be one the CultureDropDownTypes values. + /// for list of allowable values + /// Name of the default culture to select + /// String value that allows for filtering out a specific language + /// Boolean that defines wether or not to load host (ie. all available) locales + public static void LoadCultureDropDownList(DropDownList list, CultureDropDownTypes displayType, string selectedValue, string filter, bool host) + { + IEnumerable cultureListItems = LoadCultureInListItems(displayType, selectedValue, filter, host); + + //add the items to the list + foreach (var cultureItem in cultureListItems) + { + list.Items.Add(cultureItem); + } + + //select the default item + if (selectedValue != null) + { + ListItem item = list.Items.FindByValue(selectedValue); + if (item != null) + { + list.SelectedIndex = -1; + item.Selected = true; + } + } + } + + /// + /// LoadCultureDropDownList loads a DropDownList with the list of supported cultures + /// based on the languages defined in the supported locales file + /// This overload allows us to filter a language from the dropdown. To do so pass a language code to the Filter parameter + /// This overload allows us to display all installed languages. To do so, pass the value True to the Host parameter + /// + /// + /// + /// + /// + /// + public static IEnumerable LoadCultureInListItems(CultureDropDownTypes displayType, string selectedValue, string filter, bool host) + { + PortalSettings objPortalSettings = PortalController.GetCurrentPortalSettings(); + Dictionary enabledLanguages; + if (host) + { + enabledLanguages = LocaleController.Instance.GetLocales(Null.NullInteger); + } + else + { + enabledLanguages = LocaleController.Instance.GetLocales(objPortalSettings.PortalId); + } + + var cultureListItems = new List(enabledLanguages.Count); + foreach (KeyValuePair kvp in enabledLanguages) + { + if (kvp.Value.Code != filter) + { + cultureListItems.Add(new ListItem { Value = kvp.Value.Code, Text = GetLocaleName(kvp.Value.Code, displayType) }); + } + } + + return cultureListItems; + } + + #endregion + + /// ----------------------------------------------------------------------------- + /// + /// Localizes ModuleControl Titles + /// + /// ModuleControl + /// + /// Localized control title if found + /// + /// + /// Resource keys are: ControlTitle_[key].Text + /// Key MUST be lowercase in the resource file + /// + /// + /// [vmasanas] 08/11/2004 Created + /// [cnurse] 11/28/2008 Modified Signature + /// + /// ----------------------------------------------------------------------------- + public static string LocalizeControlTitle(IModuleControl moduleControl) + { + string controlTitle = moduleControl.ModuleContext.Configuration.ModuleTitle; + string controlKey = moduleControl.ModuleContext.Configuration.ModuleControl.ControlKey.ToLower(); + + if (!string.IsNullOrEmpty(controlTitle) && !string.IsNullOrEmpty(controlKey)) + { + controlTitle = moduleControl.ModuleContext.Configuration.ModuleControl.ControlTitle; + } + + if (!string.IsNullOrEmpty(controlKey)) + { + string reskey = "ControlTitle_" + moduleControl.ModuleContext.Configuration.ModuleControl.ControlKey.ToLower() + ".Text"; + string localizedvalue = GetString(reskey, moduleControl.LocalResourceFile); + if (string.IsNullOrEmpty(localizedvalue)) + { + controlTitle = moduleControl.ModuleContext.Configuration.ModuleControl.ControlTitle; + } + else + { + controlTitle = localizedvalue; + } + } + return controlTitle; + } + + /// ----------------------------------------------------------------------------- + /// + /// LocalizeDataGrid creates localized Headers for a DataGrid + /// + /// Grid to localize + /// The root name of the Resource File where the localized + /// text can be found + /// + /// [cnurse] 9/10/2004 Created + /// + /// ----------------------------------------------------------------------------- + public static void LocalizeDataGrid(ref DataGrid grid, string resourceFile) + { + string localizedText; + foreach (DataGridColumn col in grid.Columns) + { + //Localize Header Text + if (!string.IsNullOrEmpty(col.HeaderText)) + { + localizedText = GetString(col.HeaderText + ".Header", resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + col.HeaderText = localizedText; + } + } + if (col is EditCommandColumn) + { + var editCol = (EditCommandColumn)col; + + //Edit Text - maintained for backward compatibility + localizedText = GetString(editCol.EditText + ".EditText", resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + editCol.EditText = localizedText; + } + + //Edit Text + localizedText = GetString(editCol.EditText, resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + editCol.EditText = localizedText; + } + + //Cancel Text + localizedText = GetString(editCol.CancelText, resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + editCol.CancelText = localizedText; + } + + //Update Text + localizedText = GetString(editCol.UpdateText, resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + editCol.UpdateText = localizedText; + } + } + else if (col is ButtonColumn) + { + var buttonCol = (ButtonColumn)col; + + //Edit Text + localizedText = GetString(buttonCol.Text, resourceFile); + if (!String.IsNullOrEmpty(localizedText)) + { + buttonCol.Text = localizedText; + } + } + } + } + + /// + /// Localizes headers and fields on a DetailsView control + /// + /// + /// The root name of the resource file where the localized + /// texts can be found + /// + public static void LocalizeDetailsView(ref DetailsView detailsView, string resourceFile) + { + foreach (DataControlField field in detailsView.Fields) + { + LocalizeDataControlField(field, resourceFile); + } + } + + /// + /// Localizes headers and fields on a GridView control + /// + /// Grid to localize + /// The root name of the resource file where the localized + /// texts can be found + /// + public static void LocalizeGridView(ref GridView gridView, string resourceFile) + { + foreach (DataControlField column in gridView.Columns) + { + LocalizeDataControlField(column, resourceFile); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Localizes the "Built In" Roles + /// + /// + /// Localizes: + /// -DesktopTabs + /// -BreadCrumbs + /// + /// + /// [cnurse] 02/01/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static string LocalizeRole(string role) + { + string localRole; + switch (role) + { + case Globals.glbRoleAllUsersName: + case Globals.glbRoleSuperUserName: + case Globals.glbRoleUnauthUserName: + string roleKey = role.Replace(" ", ""); + localRole = GetString(roleKey); + break; + default: + localRole = role; + break; + } + return localRole; + } + + public static void RemoveLanguageFromPortal(int portalID, int languageID) + { + //Remove Translator Role from Portal + Locale language = LocaleController.Instance.GetLocale(languageID); + if (language != null) + { + if (Config.GetFriendlyUrlProvider() == "advanced") + { + // only do this with Advanced URL Management + + var portalInfo = new PortalController().GetPortal(portalID); + if (portalInfo != null) + { + // check to see if this is the last extra language being added to the portal + var lastLanguage = LocaleController.Instance.GetLocales(portalID).Count == 2; + + var portalAliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalID); + foreach (var portalAliasInfo in portalAliases) + { + if (portalAliasInfo.CultureCode == language.Code) + { + TestablePortalAliasController.Instance.DeletePortalAlias(portalAliasInfo); + } + + if (lastLanguage && portalAliasInfo.CultureCode == portalInfo.DefaultLanguage) + { + TestablePortalAliasController.Instance.DeletePortalAlias(portalAliasInfo); + } + } + } + } + + //Get Translator Role + string roleName = string.Format("Translator ({0})", language.Code); + RoleInfo role = TestableRoleController.Instance.GetRole(portalID, r => r.RoleName == roleName); + + if (role != null) + { + TestableRoleController.Instance.DeleteRole(role); + } + + DataProvider.Instance().DeletePortalLanguages(portalID, languageID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("portalID/languageID", + portalID + "/" + languageID, + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.LANGUAGETOPORTAL_DELETED); + + DataCache.ClearPortalCache(portalID, false); + } + } + + public static void RemoveLanguageFromPortals(int languageID) + { + var controller = new PortalController(); + foreach (PortalInfo portal in controller.GetPortals()) + { + RemoveLanguageFromPortal(portal.PortalID, languageID); + } + } + + public static void RemoveLanguagesFromPortal(int portalID) + { + foreach (Locale locale in LocaleController.Instance.GetLocales(portalID).Values) + { + RemoveLanguageFromPortal(portalID, locale.LanguageId); + } + } + + public static void SaveLanguage(Locale locale) + { + SaveLanguage(locale, true); + } + + + public static void SaveLanguage(Locale locale, bool clearCache) + { + var objEventLog = new EventLogController(); + if (locale.LanguageId == Null.NullInteger) + { + locale.LanguageId = DataProvider.Instance().AddLanguage(locale.Code, locale.Text, locale.Fallback, UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(locale, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGE_CREATED); + } + else + { + DataProvider.Instance().UpdateLanguage(locale.LanguageId, locale.Code, locale.Text, locale.Fallback, UserController.GetCurrentUserInfo().UserID); + objEventLog.AddLog(locale, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.LANGUAGE_UPDATED); + } + if (clearCache) + DataCache.ClearHostCache(true); + } + + public static void SetLanguage(string value) + { + try + { + HttpResponse response = HttpContext.Current.Response; + if (response == null) + { + return; + } + + //save the page culture as a cookie + HttpCookie cookie = response.Cookies.Get("language"); + if ((cookie == null)) + { + if (!String.IsNullOrEmpty(value)) + { + cookie = new HttpCookie("language", value); + response.Cookies.Add(cookie); + } + } + else + { + cookie.Value = value; + if (!String.IsNullOrEmpty(value)) + { + response.Cookies.Set(cookie); + } + else + { + response.Cookies.Remove("language"); + } + } + } + catch + { + return; + } + } + + /// + /// Sets the culture codes on the current Thread + /// + /// Culture Info for the current page + /// The current portalSettings + /// + /// This method will configure the Thread culture codes. Any page which does not derive from PageBase should + /// be sure to call this method in OnInit to ensure localiztion works correctly. See the TelerikDialogHandler for an example. + /// + public static void SetThreadCultures(CultureInfo cultureInfo, PortalSettings portalSettings) + { + if (cultureInfo == null) + { + throw new ArgumentNullException("cultureInfo"); + } + + Thread.CurrentThread.CurrentCulture = cultureInfo; + + if (portalSettings != null && portalSettings.ContentLocalizationEnabled && + HttpContext.Current.Request.IsAuthenticated && + portalSettings.AllowUserUICulture) + { + Thread.CurrentThread.CurrentUICulture = GetUserUICulture(cultureInfo, portalSettings); + } + else + { + Thread.CurrentThread.CurrentUICulture = cultureInfo; + } + } + + /// + /// When portal allows users to select their preferred UI language, this method + /// will return the user ui preferred language if defined. Otherwise defaults + /// to the current culture + /// + /// Current culture + /// PortalSettings for the current request + /// + private static CultureInfo GetUserUICulture(CultureInfo currentCulture, PortalSettings portalSettings) + { + CultureInfo uiCulture = currentCulture; + try + { + object oCulture = Personalization.Personalization.GetProfile("Usability", "UICulture"); + if (oCulture != null) + { + CultureInfo ci = GetCultureFromString(portalSettings.PortalId, oCulture.ToString()); + if (ci != null) + uiCulture = ci; + } + } + catch + { + // UserCulture seems not valid anymore, update to current culture + Personalization.Personalization.SetProfile("Usability", "UICulture", currentCulture.Name); + } + return uiCulture; + } + + /// + /// Maps the culture code string into the corresponding language ID in the + /// database. In case there is no language defined in the systen with the + /// passed code, -1 () is returned. + /// + /// The culture to get the language ID for. + /// Language ID integer + public static int GetCultureLanguageID(string cultureCode) + { + var locale = LocaleController.Instance.GetLocale(cultureCode); + return locale != null ? locale.LanguageId : Null.NullInteger; + } + #endregion + + #region Obsolete + + [Obsolete("Deprecated in DNN 5.0. Replaced by GetLocales().")] + public static LocaleCollection GetEnabledLocales() + { + PortalSettings objPortalSettings = PortalController.GetCurrentPortalSettings(); + var enabledLocales = new LocaleCollection(); + foreach (KeyValuePair kvp in LocaleController.Instance.GetLocales(objPortalSettings.PortalId)) + { + enabledLocales.Add(kvp.Key, kvp.Value); + } + return enabledLocales; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by GetLocales().")] + public static LocaleCollection GetSupportedLocales() + { + var supportedLocales = new LocaleCollection(); + foreach (KeyValuePair kvp in LocaleController.Instance.GetLocales(Null.NullInteger)) + { + supportedLocales.Add(kvp.Key, kvp.Value); + } + return supportedLocales; + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by LocaleController.GetLocale(code).")] + public static Locale GetLocale(string code) + { + return GetLocale(Null.NullInteger, code); + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by LocaleController.GetLocale(portalID, code).")] + public static Locale GetLocale(int portalID, string code) + { + Dictionary dicLocales = LocaleController.Instance.GetLocales(portalID); + Locale language = null; + + if (dicLocales != null) + { + dicLocales.TryGetValue(code, out language); + } + + return language; + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by LocaleController.GetLocale(languageID).")] + public static Locale GetLocaleByID(int languageID) + { + Dictionary dicLocales = LocaleController.Instance.GetLocales(Null.NullInteger); + Locale language = null; + + foreach (KeyValuePair kvp in dicLocales) + { + if (kvp.Value.LanguageId == languageID) + { + language = kvp.Value; + break; + } + } + + return language; + } + + [Obsolete("Deprecated in DNN 5.5. Replaced by LocaleController.GetLocales(portalID).")] + public static Dictionary GetLocales(int portalID) + { + return LocaleController.Instance.GetLocales(portalID); + } + + [Obsolete("Deprecated in DNN 6.0. Replaced by SystemTimeZone and use of .NET TimeZoneInfo class")] + public static NameValueCollection GetTimeZones(string language) + { + language = language.ToLower(); + string cacheKey = "dotnetnuke-" + language + "-timezones"; + string translationFile; + if (language == SystemLocale.ToLower()) + { + translationFile = TimezonesFile; + } + else + { + translationFile = TimezonesFile.Replace(".xml", "." + language + ".xml"); + } + var timeZones = (NameValueCollection)DataCache.GetCache(cacheKey); + if (timeZones == null) + { + string filePath = HttpContext.Current.Server.MapPath(translationFile); + timeZones = new NameValueCollection(); + if (File.Exists(filePath) == false) + { + return timeZones; + } + var dp = new DNNCacheDependency(filePath); + try + { + var d = new XmlDocument(); + d.Load(filePath); + foreach (XmlNode n in d.SelectSingleNode("root").ChildNodes) + { + if (n.NodeType != XmlNodeType.Comment) + { + timeZones.Add(n.Attributes["name"].Value, n.Attributes["key"].Value); + } + } + } + catch (Exception exc) + { + Logger.Error(exc); + + } + if (Host.PerformanceSetting != Globals.PerformanceSettings.NoCaching) + { + DataCache.SetCache(cacheKey, timeZones, dp); + } + } + return timeZones; + } + + [Obsolete("Deprecated in DNN 5.5. Replcaed by LocaleController.IsEnabled()")] + public static bool LocaleIsEnabled(Locale locale) + { + return LocaleIsEnabled(locale.Code); + } + + [Obsolete("Deprecated in DNN 5.5. Replcaed by LocaleController.IsEnabled()")] + public static bool LocaleIsEnabled(string localeCode) + { + PortalSettings _Settings = PortalController.GetCurrentPortalSettings(); + + return LocaleController.Instance.IsEnabled(ref localeCode, _Settings.PortalId); + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by LocalizeControlTitle(IModuleControl).")] + public static string LocalizeControlTitle(string controlTitle, string controlSrc, string Key) + { + string reskey; + reskey = "ControlTitle_" + Key.ToLower() + ".Text"; + string resFile = controlSrc.Substring(0, controlSrc.LastIndexOf("/") + 1) + LocalResourceDirectory + + controlSrc.Substring(controlSrc.LastIndexOf("/"), controlSrc.LastIndexOf(".") - controlSrc.LastIndexOf("/")); + if (resFile.StartsWith("DesktopModules")) + { + resFile = "~/" + resFile; + } + string localizedvalue = GetString(reskey, resFile); + if (localizedvalue != null) + { + return localizedvalue; + } + else + { + return controlTitle; + } + } + + [Obsolete("Deprecated in DNN 5.0. This does nothing now as the Admin Tabs are treated like any other tab.")] + public static void LocalizePortalSettings() + { + } + + [Obsolete("Deprecated in DNN 6.0. Replaced by SystemTimeZone and use of .NET TimeZoneInfo class")] + public static int SystemTimeZoneOffset + { + get + { + return -480; + } + } + + [Obsolete("Deprecated in DNN 6.0. Replaced by SystemTimeZone and use of .NET TimeZoneInfo class")] + public static string TimezonesFile + { + get + { + return ApplicationResourceDirectory + "/TimeZones.xml"; + } + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by Host.EnableBrowserLanguage OR PortalSettings.EnableBrowserLanguage")] + public static bool UseBrowserLanguage() + { + return PortalController.GetCurrentPortalSettings().EnableBrowserLanguage; + } + + [Obsolete("Deprecated in DNN 5.0. Replaced by Host.EnableUrlLanguage OR PortalSettings.EnableUrlLanguage")] + public static bool UseLanguageInUrl() + { + return PortalController.GetCurrentPortalSettings().EnableUrlLanguage; + } + + [Obsolete("Deprecated in DNN 6.0. Replaced by new DnnTimeZoneComboBox control and use of .NET TimeZoneInfo class")] + public static void LoadTimeZoneDropDownList(DropDownList list, string language, string selectedValue) + { + NameValueCollection timeZones = GetTimeZones(language); + //If no Timezones defined get the System Locale Time Zones + if (timeZones.Count == 0) + { + timeZones = GetTimeZones(SystemLocale.ToLower()); + } + int i; + for (i = 0; i <= timeZones.Keys.Count - 1; i++) + { + list.Items.Add(new ListItem(timeZones.GetKey(i), timeZones.Get(i))); + } + + //select the default item + if (selectedValue != null) + { + ListItem item = list.Items.FindByValue(selectedValue); + if (item == null) + { + //Try system default + item = list.Items.FindByValue(SystemTimeZoneOffset.ToString()); + } + if (item != null) + { + list.SelectedIndex = -1; + item.Selected = true; + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LocalizationExpressionBuilder.cs b/DNN Platform/Library/Services/Localization/LocalizationExpressionBuilder.cs new file mode 100644 index 00000000000..d972f2da35d --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LocalizationExpressionBuilder.cs @@ -0,0 +1,123 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.CodeDom; +using System.ComponentModel; +using System.IO; +using System.Web; +using System.Web.Compilation; +using System.Web.UI; +using System.Web.UI.Design; + +#endregion + +namespace DotNetNuke.Services.Localization +{ + [ExpressionPrefix("dnnLoc"), ExpressionEditor("DotNetNuke.Services.Localization.LocalizationExpressionBuilderEditor")] + public class LocalizationExpressionBuilder : ExpressionBuilder + { + public override bool SupportsEvaluate + { + get + { + return true; + } + } + + public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context) + { + var inputParams = new CodeExpression[] + { + new CodePrimitiveExpression(entry.Expression.Trim()), + new CodeTypeOfExpression(entry.DeclaringType), + new CodePrimitiveExpression(entry.PropertyInfo.Name), + new CodePrimitiveExpression(context.VirtualPath) + }; + + return new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(GetType()), "GetLocalizedResource", inputParams); + } + + public static object GetLocalizedResource(string key, Type targetType, string propertyName, string virtualPath) + { + if (HttpContext.Current == null) + { + return null; + } + + string localResourceFile = ""; + if (!string.IsNullOrEmpty(virtualPath)) + { + string filename = Path.GetFileName(virtualPath); + if (filename != null) + { + localResourceFile = virtualPath.Replace(filename, Localization.LocalResourceDirectory + "/" + filename); + } + } + string value = Localization.GetString(key, localResourceFile); + + if (value == null) + { + throw new InvalidOperationException(string.Format("Localized Value '{0}' not found.", key)); + } + + // check if value can be converted to property type + if (targetType != null) + { + PropertyDescriptor propDesc = TypeDescriptor.GetProperties(targetType)[propertyName]; + if (propDesc != null && propDesc.PropertyType != value.GetType()) + { + // Type mismatch - make sure that the value can be converted to the Web control property type + if (propDesc.Converter != null) + { + if (propDesc.Converter.CanConvertFrom(value.GetType()) == false) + { + throw new InvalidOperationException(string.Format("Localized value '{0}' cannot be converted to type {1}.", key, propDesc.PropertyType)); + } + return propDesc.Converter.ConvertFrom(value); + } + } + } + + // If we reach here, no type mismatch - return the value + return value; + } + + public override object EvaluateExpression(object target, BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context) + { + string key = entry.Expression.Trim(); + Type targetType = entry.DeclaringType; + string propertyName = entry.PropertyInfo.Name; + string virtualPath = context.VirtualPath; + + return GetLocalizedResource(key, targetType, propertyName, virtualPath); + } + } + + public class LocalizationExpressionBuilderEditor : ExpressionEditor + { + public override object EvaluateExpression(string expression, object parseTimeData, Type propertyType, IServiceProvider serviceProvider) + { + return string.Concat("[dnnLoc:", expression, "]"); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Localization/LocalizationProvider.cs b/DNN Platform/Library/Services/Localization/LocalizationProvider.cs new file mode 100644 index 00000000000..056274c1af6 --- /dev/null +++ b/DNN Platform/Library/Services/Localization/LocalizationProvider.cs @@ -0,0 +1,425 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Web.Hosting; +using System.Xml.XPath; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Cache; + +namespace DotNetNuke.Services.Localization +{ + public class LocalizationProvider : ComponentBase, ILocalizationProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(LocalizationProvider)); + #region Nested type: CustomizedLocale + + private enum CustomizedLocale + { + None = 0, + Portal = 1, + Host = 2 + } + + #endregion + + #region Implementation of ILocalizationProvider + + public string GetString(string key, string resourceFileRoot) + { + return GetString(key, resourceFileRoot, null, PortalController.GetCurrentPortalSettings(), false); + } + + public string GetString(string key, string resourceFileRoot, string language) + { + return GetString(key, resourceFileRoot, language, PortalController.GetCurrentPortalSettings(), false); + } + + public string GetString(string key, string resourceFileRoot, string language, PortalSettings portalSettings) + { + return GetString(key, resourceFileRoot, language, portalSettings, false); + } + + public string GetString(string key, string resourceFileRoot, string language, PortalSettings portalSettings, bool disableShowMissingKeys) + { + //make the default translation property ".Text" + if (key.IndexOf(".", StringComparison.Ordinal) < 1) + { + key += ".Text"; + } + string resourceValue = Null.NullString; + bool keyFound = TryGetStringInternal(key, language, resourceFileRoot, portalSettings, ref resourceValue); + + //If the key can't be found then it doesn't exist in the Localization Resources + if (Localization.ShowMissingKeys && !disableShowMissingKeys) + { + if (keyFound) + { + resourceValue = "[L]" + resourceValue; + } + else + { + resourceValue = "RESX:" + key; + } + } + + if (!keyFound) + { + Logger.WarnFormat("Missing localization key. key:{0} resFileRoot:{1} threadCulture:{2} userlan:{3}", key, resourceFileRoot, Thread.CurrentThread.CurrentUICulture, language); + } + + return resourceValue; + } + + #endregion + + private static object GetResourceFileCallBack(CacheItemArgs cacheItemArgs) + { + string cacheKey = cacheItemArgs.CacheKey; + Dictionary resources = null; + + string filePath = null; + try + { + //Get resource file lookup to determine if the resource file even exists + SharedDictionary resourceFileExistsLookup = GetResourceFileLookupDictionary(); + + if (ResourceFileMayExist(resourceFileExistsLookup, cacheKey)) + { + //check if an absolute reference for the resource file was used + if (cacheKey.Contains(":\\") && Path.IsPathRooted(cacheKey)) + { + //if an absolute reference, check that the file exists + if (File.Exists(cacheKey)) + { + filePath = cacheKey; + } + } + + //no filepath found from an absolute reference, try and map the path to get the file path + if (filePath == null) + { + filePath = HostingEnvironment.MapPath(Globals.ApplicationPath + cacheKey); + } + + //The file is not in the lookup, or we know it exists as we have found it before + if (File.Exists(filePath)) + { + if (filePath != null) + { + var doc = new XPathDocument(filePath); + resources = new Dictionary(); + foreach (XPathNavigator nav in doc.CreateNavigator().Select("root/data")) + { + if (nav.NodeType != XPathNodeType.Comment) + { + var selectSingleNode = nav.SelectSingleNode("value"); + if (selectSingleNode != null) + { + resources[nav.GetAttribute("name", String.Empty)] = selectSingleNode.Value; + } + } + } + } + cacheItemArgs.CacheDependency = new DNNCacheDependency(filePath); + + //File exists so add it to lookup with value true, so we are safe to try again + using (resourceFileExistsLookup.GetWriteLock()) + { + resourceFileExistsLookup[cacheKey] = true; + } + } + else + { + //File does not exist so add it to lookup with value false, so we don't try again + using (resourceFileExistsLookup.GetWriteLock()) + { + resourceFileExistsLookup[cacheKey] = false; + } + } + } + } + catch (Exception ex) + { + throw new Exception(string.Format("The following resource file caused an error while reading: {0}", filePath), ex); + } + return resources; + } + + private static SharedDictionary GetResourceFileLookupDictionary() + { + return + CBO.GetCachedObject>( + new CacheItemArgs(DataCache.ResourceFileLookupDictionaryCacheKey, DataCache.ResourceFileLookupDictionaryTimeOut, DataCache.ResourceFileLookupDictionaryCachePriority), + c => new SharedDictionary(), + true); + } + + private static Dictionary GetResourceFile(string resourceFile) + { + return CBO.GetCachedObject>(new CacheItemArgs(resourceFile, DataCache.ResourceFilesCacheTimeOut, DataCache.ResourceFilesCachePriority), + GetResourceFileCallBack, + true); + } + + private static string GetResourceFileName(string resourceFileRoot, string language) + { + string resourceFile; + language = language.ToLower(); + if (resourceFileRoot != null) + { + if (language == Localization.SystemLocale.ToLower() || String.IsNullOrEmpty(language)) + { + switch (resourceFileRoot.Substring(resourceFileRoot.Length - 5, 5).ToLower()) + { + case ".resx": + resourceFile = resourceFileRoot; + break; + case ".ascx": + resourceFile = resourceFileRoot + ".resx"; + break; + case ".aspx": + resourceFile = resourceFileRoot + ".resx"; + break; + default: + resourceFile = resourceFileRoot + ".ascx.resx"; //a portal module + break; + } + } + else + { + switch (resourceFileRoot.Substring(resourceFileRoot.Length - 5, 5).ToLower()) + { + case ".resx": + resourceFile = resourceFileRoot.Replace(".resx", "." + language + ".resx"); + break; + case ".ascx": + resourceFile = resourceFileRoot.Replace(".ascx", ".ascx." + language + ".resx"); + break; + case ".aspx": + resourceFile = resourceFileRoot.Replace(".aspx", ".aspx." + language + ".resx"); + break; + default: + resourceFile = resourceFileRoot + ".ascx." + language + ".resx"; + break; + } + } + } + else + { + if (language == Localization.SystemLocale.ToLower() || String.IsNullOrEmpty(language)) + { + resourceFile = Localization.SharedResourceFile; + } + else + { + resourceFile = Localization.SharedResourceFile.Replace(".resx", "." + language + ".resx"); + } + } + return resourceFile; + } + + private static bool ResourceFileMayExist(SharedDictionary resourceFileExistsLookup, string cacheKey) + { + bool mayExist; + using (resourceFileExistsLookup.GetReadLock()) + { + mayExist = !resourceFileExistsLookup.ContainsKey(cacheKey) || resourceFileExistsLookup[cacheKey]; + } + return mayExist; + } + + private static bool TryGetFromResourceFile(string key, string resourceFile, string userLanguage, string fallbackLanguage, string defaultLanguage, int portalID, ref string resourceValue) + { + //Try the user's language first + bool bFound = TryGetFromResourceFile(key, GetResourceFileName(resourceFile, userLanguage), portalID, ref resourceValue); + + if (!bFound && fallbackLanguage != userLanguage) + { + //Try fallback language next + bFound = TryGetFromResourceFile(key, GetResourceFileName(resourceFile, fallbackLanguage), portalID, ref resourceValue); + } + if (!bFound && !(defaultLanguage == userLanguage || defaultLanguage == fallbackLanguage)) + { + //Try default Language last + bFound = TryGetFromResourceFile(key, GetResourceFileName(resourceFile, defaultLanguage), portalID, ref resourceValue); + } + return bFound; + } + + private static bool TryGetFromResourceFile(string key, string resourceFile, int portalID, ref string resourceValue) + { + //Try Portal Resource File + bool bFound = TryGetFromResourceFile(key, resourceFile, portalID, CustomizedLocale.Portal, ref resourceValue); + if (!bFound) + { + //Try Host Resource File + bFound = TryGetFromResourceFile(key, resourceFile, portalID, CustomizedLocale.Host, ref resourceValue); + } + if (!bFound) + { + //Try Portal Resource File + bFound = TryGetFromResourceFile(key, resourceFile, portalID, CustomizedLocale.None, ref resourceValue); + } + return bFound; + } + + private static bool TryGetStringInternal(string key, string userLanguage, string resourceFile, PortalSettings portalSettings, ref string resourceValue) + { + string defaultLanguage = Null.NullString; + string fallbackLanguage = Localization.SystemLocale; + int portalId = Null.NullInteger; + + //Get the default language + if (portalSettings != null) + { + defaultLanguage = portalSettings.DefaultLanguage; + portalId = portalSettings.PortalId; + } + + //Set the userLanguage if not passed in + if (String.IsNullOrEmpty(userLanguage)) + { + userLanguage = Thread.CurrentThread.CurrentUICulture.ToString(); + } + + //Default the userLanguage to the defaultLanguage if not set + if (String.IsNullOrEmpty(userLanguage)) + { + userLanguage = defaultLanguage; + } + Locale userLocale = null; + try + { + if (Globals.Status != Globals.UpgradeStatus.Install) + { + //Get Fallback language, but not when we are installing (because we may not have a database yet) + userLocale = LocaleController.Instance.GetLocale(userLanguage); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + + if (userLocale != null && !String.IsNullOrEmpty(userLocale.Fallback)) + { + fallbackLanguage = userLocale.Fallback; + } + if (String.IsNullOrEmpty(resourceFile)) + { + resourceFile = Localization.SharedResourceFile; + } + + //Try the resource file for the key + bool bFound = TryGetFromResourceFile(key, resourceFile, userLanguage, fallbackLanguage, defaultLanguage, portalId, ref resourceValue); + if (!bFound) + { + if (Localization.SharedResourceFile.ToLowerInvariant() != resourceFile.ToLowerInvariant()) + { + //try to use a module specific shared resource file + string localSharedFile = resourceFile.Substring(0, resourceFile.LastIndexOf("/", StringComparison.Ordinal) + 1) + Localization.LocalSharedResourceFile; + + if (localSharedFile.ToLowerInvariant() != resourceFile.ToLowerInvariant()) + { + bFound = TryGetFromResourceFile(key, localSharedFile, userLanguage, fallbackLanguage, defaultLanguage, portalId, ref resourceValue); + } + } + } + if (!bFound) + { + if (Localization.SharedResourceFile.ToLowerInvariant() != resourceFile.ToLowerInvariant()) + { + bFound = TryGetFromResourceFile(key, Localization.SharedResourceFile, userLanguage, fallbackLanguage, defaultLanguage, portalId, ref resourceValue); + } + } + return bFound; + } + + private static bool TryGetFromResourceFile(string key, string resourceFile, int portalID, CustomizedLocale resourceType, ref string resourceValue) + { + bool bFound = Null.NullBoolean; + string resourceFileName = resourceFile; + switch (resourceType) + { + case CustomizedLocale.Host: + resourceFileName = resourceFile.Replace(".resx", ".Host.resx"); + break; + case CustomizedLocale.Portal: + resourceFileName = resourceFile.Replace(".resx", ".Portal-" + portalID + ".resx"); + break; + } + + if (resourceFileName.StartsWith("desktopmodules", StringComparison.InvariantCultureIgnoreCase) + || resourceFileName.StartsWith("admin", StringComparison.InvariantCultureIgnoreCase) + || resourceFileName.StartsWith("controls", StringComparison.InvariantCultureIgnoreCase)) + { + resourceFileName = "~/" + resourceFileName; + } + + //Local resource files are either named ~/... or /... + //The following logic creates a cachekey of /.... + string cacheKey = resourceFileName.Replace("~/", "/").ToLowerInvariant(); + if (!String.IsNullOrEmpty(Globals.ApplicationPath)) + { + if (Globals.ApplicationPath != "/portals") + { + if (cacheKey.StartsWith(Globals.ApplicationPath)) + { + cacheKey = cacheKey.Substring(Globals.ApplicationPath.Length); + } + } + else + { + cacheKey = "~" + cacheKey; + if (cacheKey.StartsWith("~" + Globals.ApplicationPath)) + { + cacheKey = cacheKey.Substring(Globals.ApplicationPath.Length + 1); + } + } + } + + //Get resource file lookup to determine if the resource file even exists + SharedDictionary resourceFileExistsLookup = GetResourceFileLookupDictionary(); + + if (ResourceFileMayExist(resourceFileExistsLookup, cacheKey)) + { + //File is not in lookup or its value is true so we know it exists + Dictionary dicResources = GetResourceFile(cacheKey); + if (dicResources != null) + { + bFound = dicResources.TryGetValue(key, out resourceValue); + } + } + + return bFound; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/DBLoggingProvider.cs b/DNN Platform/Library/Services/Log/EventLog/DBLoggingProvider.cs new file mode 100644 index 00000000000..42f5d64dfe3 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/DBLoggingProvider.cs @@ -0,0 +1,594 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Xml; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Scheduling; + +#endregion + + +namespace DotNetNuke.Services.Log.EventLog +{ + public class DBLoggingProvider : LoggingProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (DBLoggingProvider)); + private const int ReaderLockTimeout = 10000; + private const int WriterLockTimeout = 10000; + private static readonly IList LogQueue = new List(); + private static readonly ReaderWriterLock LockNotif = new ReaderWriterLock(); + private static readonly ReaderWriterLock LockQueueLog = new ReaderWriterLock(); + + private static Hashtable FillLogTypeConfigInfoByKey(ArrayList arr) + { + var ht = new Hashtable(); + int i; + for (i = 0; i <= arr.Count - 1; i++) + { + var logTypeConfigInfo = (LogTypeConfigInfo) arr[i]; + if (String.IsNullOrEmpty(logTypeConfigInfo.LogTypeKey)) + { + logTypeConfigInfo.LogTypeKey = "*"; + } + if (String.IsNullOrEmpty(logTypeConfigInfo.LogTypePortalID)) + { + logTypeConfigInfo.LogTypePortalID = "*"; + } + ht.Add(logTypeConfigInfo.LogTypeKey + "|" + logTypeConfigInfo.LogTypePortalID, logTypeConfigInfo); + } + DataCache.SetCache("GetLogTypeConfigInfoByKey", ht); + return ht; + } + + private LogTypeConfigInfo GetLogTypeConfigInfoByKey(string logTypeKey, string logTypePortalID) + { + var configInfoByKey = (Hashtable) DataCache.GetCache("GetLogTypeConfigInfoByKey") ?? FillLogTypeConfigInfoByKey(GetLogTypeConfigInfo()); + var logTypeConfigInfo = (LogTypeConfigInfo) configInfoByKey[logTypeKey + "|" + logTypePortalID]; + if (logTypeConfigInfo == null) + { + logTypeConfigInfo = (LogTypeConfigInfo) configInfoByKey["*|" + logTypePortalID]; + if (logTypeConfigInfo == null) + { + logTypeConfigInfo = (LogTypeConfigInfo) configInfoByKey[logTypeKey + "|*"]; + if (logTypeConfigInfo == null) + { + logTypeConfigInfo = (LogTypeConfigInfo) configInfoByKey["*|*"]; + } + else + { + return logTypeConfigInfo; + } + } + else + { + return logTypeConfigInfo; + } + } + else + { + return logTypeConfigInfo; + } + return logTypeConfigInfo; + } + + private static LogInfo FillLogInfo(IDataReader dr) + { + var obj = new LogInfo(); + try + { + obj.LogCreateDate = Convert.ToDateTime(dr["LogCreateDate"]); + obj.LogGUID = Convert.ToString(dr["LogGUID"]); + if (dr["LogPortalID"] != DBNull.Value) + { + obj.LogPortalID = Convert.ToInt32(dr["LogPortalID"]); + } + if (dr["LogPortalName"] != DBNull.Value) + { + obj.LogPortalName = Convert.ToString(dr["LogPortalName"]); + } + if (dr["LogServerName"] != DBNull.Value) + { + obj.LogServerName = Convert.ToString(dr["LogServerName"]); + } + if (dr["LogUserID"] != DBNull.Value) + { + obj.LogUserID = Convert.ToInt32(dr["LogUserID"]); + } + obj.LogTypeKey = Convert.ToString(dr["LogTypeKey"]); + obj.LogUserName = Convert.ToString(dr["LogUserName"]); + obj.LogConfigID = Convert.ToString(dr["LogConfigID"]); + obj.LogProperties.Deserialize(Convert.ToString(dr["LogProperties"])); + } + catch (Exception exc) + { + Logger.Error(exc); + } + return obj; + } + + private static void FillLogs(IDataReader dr, IList logs, ref int totalRecords) + { + try + { + while (dr.Read()) + { + LogInfo logInfo = FillLogInfo(dr); + logs.Add(logInfo); + } + dr.NextResult(); + while (dr.Read()) + { + totalRecords = Convert.ToInt32(dr["TotalRecords"]); + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + + private static void WriteError(LogTypeConfigInfo logTypeConfigInfo, Exception exc, string header, string message) + { + if (HttpContext.Current != null) + { + if (HttpContext.Current.IsCustomErrorEnabled) + { + HttpContext.Current.AddError(exc); + } + else + { + HttpResponse response = HttpContext.Current.Response; + response.StatusCode = 500; + HtmlUtils.WriteHeader(response, header); + + if (logTypeConfigInfo != null) + { + HtmlUtils.WriteError(response, logTypeConfigInfo.LogFileNameWithPath, message); + } + HtmlUtils.WriteFooter(response); + response.End(); + } + } + + } + + private static void WriteLog(LogQueueItem logQueueItem) + { + LogTypeConfigInfo logTypeConfigInfo = null; + try + { + logTypeConfigInfo = logQueueItem.LogTypeConfigInfo; + if (logTypeConfigInfo != null) + { + LogInfo objLogInfo = logQueueItem.LogInfo; + string logProperties = objLogInfo.LogProperties.Serialize(); + DataProvider.Instance().AddLog(objLogInfo.LogGUID, + objLogInfo.LogTypeKey, + objLogInfo.LogUserID, + objLogInfo.LogUserName, + objLogInfo.LogPortalID, + objLogInfo.LogPortalName, + objLogInfo.LogCreateDate, + objLogInfo.LogServerName, + logProperties, + Convert.ToInt32(objLogInfo.LogConfigID)); + if (logTypeConfigInfo.EmailNotificationIsActive) + { + LockNotif.AcquireWriterLock(ReaderLockTimeout); + try + { + if (logTypeConfigInfo.NotificationThreshold == 0) + { + string str = logQueueItem.LogInfo.Serialize(); + + Mail.Mail.SendEmail(logTypeConfigInfo.MailFromAddress, logTypeConfigInfo.MailToAddress, "Event Notification", str); + } + } + finally + { + LockNotif.ReleaseWriterLock(); + } + } + } + } + catch (SqlException exc) + { + Logger.Error(exc); + WriteError(logTypeConfigInfo, exc, "SQL Exception", SqlUtils.TranslateSQLException(exc)); + } + catch (Exception exc) + { + Logger.Error(exc); + WriteError(logTypeConfigInfo, exc, "Unhandled Error", exc.Message); + } + } + + public override void AddLog(LogInfo logInfo) + { + string configPortalID = logInfo.LogPortalID != Null.NullInteger + ? logInfo.LogPortalID.ToString() + : "*"; + var logTypeConfigInfo = GetLogTypeConfigInfoByKey(logInfo.LogTypeKey, configPortalID); + if (logTypeConfigInfo == null || logTypeConfigInfo.LoggingIsActive == false) + { + return; + } + logInfo.LogConfigID = logTypeConfigInfo.ID; + var logQueueItem = new LogQueueItem {LogInfo = logInfo, LogTypeConfigInfo = logTypeConfigInfo}; + SchedulingProvider scheduler = SchedulingProvider.Instance(); + if (scheduler == null || logInfo.BypassBuffering || SchedulingProvider.Enabled == false + || scheduler.GetScheduleStatus() == ScheduleStatus.STOPPED || !Host.EventLogBuffer) + { + WriteLog(logQueueItem); + } + else + { + LogQueue.Add(logQueueItem); + } + } + + public override void AddLogType(string logTypeKey, string logTypeFriendlyName, string logTypeDescription, string logTypeCSSClass, string logTypeOwner) + { + DataProvider.Instance().AddLogType(logTypeKey, logTypeFriendlyName, logTypeDescription, logTypeCSSClass, logTypeOwner); + } + + public override void AddLogTypeConfigInfo(string id, bool loggingIsActive, string logTypeKey, string logTypePortalID, string keepMostRecent, string logFileName, bool emailNotificationIsActive, + string threshold, string thresholdTime, string thresholdTimeType, string mailFromAddress, string mailToAddress) + { + int intThreshold = -1; + int intThresholdTime = -1; + int intThresholdTimeType = -1; + int intKeepMostRecent = -1; + if (Regex.IsMatch(threshold, "^\\d+$")) + { + intThreshold = Convert.ToInt32(threshold); + } + if (Regex.IsMatch(thresholdTime, "^\\d+$")) + { + intThresholdTime = Convert.ToInt32(thresholdTime); + } + if (Regex.IsMatch(thresholdTimeType, "^\\d+$")) + { + intThresholdTimeType = Convert.ToInt32(thresholdTimeType); + } + if (Regex.IsMatch(keepMostRecent, "^\\d+$")) + { + intKeepMostRecent = Convert.ToInt32(keepMostRecent); + } + DataProvider.Instance().AddLogTypeConfigInfo(loggingIsActive, + logTypeKey, + logTypePortalID, + intKeepMostRecent, + emailNotificationIsActive, + intThreshold, + intThresholdTime, + intThresholdTimeType, + mailFromAddress, + mailToAddress); + DataCache.RemoveCache("GetLogTypeConfigInfo"); + DataCache.RemoveCache("GetLogTypeConfigInfoByKey"); + } + + public override void ClearLog() + { + DataProvider.Instance().ClearLog(); + } + + public override void DeleteLog(LogInfo logInfo) + { + DataProvider.Instance().DeleteLog(logInfo.LogGUID); + } + + public override void DeleteLogType(string logTypeKey) + { + DataProvider.Instance().DeleteLogType(logTypeKey); + } + + public override void DeleteLogTypeConfigInfo(string id) + { + DataProvider.Instance().DeleteLogTypeConfigInfo(id); + DataCache.RemoveCache("GetLogTypeConfigInfo"); + DataCache.RemoveCache("GetLogTypeConfigInfoByKey"); + } + + public override List GetLogs(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords) + { + var logs = new List(); + FillLogs(DataProvider.Instance().GetLogs(portalID, logType, pageSize, pageIndex), logs, ref totalRecords); + return logs; + } + + public override ArrayList GetLogTypeConfigInfo() + { + var list = (ArrayList) DataCache.GetCache("GetLogTypeConfigInfo"); + if (list == null) + { + IDataReader dr = null; + try + { + dr = DataProvider.Instance().GetLogTypeConfigInfo(); + list = CBO.FillCollection(dr, typeof (LogTypeConfigInfo)); + DataCache.SetCache("GetLogTypeConfigInfo", list); + FillLogTypeConfigInfoByKey(list); + } + finally + { + if (dr == null) + { + list = new ArrayList(); + } + else + { + CBO.CloseDataReader(dr, true); + } + } + } + return list; + } + + public override LogTypeConfigInfo GetLogTypeConfigInfoByID(string id) + { + return (LogTypeConfigInfo) CBO.FillObject(DataProvider.Instance().GetLogTypeConfigInfoByID(Convert.ToInt32(id)), typeof (LogTypeConfigInfo)); + } + + public override ArrayList GetLogTypeInfo() + { + return CBO.FillCollection(DataProvider.Instance().GetLogTypeInfo(), typeof (LogTypeInfo)); + } + + public override object GetSingleLog(LogInfo logInfo, ReturnType returnType) + { + IDataReader dr = DataProvider.Instance().GetSingleLog(logInfo.LogGUID); + LogInfo log = null; + try + { + if (dr != null) + { + dr.Read(); + log = FillLogInfo(dr); + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + if (returnType == ReturnType.LogInfoObjects) + { + return log; + } + var xmlDoc = new XmlDocument(); + if (log != null) + { + xmlDoc.LoadXml(log.Serialize()); + } + return xmlDoc.DocumentElement; + } + + public override bool LoggingIsEnabled(string logType, int portalID) + { + string configPortalID = portalID.ToString(); + if (portalID == -1) + { + configPortalID = "*"; + } + LogTypeConfigInfo configInfo = GetLogTypeConfigInfoByKey(logType, configPortalID); + if (configInfo == null) + { + return false; + } + return configInfo.LoggingIsActive; + } + + public override void PurgeLogBuffer() + { + LockQueueLog.AcquireWriterLock(WriterLockTimeout); + try + { + for (int i = LogQueue.Count - 1; i >= 0; i += -1) + { + LogQueueItem logQueueItem = LogQueue[i]; + //in case the log was removed + //by another thread simultaneously + if (logQueueItem != null) + { + WriteLog(logQueueItem); + LogQueue.Remove(logQueueItem); + } + } + } + finally + { + LockQueueLog.ReleaseWriterLock(); + } + DataProvider.Instance().PurgeLog(); + } + + public override void SendLogNotifications() + { + List configInfos = CBO.FillCollection(DataProvider.Instance().GetEventLogPendingNotifConfig()); + foreach (LogTypeConfigInfo typeConfigInfo in configInfos) + { + IDataReader dr = DataProvider.Instance().GetEventLogPendingNotif(Convert.ToInt32(typeConfigInfo.ID)); + string log = ""; + try + { + while (dr.Read()) + { + LogInfo logInfo = FillLogInfo(dr); + log += logInfo.Serialize() + Environment.NewLine + Environment.NewLine; + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + Mail.Mail.SendEmail(typeConfigInfo.MailFromAddress, typeConfigInfo.MailToAddress, "Event Notification", log); + DataProvider.Instance().UpdateEventLogPendingNotif(Convert.ToInt32(typeConfigInfo.ID)); + } + } + + public override bool SupportsEmailNotification() + { + return true; + } + + public override bool SupportsInternalViewer() + { + return true; + } + + public override bool SupportsSendToCoreTeam() + { + return false; + } + + public override bool SupportsSendViaEmail() + { + return true; + } + + public override void UpdateLogType(string logTypeKey, string logTypeFriendlyName, string logTypeDescription, string logTypeCSSClass, string logTypeOwner) + { + DataProvider.Instance().UpdateLogType(logTypeKey, logTypeFriendlyName, logTypeDescription, logTypeCSSClass, logTypeOwner); + } + + public override void UpdateLogTypeConfigInfo(string id, bool loggingIsActive, string logTypeKey, string logTypePortalID, string keepMostRecent, string logFileName, bool emailNotificationIsActive, string threshold, string thresholdTime, string thresholdTimeType, string mailFromAddress, string mailToAddress) + { + int intThreshold = -1; + int intThresholdTime = -1; + int intThresholdTimeType = -1; + int intKeepMostRecent = -1; + if (Regex.IsMatch(threshold, "^\\d+$")) + { + intThreshold = Convert.ToInt32(threshold); + } + if (Regex.IsMatch(thresholdTime, "^\\d+$")) + { + intThresholdTime = Convert.ToInt32(thresholdTime); + } + if (Regex.IsMatch(thresholdTimeType, "^\\d+$")) + { + intThresholdTimeType = Convert.ToInt32(thresholdTimeType); + } + if (Regex.IsMatch(keepMostRecent, "^\\d+$")) + { + intKeepMostRecent = Convert.ToInt32(keepMostRecent); + } + DataProvider.Instance().UpdateLogTypeConfigInfo(id, + loggingIsActive, + logTypeKey, + logTypePortalID, + intKeepMostRecent, + emailNotificationIsActive, + intThreshold, + intThresholdTime, + intThresholdTimeType, + mailFromAddress, + mailToAddress); + DataCache.RemoveCache("GetLogTypeConfigInfo"); + DataCache.RemoveCache("GetLogTypeConfigInfoByKey"); + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog() + { + var logs = new LogInfoArray(); + int totalRecords = 0; + FillLogs(DataProvider.Instance().GetLogs(Null.NullInteger, Null.NullString, 10, 0), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(string logType) + { + var logs = new LogInfoArray(); + int totalRecords = 0; + FillLogs(DataProvider.Instance().GetLogs(Null.NullInteger, logType, 10, 0), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(int portalID) + { + var logs = new LogInfoArray(); + int totalRecords = 0; + FillLogs(DataProvider.Instance().GetLogs(portalID, Null.NullString, 10, 0), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(int portalID, string logType) + { + var logs = new LogInfoArray(); + int totalRecords = 0; + FillLogs(DataProvider.Instance().GetLogs(portalID, logType, 10, 0), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(int pageSize, int pageIndex, ref int totalRecords) + { + var logs = new LogInfoArray(); + FillLogs(DataProvider.Instance().GetLogs(Null.NullInteger, Null.NullString, pageSize, pageIndex), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(string logType, int pageSize, int pageIndex, ref int totalRecords) + { + var logs = new LogInfoArray(); + FillLogs(DataProvider.Instance().GetLogs(Null.NullInteger, logType, pageSize, pageIndex), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(int portalID, int pageSize, int pageIndex, ref int totalRecords) + { + var logs = new LogInfoArray(); + FillLogs(DataProvider.Instance().GetLogs(portalID, Null.NullString, pageSize, pageIndex), logs, ref totalRecords); + return logs; + } + + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public override LogInfoArray GetLog(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords) + { + var logs = new LogInfoArray(); + FillLogs(DataProvider.Instance().GetLogs(portalID, logType, pageSize, pageIndex), logs, ref totalRecords); + return logs; + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/EventLogController.cs b/DNN Platform/Library/Services/Log/EventLog/EventLogController.cs new file mode 100644 index 00000000000..36248611260 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/EventLogController.cs @@ -0,0 +1,345 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System.Globalization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class EventLogController : LogController, IEventLogController + { + #region EventLogType enum + + public enum EventLogType + { + USER_CREATED, + USER_DELETED, + LOGIN_SUPERUSER, + LOGIN_SUCCESS, + LOGIN_FAILURE, + LOGIN_USERLOCKEDOUT, + LOGIN_USERNOTAPPROVED, + CACHE_REFRESHED, + PASSWORD_SENT_SUCCESS, + PASSWORD_SENT_FAILURE, + LOG_NOTIFICATION_FAILURE, + PORTAL_CREATED, + PORTAL_DELETED, + TAB_CREATED, + TAB_UPDATED, + TAB_DELETED, + TAB_SENT_TO_RECYCLE_BIN, + TAB_RESTORED, + USER_ROLE_CREATED, + USER_ROLE_DELETED, + USER_ROLE_UPDATED, + ROLE_CREATED, + ROLE_UPDATED, + ROLE_DELETED, + MODULE_CREATED, + MODULE_UPDATED, + MODULE_DELETED, + MODULE_SENT_TO_RECYCLE_BIN, + MODULE_RESTORED, + SCHEDULER_EVENT_STARTED, + SCHEDULER_EVENT_PROGRESSING, + SCHEDULER_EVENT_COMPLETED, + APPLICATION_START, + APPLICATION_END, + APPLICATION_SHUTTING_DOWN, + SCHEDULER_STARTED, + SCHEDULER_SHUTTING_DOWN, + SCHEDULER_STOPPED, + ADMIN_ALERT, + HOST_ALERT, + CACHE_REMOVED, + CACHE_EXPIRED, + CACHE_UNDERUSED, + CACHE_DEPENDENCYCHANGED, + CACHE_OVERFLOW, + CACHE_REFRESH, + LISTENTRY_CREATED, + LISTENTRY_UPDATED, + LISTENTRY_DELETED, + DESKTOPMODULE_CREATED, + DESKTOPMODULE_UPDATED, + DESKTOPMODULE_DELETED, + SKINCONTROL_CREATED, + SKINCONTROL_UPDATED, + SKINCONTROL_DELETED, + PORTALALIAS_CREATED, + PORTALALIAS_UPDATED, + PORTALALIAS_DELETED, + PROFILEPROPERTY_CREATED, + PROFILEPROPERTY_UPDATED, + PROFILEPROPERTY_DELETED, + USER_UPDATED, + DESKTOPMODULEPERMISSION_CREATED, + DESKTOPMODULEPERMISSION_UPDATED, + DESKTOPMODULEPERMISSION_DELETED, + PERMISSION_CREATED, + PERMISSION_UPDATED, + PERMISSION_DELETED, + TABPERMISSION_CREATED, + TABPERMISSION_UPDATED, + TABPERMISSION_DELETED, + AUTHENTICATION_CREATED, + AUTHENTICATION_UPDATED, + AUTHENTICATION_DELETED, + FOLDER_CREATED, + FOLDER_UPDATED, + FOLDER_DELETED, + PACKAGE_CREATED, + PACKAGE_UPDATED, + PACKAGE_DELETED, + LANGUAGEPACK_CREATED, + LANGUAGEPACK_UPDATED, + LANGUAGEPACK_DELETED, + LANGUAGE_CREATED, + LANGUAGE_UPDATED, + LANGUAGE_DELETED, + SKINPACKAGE_CREATED, + SKINPACKAGE_UPDATED, + SKINPACKAGE_DELETED, + SCHEDULE_CREATED, + SCHEDULE_UPDATED, + SCHEDULE_DELETED, + HOST_SETTING_CREATED, + HOST_SETTING_UPDATED, + HOST_SETTING_DELETED, + PORTALDESKTOPMODULE_CREATED, + PORTALDESKTOPMODULE_UPDATED, + PORTALDESKTOPMODULE_DELETED, + TABMODULE_CREATED, + TABMODULE_UPDATED, + TABMODULE_DELETED, + TABMODULE_SETTING_CREATED, + TABMODULE_SETTING_UPDATED, + TABMODULE_SETTING_DELETED, + MODULE_SETTING_CREATED, + MODULE_SETTING_UPDATED, + MODULE_SETTING_DELETED, + PORTAL_SETTING_CREATED, + PORTAL_SETTING_UPDATED, + PORTAL_SETTING_DELETED, + PORTALINFO_CREATED, + PORTALINFO_UPDATED, + PORTALINFO_DELETED, + AUTHENTICATION_USER_CREATED, + AUTHENTICATION_USER_UPDATED, + AUTHENTICATION_USER_DELETED, + LANGUAGETOPORTAL_CREATED, + LANGUAGETOPORTAL_UPDATED, + LANGUAGETOPORTAL_DELETED, + TAB_ORDER_UPDATED, + TAB_SETTING_CREATED, + TAB_SETTING_UPDATED, + TAB_SETTING_DELETED, + HOST_SQL_EXECUTED, + USER_RESTORED, + USER_REMOVED, + USER_IMPERSONATED, + USERNAME_UPDATED, + IP_LOGIN_BANNED, + PAGE_NOT_FOUND_404, + TABURL_CREATED, + TABURL_UPDATED, + TABURL_DELETED + } + + #endregion + + #region IEventLogController Members + + public void AddLog(string propertyName, string propertyValue, EventLogType logType) + { + AddLog(propertyName, propertyValue, PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, logType); + } + + public void AddLog(string propertyName, string propertyValue, PortalSettings portalSettings, int userID, + EventLogType logType) + { + AddLog(propertyName, propertyValue, portalSettings, userID, logType.ToString()); + } + + public void AddLog(string propertyName, string propertyValue, PortalSettings portalSettings, int userID, + string logType) + { + var properties = new LogProperties(); + var logDetailInfo = new LogDetailInfo {PropertyName = propertyName, PropertyValue = propertyValue}; + properties.Add(logDetailInfo); + AddLog(properties, portalSettings, userID, logType, false); + } + + public void AddLog(LogProperties properties, PortalSettings portalSettings, int userID, string logTypeKey, + bool bypassBuffering) + { + //supports adding a custom string for LogType + var logInfo = new LogInfo + { + LogUserID = userID, + LogTypeKey = logTypeKey, + LogProperties = properties, + BypassBuffering = bypassBuffering + }; + if (portalSettings != null) + { + logInfo.LogPortalID = portalSettings.PortalId; + logInfo.LogPortalName = portalSettings.PortalName; + } + AddLog(logInfo); + } + + public void AddLog(PortalSettings portalSettings, int userID, EventLogType logType) + { + AddLog(new LogProperties(), portalSettings, userID, logType.ToString(), false); + } + + public void AddLog(object businessObject, PortalSettings portalSettings, int userID, string userName, + EventLogType logType) + { + AddLog(businessObject, portalSettings, userID, userName, logType.ToString()); + } + + public void AddLog(object businessObject, PortalSettings portalSettings, int userID, string userName, + string logType) + { + var logInfo = new LogInfo {LogUserID = userID, LogTypeKey = logType}; + if (portalSettings != null) + { + logInfo.LogPortalID = portalSettings.PortalId; + logInfo.LogPortalName = portalSettings.PortalName; + } + switch (businessObject.GetType().FullName) + { + case "DotNetNuke.Entities.Portals.PortalInfo": + var portal = (PortalInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("PortalID", + portal.PortalID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("PortalName", portal.PortalName)); + logInfo.LogProperties.Add(new LogDetailInfo("Description", portal.Description)); + logInfo.LogProperties.Add(new LogDetailInfo("KeyWords", portal.KeyWords)); + logInfo.LogProperties.Add(new LogDetailInfo("LogoFile", portal.LogoFile)); + break; + case "DotNetNuke.Entities.Tabs.TabInfo": + var tab = (TabInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("TabID", + tab.TabID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("PortalID", + tab.PortalID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("TabName", tab.TabName)); + logInfo.LogProperties.Add(new LogDetailInfo("Title", tab.Title)); + logInfo.LogProperties.Add(new LogDetailInfo("Description", tab.Description)); + logInfo.LogProperties.Add(new LogDetailInfo("KeyWords", tab.KeyWords)); + logInfo.LogProperties.Add(new LogDetailInfo("Url", tab.Url)); + logInfo.LogProperties.Add(new LogDetailInfo("ParentId", + tab.ParentId.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("IconFile", tab.IconFile)); + logInfo.LogProperties.Add(new LogDetailInfo("IsVisible", + tab.IsVisible.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("SkinSrc", tab.SkinSrc)); + logInfo.LogProperties.Add(new LogDetailInfo("ContainerSrc", tab.ContainerSrc)); + break; + case "DotNetNuke.Entities.Modules.ModuleInfo": + var module = (ModuleInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("ModuleId", + module.ModuleID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("ModuleTitle", module.ModuleTitle)); + logInfo.LogProperties.Add(new LogDetailInfo("TabModuleID", + module.TabModuleID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("TabID", + module.TabID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("PortalID", + module.PortalID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("ModuleDefId", + module.ModuleDefID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("FriendlyName", module.DesktopModule.FriendlyName)); + logInfo.LogProperties.Add(new LogDetailInfo("IconFile", module.IconFile)); + logInfo.LogProperties.Add(new LogDetailInfo("Visibility", module.Visibility.ToString())); + logInfo.LogProperties.Add(new LogDetailInfo("ContainerSrc", module.ContainerSrc)); + break; + case "DotNetNuke.Entities.Users.UserInfo": + var user = (UserInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("UserID", + user.UserID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("FirstName", user.Profile.FirstName)); + logInfo.LogProperties.Add(new LogDetailInfo("LastName", user.Profile.LastName)); + logInfo.LogProperties.Add(new LogDetailInfo("UserName", user.Username)); + logInfo.LogProperties.Add(new LogDetailInfo("Email", user.Email)); + break; + case "DotNetNuke.Security.Roles.RoleInfo": + var role = (RoleInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("RoleID", + role.RoleID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("RoleName", role.RoleName)); + logInfo.LogProperties.Add(new LogDetailInfo("PortalID", + role.PortalID.ToString(CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("Description", role.Description)); + logInfo.LogProperties.Add(new LogDetailInfo("IsPublic", + role.IsPublic.ToString(CultureInfo.InvariantCulture))); + break; + case "DotNetNuke.Entities.Modules.DesktopModuleInfo": + var desktopModule = (DesktopModuleInfo) businessObject; + logInfo.LogProperties.Add(new LogDetailInfo("DesktopModuleID", + desktopModule.DesktopModuleID.ToString( + CultureInfo.InvariantCulture))); + logInfo.LogProperties.Add(new LogDetailInfo("ModuleName", desktopModule.ModuleName)); + logInfo.LogProperties.Add(new LogDetailInfo("FriendlyName", desktopModule.FriendlyName)); + logInfo.LogProperties.Add(new LogDetailInfo("FolderName", desktopModule.FolderName)); + logInfo.LogProperties.Add(new LogDetailInfo("Description", desktopModule.Description)); + break; + default: //Serialise using XmlSerializer + logInfo.LogProperties.Add(new LogDetailInfo("logdetail", XmlUtils.Serialize(businessObject))); + break; + } + base.AddLog(logInfo); + } + + #endregion + + #region Helper Methods + + public static void AddSettingLog(EventLogType logTypeKey, string idFieldName, int idValue, string settingName, + string settingValue, int userId) + { + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo() { LogUserID = userId, LogTypeKey = logTypeKey.ToString() }; + eventLogInfo.LogProperties.Add(new LogDetailInfo(idFieldName, idValue.ToString())); + eventLogInfo.LogProperties.Add(new LogDetailInfo("SettingName", settingName)); + eventLogInfo.LogProperties.Add(new LogDetailInfo("SettingValue", settingValue)); + + eventLogController.AddLog(eventLogInfo); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/ExceptionLogController.cs b/DNN Platform/Library/Services/Log/EventLog/ExceptionLogController.cs new file mode 100644 index 00000000000..9d37a288fb4 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/ExceptionLogController.cs @@ -0,0 +1,140 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Exceptions; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class ExceptionLogController : LogController + { + #region ExceptionLogType enum + + public enum ExceptionLogType + { + GENERAL_EXCEPTION, + MODULE_LOAD_EXCEPTION, + PAGE_LOAD_EXCEPTION, + SCHEDULER_EXCEPTION, + SECURITY_EXCEPTION, + SEARCH_INDEXER_EXCEPTION, + DATA_EXCEPTION + } + + #endregion + + public void AddLog(Exception objException) + { + AddLog(objException, ExceptionLogType.GENERAL_EXCEPTION); + } + + public void AddLog(BasePortalException objBasePortalException) + { + if (objBasePortalException.GetType().Name == "ModuleLoadException") + { + AddLog(objBasePortalException, ExceptionLogType.MODULE_LOAD_EXCEPTION); + } + else if (objBasePortalException.GetType().Name == "PageLoadException") + { + AddLog(objBasePortalException, ExceptionLogType.PAGE_LOAD_EXCEPTION); + } + else if (objBasePortalException.GetType().Name == "SchedulerException") + { + AddLog(objBasePortalException, ExceptionLogType.SCHEDULER_EXCEPTION); + } + else if (objBasePortalException.GetType().Name == "SecurityException") + { + AddLog(objBasePortalException, ExceptionLogType.SECURITY_EXCEPTION); + } + else if (objBasePortalException.GetType().Name == "SearchException") + { + AddLog(objBasePortalException, ExceptionLogType.SEARCH_INDEXER_EXCEPTION); + } + else + { + AddLog(objBasePortalException, ExceptionLogType.GENERAL_EXCEPTION); + } + } + + public void AddLog(Exception objException, ExceptionLogType LogType) + { + var objLogController = new LogController(); + var objLogInfo = new LogInfo(); + objLogInfo.LogTypeKey = LogType.ToString(); + if (LogType == ExceptionLogType.SEARCH_INDEXER_EXCEPTION) + { + //Add SearchException Properties + var objSearchException = (SearchException) objException; + objLogInfo.LogProperties.Add(new LogDetailInfo("ModuleId", objSearchException.SearchItem.ModuleId.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("SearchItemId", objSearchException.SearchItem.SearchItemId.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("Title", objSearchException.SearchItem.Title)); + objLogInfo.LogProperties.Add(new LogDetailInfo("SearchKey", objSearchException.SearchItem.SearchKey)); + objLogInfo.LogProperties.Add(new LogDetailInfo("GUID", objSearchException.SearchItem.GUID)); + } + else if (LogType == ExceptionLogType.MODULE_LOAD_EXCEPTION) + { + //Add ModuleLoadException Properties + var objModuleLoadException = (ModuleLoadException) objException; + objLogInfo.LogProperties.Add(new LogDetailInfo("ModuleId", objModuleLoadException.ModuleId.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("ModuleDefId", objModuleLoadException.ModuleDefId.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("FriendlyName", objModuleLoadException.FriendlyName)); + objLogInfo.LogProperties.Add(new LogDetailInfo("ModuleControlSource", objModuleLoadException.ModuleControlSource)); + } + else if (LogType == ExceptionLogType.SECURITY_EXCEPTION) + { + //Add SecurityException Properties + var objSecurityException = (SecurityException) objException; + objLogInfo.LogProperties.Add(new LogDetailInfo("Querystring", objSecurityException.Querystring)); + objLogInfo.LogProperties.Add(new LogDetailInfo("IP", objSecurityException.IP)); + } + + //Add BasePortalException Properties + var objBasePortalException = new BasePortalException(objException.ToString(), objException); + objLogInfo.LogProperties.Add(new LogDetailInfo("AssemblyVersion", objBasePortalException.AssemblyVersion)); + objLogInfo.LogProperties.Add(new LogDetailInfo("PortalID", objBasePortalException.PortalID.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("PortalName", objBasePortalException.PortalName)); + objLogInfo.LogProperties.Add(new LogDetailInfo("UserID", objBasePortalException.UserID.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("UserName", objBasePortalException.UserName)); + objLogInfo.LogProperties.Add(new LogDetailInfo("ActiveTabID", objBasePortalException.ActiveTabID.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("ActiveTabName", objBasePortalException.ActiveTabName)); + objLogInfo.LogProperties.Add(new LogDetailInfo("RawURL", objBasePortalException.RawURL)); + objLogInfo.LogProperties.Add(new LogDetailInfo("AbsoluteURL", objBasePortalException.AbsoluteURL)); + objLogInfo.LogProperties.Add(new LogDetailInfo("AbsoluteURLReferrer", objBasePortalException.AbsoluteURLReferrer)); + objLogInfo.LogProperties.Add(new LogDetailInfo("UserAgent", objBasePortalException.UserAgent)); + objLogInfo.LogProperties.Add(new LogDetailInfo("DefaultDataProvider", objBasePortalException.DefaultDataProvider)); + objLogInfo.LogProperties.Add(new LogDetailInfo("ExceptionGUID", objBasePortalException.ExceptionGUID)); + objLogInfo.LogProperties.Add(new LogDetailInfo("InnerException", objBasePortalException.InnerException.Message)); + objLogInfo.LogProperties.Add(new LogDetailInfo("FileName", objBasePortalException.FileName)); + objLogInfo.LogProperties.Add(new LogDetailInfo("FileLineNumber", objBasePortalException.FileLineNumber.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("FileColumnNumber", objBasePortalException.FileColumnNumber.ToString())); + objLogInfo.LogProperties.Add(new LogDetailInfo("Method", objBasePortalException.Method)); + objLogInfo.LogProperties.Add(new LogDetailInfo("StackTrace", objBasePortalException.StackTrace)); + objLogInfo.LogProperties.Add(new LogDetailInfo("Message", objBasePortalException.Message)); + objLogInfo.LogProperties.Add(new LogDetailInfo("Source", objBasePortalException.Source)); + objLogInfo.LogPortalID = objBasePortalException.PortalID; + objLogController.AddLog(objLogInfo); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/IEventLogController.cs b/DNN Platform/Library/Services/Log/EventLog/IEventLogController.cs new file mode 100644 index 00000000000..9aae7980a50 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/IEventLogController.cs @@ -0,0 +1,25 @@ +using DotNetNuke.Entities.Portals; + +namespace DotNetNuke.Services.Log.EventLog +{ + /// + /// Do not implement. This interface is only implemented by the DotNetNuke core framework. Outside the framework it should used as a type and for unit test purposes only. + /// There is no guarantee that this interface will not change. + /// + public interface IEventLogController + { + void AddLog(string propertyName, string propertyValue, EventLogController.EventLogType logType); + + void AddLog(string propertyName, string propertyValue, PortalSettings portalSettings, int userID, EventLogController.EventLogType logType); + + void AddLog(string propertyName, string propertyValue, PortalSettings portalSettings, int userID, string logType); + + void AddLog(PortalSettings portalSettings, int userID, EventLogController.EventLogType logType); + + void AddLog(LogProperties properties, PortalSettings portalSettings, int userID, string logTypeKey, bool bypassBuffering); + + void AddLog(object businessObject, PortalSettings portalSettings, int userID, string userName, EventLogController.EventLogType logType); + + void AddLog(object businessObject, PortalSettings portalSettings, int userID, string userName, string logType); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/ILogViewer.cs b/DNN Platform/Library/Services/Log/EventLog/ILogViewer.cs new file mode 100644 index 00000000000..2e0ee459119 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/ILogViewer.cs @@ -0,0 +1,31 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +namespace DotNetNuke.Services.Log.EventLog +{ + public interface ILogViewer + { + void BindData(); + + string EventFilter { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogController.cs b/DNN Platform/Library/Services/Log/EventLog/LogController.cs new file mode 100644 index 00000000000..a50053f87ac --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogController.cs @@ -0,0 +1,472 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data.SqlClient; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class LogController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (LogController)); + private const int WriterLockTimeout = 10000; //milliseconds + private static readonly ReaderWriterLock LockLog = new ReaderWriterLock(); + private static readonly PortalController portalController = new PortalController(); + + #region Private Methods + + private static void AddLogToFile(LogInfo logInfo) + { + try + { + var f = Globals.HostMapPath + "\\Logs\\LogFailures.xml.resources"; + WriteLog(f, logInfo.Serialize()); + } + // ReSharper disable EmptyGeneralCatchClause + catch (Exception exc) // ReSharper restore EmptyGeneralCatchClause + { + Logger.Error(exc); + + } + } + + private static void RaiseError(string filePath, string header, string message) + { + Logger.ErrorFormat("filePath={0}, header={1}, message={2}", filePath, header, message); + + if (HttpContext.Current != null) + { + HttpResponse response = HttpContext.Current.Response; + HtmlUtils.WriteHeader(response, header); + HtmlUtils.WriteError(response, filePath, message); + HtmlUtils.WriteFooter(response); + response.End(); + } + } + + private static void WriteToStreamWriter(FileStream fs, string message) + { + using (var sw = new StreamWriter(fs, Encoding.UTF8)) + { + var fileLength = fs.Length; + if (fileLength > 0) + { + fs.Position = fileLength - 9; + } + else + { + message = "" + message; + } + sw.WriteLine(message + ""); + sw.Flush(); + } + } + + private static void WriteLog(string filePath, string message) + { + FileStream fs = null; + try + { + LockLog.AcquireWriterLock(WriterLockTimeout); + var intAttempts = 0; + while (fs == null && intAttempts < 100) + { + intAttempts += 1; + try + { + fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + catch (IOException exc) + { + Logger.Debug(exc); + Thread.Sleep(1); + } + } + if (fs == null) + { + if (HttpContext.Current != null) + { + HttpContext.Current.Response.Write("An error has occurred writing to the exception log."); + HttpContext.Current.Response.End(); + } + } + else + { + WriteToStreamWriter(fs, message); + } + } + catch (UnauthorizedAccessException) + { + RaiseError(filePath, "Unauthorized Access Error", "The Windows User Account listed below must have Read/Write Privileges for the website path."); + } + catch (DirectoryNotFoundException exc) + { + RaiseError(filePath, "Directory Not Found Error", exc.Message); + } + catch (PathTooLongException exc) + { + RaiseError(filePath, "Path Too Long Error", exc.Message); + } + catch (IOException exc) + { + RaiseError(filePath, "IO Error", exc.Message); + } + catch (SqlException exc) + { + RaiseError(filePath, "SQL Exception", SqlUtils.TranslateSQLException(exc)); + } + catch (Exception exc) + { + RaiseError(filePath, "Unhandled Error", exc.Message); + } + finally + { + if (fs != null) + { + fs.Close(); + } + LockLog.ReleaseWriterLock(); + } + } + + #endregion + + #region Public Methods + + public void AddLog(LogInfo logInfo) + { + if (Globals.Status == Globals.UpgradeStatus.Install) + { + //AddLogToFile(logInfo); + Logger.Info(logInfo); + } + else + { + try + { + logInfo.LogCreateDate = DateTime.Now; + logInfo.LogServerName = Globals.ServerName; + if (string.IsNullOrEmpty(logInfo.LogServerName)) + { + logInfo.LogServerName = "NA"; + } + if (String.IsNullOrEmpty(logInfo.LogUserName)) + { + if (HttpContext.Current != null) + { + if (HttpContext.Current.Request.IsAuthenticated) + { + logInfo.LogUserName = UserController.GetCurrentUserInfo().Username; + } + } + } + + //Get portal name if name isn't set + if (logInfo.LogPortalID != Null.NullInteger && String.IsNullOrEmpty(logInfo.LogPortalName)) + { + logInfo.LogPortalName = portalController.GetPortal(logInfo.LogPortalID).PortalName; + } + + if (LoggingProvider.Instance() != null) + { + try + { + LoggingProvider.Instance().AddLog(logInfo); + } + catch (Exception) + { + if (Globals.Status != Globals.UpgradeStatus.Upgrade) //this may caught exception during upgrade because old logging provider has problem in it. + { + throw; + } + } + + } + } + catch (Exception exc) + { + Logger.Error(exc); + + //AddLogToFile(logInfo); + } + } + } + + public virtual void AddLogType(string configFile, string fallbackConfigFile) + { + var xmlDoc = new XmlDocument(); + try + { + xmlDoc.Load(configFile); + } + catch (FileNotFoundException exc) + { + Logger.Debug(exc); + xmlDoc.Load(fallbackConfigFile); + } + + var logType = xmlDoc.SelectNodes("/LogConfig/LogTypes/LogType"); + if (logType != null) + { + foreach (XmlNode typeInfo in logType) + { + if (typeInfo.Attributes != null) + { + var objLogTypeInfo = new LogTypeInfo + { + LogTypeKey = typeInfo.Attributes["LogTypeKey"].Value, + LogTypeFriendlyName = typeInfo.Attributes["LogTypeFriendlyName"].Value, + LogTypeDescription = typeInfo.Attributes["LogTypeDescription"].Value, + LogTypeCSSClass = typeInfo.Attributes["LogTypeCSSClass"].Value, + LogTypeOwner = typeInfo.Attributes["LogTypeOwner"].Value + }; + AddLogType(objLogTypeInfo); + } + } + } + + var logTypeConfig = xmlDoc.SelectNodes("/LogConfig/LogTypeConfig"); + if (logTypeConfig != null) + { + foreach (XmlNode typeConfigInfo in logTypeConfig) + { + if (typeConfigInfo.Attributes != null) + { + var logTypeConfigInfo = new LogTypeConfigInfo + { + EmailNotificationIsActive = typeConfigInfo.Attributes["EmailNotificationStatus"].Value == "On", + KeepMostRecent = typeConfigInfo.Attributes["KeepMostRecent"].Value, + LoggingIsActive = typeConfigInfo.Attributes["LoggingStatus"].Value == "On", + LogTypeKey = typeConfigInfo.Attributes["LogTypeKey"].Value, + LogTypePortalID = typeConfigInfo.Attributes["LogTypePortalID"].Value, + MailFromAddress = typeConfigInfo.Attributes["MailFromAddress"].Value, + MailToAddress = typeConfigInfo.Attributes["MailToAddress"].Value, + NotificationThreshold = Convert.ToInt32(typeConfigInfo.Attributes["NotificationThreshold"].Value), + NotificationThresholdTime = Convert.ToInt32(typeConfigInfo.Attributes["NotificationThresholdTime"].Value), + NotificationThresholdTimeType = + (LogTypeConfigInfo.NotificationThresholdTimeTypes) + Enum.Parse(typeof(LogTypeConfigInfo.NotificationThresholdTimeTypes), typeConfigInfo.Attributes["NotificationThresholdTimeType"].Value) + }; + AddLogTypeConfigInfo(logTypeConfigInfo); + } + } + } + } + + public virtual void AddLogType(LogTypeInfo logType) + { + LoggingProvider.Instance().AddLogType(logType.LogTypeKey, logType.LogTypeFriendlyName, logType.LogTypeDescription, logType.LogTypeCSSClass, logType.LogTypeOwner); + } + + public virtual void AddLogTypeConfigInfo(LogTypeConfigInfo logTypeConfig) + { + LoggingProvider.Instance().AddLogTypeConfigInfo(logTypeConfig.ID, + logTypeConfig.LoggingIsActive, + logTypeConfig.LogTypeKey, + logTypeConfig.LogTypePortalID, + logTypeConfig.KeepMostRecent, + logTypeConfig.LogFileName, + logTypeConfig.EmailNotificationIsActive, + Convert.ToString(logTypeConfig.NotificationThreshold), + Convert.ToString(logTypeConfig.NotificationThresholdTime), + Convert.ToString((int)logTypeConfig.NotificationThresholdTimeType), + logTypeConfig.MailFromAddress, + logTypeConfig.MailToAddress); + } + + public void ClearLog() + { + LoggingProvider.Instance().ClearLog(); + } + + public void DeleteLog(LogInfo logInfo) + { + LoggingProvider.Instance().DeleteLog(logInfo); + } + + public virtual void DeleteLogType(LogTypeInfo logType) + { + LoggingProvider.Instance().DeleteLogType(logType.LogTypeKey); + } + + public virtual void DeleteLogTypeConfigInfo(LogTypeConfigInfo logTypeConfig) + { + LoggingProvider.Instance().DeleteLogTypeConfigInfo(logTypeConfig.ID); + } + + public virtual List GetLogs(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords) + { + return LoggingProvider.Instance().GetLogs(portalID, logType, pageSize, pageIndex, ref totalRecords); + } + + public virtual ArrayList GetLogTypeConfigInfo() + { + return LoggingProvider.Instance().GetLogTypeConfigInfo(); + } + + public virtual LogTypeConfigInfo GetLogTypeConfigInfoByID(string id) + { + return LoggingProvider.Instance().GetLogTypeConfigInfoByID(id); + } + + public virtual Dictionary GetLogTypeInfoDictionary() + { + return LoggingProvider.Instance().GetLogTypeInfo().Cast().ToDictionary(logTypeInfo => logTypeInfo.LogTypeKey); + } + + public virtual object GetSingleLog(LogInfo log, LoggingProvider.ReturnType returnType) + { + return LoggingProvider.Instance().GetSingleLog(log, returnType); + } + + public bool LoggingIsEnabled(string logType, int portalID) + { + return LoggingProvider.Instance().LoggingIsEnabled(logType, portalID); + } + + public void PurgeLogBuffer() + { + LoggingProvider.Instance().PurgeLogBuffer(); + } + + public virtual bool SupportsEmailNotification() + { + return LoggingProvider.Instance().SupportsEmailNotification(); + } + + public virtual bool SupportsInternalViewer() + { + return LoggingProvider.Instance().SupportsInternalViewer(); + } + + public virtual void UpdateLogTypeConfigInfo(LogTypeConfigInfo logTypeConfig) + { + LoggingProvider.Instance().UpdateLogTypeConfigInfo(logTypeConfig.ID, + logTypeConfig.LoggingIsActive, + logTypeConfig.LogTypeKey, + logTypeConfig.LogTypePortalID, + logTypeConfig.KeepMostRecent, + logTypeConfig.LogFileName, + logTypeConfig.EmailNotificationIsActive, + Convert.ToString(logTypeConfig.NotificationThreshold), + Convert.ToString(logTypeConfig.NotificationThresholdTime), + Convert.ToString((int)logTypeConfig.NotificationThresholdTimeType), + logTypeConfig.MailFromAddress, + logTypeConfig.MailToAddress); + } + + public virtual void UpdateLogType(LogTypeInfo logType) + { + LoggingProvider.Instance().UpdateLogType(logType.LogTypeKey, logType.LogTypeFriendlyName, logType.LogTypeDescription, logType.LogTypeCSSClass, logType.LogTypeOwner); + } + + #endregion + + #region Obsolete Methods + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 5.0 or earlier. This method has been replaced with one that supports record paging.")] + public virtual LogInfoArray GetLog() + { + return LoggingProvider.Instance().GetLog(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 5.0 or earlier. This method has been replaced with one that supports record paging.")] + public virtual LogInfoArray GetLog(int portalID) + { + return LoggingProvider.Instance().GetLog(portalID); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 5.0 or earlier. This method has been replaced with one that supports record paging.")] + public virtual LogInfoArray GetLog(int portalID, string logType) + { + return LoggingProvider.Instance().GetLog(portalID, logType); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 5.0 or earlier. This method has been replaced with one that supports record paging.")] + public virtual LogInfoArray GetLog(string logType) + { + return LoggingProvider.Instance().GetLog(logType); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public virtual LogInfoArray GetLog(int pageSize, int pageIndex, ref int totalRecords) + { + return LoggingProvider.Instance().GetLog(pageSize, pageIndex, ref totalRecords); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public virtual LogInfoArray GetLog(int portalID, int pageSize, int pageIndex, ref int totalRecords) + { + return LoggingProvider.Instance().GetLog(portalID, pageSize, pageIndex, ref totalRecords); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public virtual LogInfoArray GetLog(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords) + { + return LoggingProvider.Instance().GetLog(portalID, logType, pageSize, pageIndex, ref totalRecords); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public virtual LogInfoArray GetLog(string logType, int pageSize, int pageIndex, ref int totalRecords) + { + return LoggingProvider.Instance().GetLog(logType, pageSize, pageIndex, ref totalRecords); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogTypeInfoDictionary().")] + public virtual ArrayList GetLogTypeInfo() + { + return LoggingProvider.Instance().GetLogTypeInfo(); + } + + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogDetailInfo.cs b/DNN Platform/Library/Services/Log/EventLog/LogDetailInfo.cs new file mode 100644 index 00000000000..826a406dd00 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogDetailInfo.cs @@ -0,0 +1,107 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Text; +using System.Xml; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Serializable] + public class LogDetailInfo + { + private string _PropertyName; + private string _PropertyValue; + + public LogDetailInfo() : this("", "") + { + } + + public LogDetailInfo(string name, string value) + { + _PropertyName = name; + _PropertyValue = value; + } + + public string PropertyName + { + get + { + return _PropertyName; + } + set + { + _PropertyName = value; + } + } + + public string PropertyValue + { + get + { + return _PropertyValue; + } + set + { + _PropertyValue = value; + } + } + + public void ReadXml(XmlReader reader) + { + reader.ReadStartElement("PropertyName"); + PropertyName = reader.ReadString(); + reader.ReadEndElement(); + if (!reader.IsEmptyElement) + { + reader.ReadStartElement("PropertyValue"); + PropertyValue = reader.ReadString(); + reader.ReadEndElement(); + } + else + { + reader.Read(); + } + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("

    "); + sb.Append(PropertyName); + sb.Append(": "); + sb.Append(PropertyValue); + sb.Append("

    "); + return sb.ToString(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteStartElement("LogProperty"); + writer.WriteElementString("PropertyName", PropertyName); + writer.WriteElementString("PropertyValue", PropertyValue); + writer.WriteEndElement(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogInfo.cs b/DNN Platform/Library/Services/Log/EventLog/LogInfo.cs new file mode 100644 index 00000000000..84f27d0ebed --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogInfo.cs @@ -0,0 +1,254 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text; +using System.Xml; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Serializable] + public class LogInfo + { + #region Constructors + + public LogInfo() + { + LogGUID = Guid.NewGuid().ToString(); + BypassBuffering = false; + LogProperties = new LogProperties(); + LogPortalID = -1; + LogPortalName = ""; + LogUserID = -1; + LogUserName = ""; + } + + public LogInfo(string content) : this() + { + Deserialize(content); + } + + #endregion + + #region "Properties" + + public string LogGUID { get; set; } + + public string LogFileID { get; set; } + + public string LogTypeKey { get; set; } + + public int LogUserID { get; set; } + + public string LogUserName { get; set; } + + public int LogPortalID { get; set; } + + public string LogPortalName { get; set; } + + public DateTime LogCreateDate { get; set; } + + public long LogCreateDateNum { get; set; } + + public LogProperties LogProperties { get; set; } + + public bool BypassBuffering { get; set; } + + public string LogServerName { get; set; } + + public string LogConfigID { get; set; } + + #endregion + + #region Public Methods + + public void AddProperty(string PropertyName, string PropertyValue) + { + try + { + if (PropertyValue == null) + { + PropertyValue = string.Empty; + } + if (PropertyName.Length > 50) + { + PropertyName = PropertyName.Substring(0, 50); + } + if (PropertyValue.Length > 500) + { + PropertyValue = "(TRUNCATED TO 500 CHARS): " + PropertyValue.Substring(0, 500); + } + var objLogDetailInfo = new LogDetailInfo(); + objLogDetailInfo.PropertyName = PropertyName; + objLogDetailInfo.PropertyValue = PropertyValue; + LogProperties.Add(objLogDetailInfo); + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + + public void Deserialize(string content) + { + using (XmlReader reader = XmlReader.Create(new StringReader(content))) + { + if (reader.Read()) + { + ReadXml(reader); + } + reader.Close(); + } + } + + public void ReadXml(XmlReader reader) + { + if (reader.HasAttributes) + { + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "LogGUID": + LogGUID = reader.ReadContentAsString(); + break; + case "LogFileID": + LogFileID = reader.ReadContentAsString(); + break; + case "LogTypeKey": + LogTypeKey = reader.ReadContentAsString(); + break; + case "LogUserID": + LogUserID = reader.ReadContentAsInt(); + break; + case "LogUserName": + LogUserName = reader.ReadContentAsString(); + break; + case "LogPortalID": + LogPortalID = reader.ReadContentAsInt(); + break; + case "LogPortalName": + LogPortalName = reader.ReadContentAsString(); + break; + case "LogCreateDate": + LogCreateDate = DateTime.Parse(reader.ReadContentAsString()); + break; + case "LogCreateDateNum": + LogCreateDateNum = reader.ReadContentAsLong(); + break; + case "BypassBuffering": + BypassBuffering = bool.Parse(reader.ReadContentAsString()); + break; + case "LogServerName": + LogServerName = reader.ReadContentAsString(); + break; + case "LogConfigID": + LogConfigID = reader.ReadContentAsString(); + break; + } + } + } + + //Check for LogProperties child node + reader.Read(); + if (reader.NodeType == XmlNodeType.Element && reader.LocalName == "LogProperties") + { + reader.ReadStartElement("LogProperties"); + if (reader.ReadState != ReadState.EndOfFile && reader.NodeType != XmlNodeType.None && !String.IsNullOrEmpty(reader.LocalName)) + { + LogProperties.ReadXml(reader); + } + } + } + + public static bool IsSystemType(string PropName) + { + switch (PropName) + { + case "LogGUID": + case "LogFileID": + case "LogTypeKey": + case "LogCreateDate": + case "LogCreateDateNum": + case "LogPortalID": + case "LogPortalName": + case "LogUserID": + case "LogUserName": + case "BypassBuffering": + case "LogServerName": + return true; + } + return false; + } + + public string Serialize() + { + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.OmitXmlDeclaration = true; + var sb = new StringBuilder(); + XmlWriter writer = XmlWriter.Create(sb, settings); + WriteXml(writer); + writer.Close(); + return sb.ToString(); + } + + public override string ToString() + { + var str = new StringBuilder(); + str.Append("

    LogGUID:" + LogGUID + "

    "); + str.Append("

    LogType:" + LogTypeKey + "

    "); + str.Append("

    UserID:" + LogUserID + "

    "); + str.Append("

    Username:" + LogUserName + "

    "); + str.Append("

    PortalID:" + LogPortalID + "

    "); + str.Append("

    PortalName:" + LogPortalName + "

    "); + str.Append("

    CreateDate:" + LogCreateDate + "

    "); + str.Append("

    ServerName:" + LogServerName + "

    "); + str.Append(LogProperties.ToString()); + return str.ToString(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteStartElement("log"); + writer.WriteAttributeString("LogGUID", LogGUID); + writer.WriteAttributeString("LogFileID", LogFileID); + writer.WriteAttributeString("LogTypeKey", LogTypeKey); + writer.WriteAttributeString("LogUserID", LogUserID.ToString()); + writer.WriteAttributeString("LogUserName", LogUserName); + writer.WriteAttributeString("LogPortalID", LogPortalID.ToString()); + writer.WriteAttributeString("LogPortalName", LogPortalName); + writer.WriteAttributeString("LogCreateDate", LogCreateDate.ToString()); + writer.WriteAttributeString("LogCreateDateNum", LogCreateDateNum.ToString()); + writer.WriteAttributeString("BypassBuffering", BypassBuffering.ToString()); + writer.WriteAttributeString("LogServerName", LogServerName); + writer.WriteAttributeString("LogConfigID", LogConfigID); + LogProperties.WriteXml(writer); + writer.WriteEndElement(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogInfoArray.cs b/DNN Platform/Library/Services/Log/EventLog/LogInfoArray.cs new file mode 100644 index 00000000000..6bff11726e0 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogInfoArray.cs @@ -0,0 +1,160 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Serializable] + [Obsolete("Deprecated in 6.0. Replaced by List.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public class LogInfoArray : IEnumerable, IList + { + private readonly ArrayList _arrLogs = new ArrayList(); + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return _arrLogs.GetEnumerator(); + } + + #endregion + + #region IList Members + + public int Count + { + get + { + return _arrLogs.Count; + } + } + + public int Add(object objLogInfo) + { + return _arrLogs.Add(objLogInfo); + } + + public void Remove(object objLogInfo) + { + _arrLogs.Remove(objLogInfo); + } + + public void CopyTo(Array array, int index) + { + _arrLogs.CopyTo(array, index); + } + + public bool IsSynchronized + { + get + { + return _arrLogs.IsSynchronized; + } + } + + public object SyncRoot + { + get + { + return _arrLogs.SyncRoot; + } + } + + public void Clear() + { + _arrLogs.Clear(); + } + + public bool Contains(object value) + { + if (_arrLogs.Contains(value)) + { + return true; + } + else + { + return false; + } + } + + public int IndexOf(object value) + { + return _arrLogs.IndexOf(value); + } + + public void Insert(int index, object value) + { + _arrLogs.Insert(index, value); + } + + public bool IsFixedSize + { + get + { + return _arrLogs.IsFixedSize; + } + } + + public bool IsReadOnly + { + get + { + return _arrLogs.IsReadOnly; + } + } + + public object this[int index] + { + get + { + return _arrLogs[index]; + } + set + { + _arrLogs[index] = value; + } + } + + public void RemoveAt(int index) + { + _arrLogs.RemoveAt(index); + } + + #endregion + + public LogInfo GetItem(int Index) + { + return (LogInfo) _arrLogs[Index]; + } + + public IEnumerator GetEnumerator(int index, int count) + { + return _arrLogs.GetEnumerator(index, count); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogProperties.cs b/DNN Platform/Library/Services/Log/EventLog/LogProperties.cs new file mode 100644 index 00000000000..6310a27714b --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogProperties.cs @@ -0,0 +1,121 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Xml; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class LogProperties : ArrayList + { + #region "Public Properties" + + public string Summary + { + get + { + string summary = HtmlUtils.Clean(ToString(), true); + if (summary.Length > 75) + { + summary = summary.Substring(0, 75); + } + return summary; + } + } + + #endregion + + #region "Public Methods" + + public void Deserialize(string content) + { + using (XmlReader reader = XmlReader.Create(new StringReader(content))) + { + reader.ReadStartElement("LogProperties"); + if (reader.ReadState != ReadState.EndOfFile && reader.NodeType != XmlNodeType.None && !String.IsNullOrEmpty(reader.LocalName)) + { + ReadXml(reader); + } + reader.Close(); + } + } + + public void ReadXml(XmlReader reader) + { + do + { + reader.ReadStartElement("LogProperty"); + + //Create new LogDetailInfo object + var logDetail = new LogDetailInfo(); + + //Load it from the Xml + logDetail.ReadXml(reader); + + //Add to the collection + Add(logDetail); + + } while (reader.ReadToNextSibling("LogProperty")); + } + + public string Serialize() + { + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.OmitXmlDeclaration = true; + var sb = new StringBuilder(); + XmlWriter writer = XmlWriter.Create(sb, settings); + WriteXml(writer); + writer.Close(); + return sb.ToString(); + } + + public override string ToString() + { + var sb = new StringBuilder(); + foreach (LogDetailInfo logDetail in this) + { + sb.Append(logDetail.ToString()); + } + return sb.ToString(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteStartElement("LogProperties"); + foreach (LogDetailInfo logDetail in this) + { + logDetail.WriteXml(writer); + } + writer.WriteEndElement(); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogQueueItem.cs b/DNN Platform/Library/Services/Log/EventLog/LogQueueItem.cs new file mode 100644 index 00000000000..56f55c93f8d --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogQueueItem.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Log.EventLog +{ + public class LogQueueItem + { + public LogInfo LogInfo { get; set; } + + public LogTypeConfigInfo LogTypeConfigInfo { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogTypeConfigInfo.cs b/DNN Platform/Library/Services/Log/EventLog/LogTypeConfigInfo.cs new file mode 100644 index 00000000000..5fb4a272ebd --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogTypeConfigInfo.cs @@ -0,0 +1,91 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Serializable] + public class LogTypeConfigInfo : LogTypeInfo + { + #region NotificationThresholdTimeTypes enum + + public enum NotificationThresholdTimeTypes + { + None = 0, + Seconds = 1, + Minutes = 2, + Hours = 3, + Days = 4 + } + + #endregion + + public DateTime StartDateTime + { + get + { + switch (NotificationThresholdTimeType) + { + case NotificationThresholdTimeTypes.Seconds: + return DateTime.Now.AddSeconds(NotificationThresholdTime*-1); + case NotificationThresholdTimeTypes.Minutes: + return DateTime.Now.AddMinutes(NotificationThresholdTime*-1); + case NotificationThresholdTimeTypes.Hours: + return DateTime.Now.AddHours(NotificationThresholdTime*-1); + case NotificationThresholdTimeTypes.Days: + return DateTime.Now.AddDays(NotificationThresholdTime*-1); + default: + return Null.NullDate; + } + } + } + + public bool EmailNotificationIsActive { get; set; } + + public string MailFromAddress { get; set; } + + public string MailToAddress { get; set; } + + public int NotificationThreshold { get; set; } + + public int NotificationThresholdTime { get; set; } + + public NotificationThresholdTimeTypes NotificationThresholdTimeType { get; set; } + + public string ID { get; set; } + + public bool LoggingIsActive { get; set; } + + public string LogFileName { get; set; } + + public string LogFileNameWithPath { get; set; } + + public string LogTypePortalID { get; set; } + + public string KeepMostRecent { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogTypeInfo.cs b/DNN Platform/Library/Services/Log/EventLog/LogTypeInfo.cs new file mode 100644 index 00000000000..a1409d13d2c --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogTypeInfo.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Serializable] + public class LogTypeInfo + { + public string LogTypeCSSClass { get; set; } + + public string LogTypeDescription { get; set; } + + public string LogTypeFriendlyName { get; set; } + + public string LogTypeKey { get; set; } + + public string LogTypeOwner { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LogTypeSortFriendlyName.cs b/DNN Platform/Library/Services/Log/EventLog/LogTypeSortFriendlyName.cs new file mode 100644 index 00000000000..3b1799d7a44 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LogTypeSortFriendlyName.cs @@ -0,0 +1,44 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Obsolete("Deprecated in 6.0. No longer neccessary becuase of LINQ.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public class LogTypeSortFriendlyName : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((LogTypeInfo) x).LogTypeFriendlyName.CompareTo(((LogTypeInfo) y).LogTypeFriendlyName); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/LoggingProvider.cs b/DNN Platform/Library/Services/Log/EventLog/LoggingProvider.cs new file mode 100644 index 00000000000..38a1f6c00f2 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/LoggingProvider.cs @@ -0,0 +1,140 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +using DotNetNuke.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public abstract class LoggingProvider + { + #region ReturnType enum + + public enum ReturnType + { + LogInfoObjects, + XML + } + + #endregion + + #region "Shared/Static Methods" + + //return the provider + public static LoggingProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region "Abstract Methods" + + public abstract void AddLog(LogInfo logInfo); + + public abstract void AddLogType(string logTypeKey, string logTypeFriendlyName, string logTypeDescription, string logTypeCSSClass, string logTypeOwner); + + public abstract void AddLogTypeConfigInfo(string id, bool loggingIsActive, string logTypeKey, string logTypePortalID, string keepMostRecent, string logFileName, bool emailNotificationIsActive, string threshold, string notificationThresholdTime, string notificationThresholdTimeType, string mailFromAddress, string mailToAddress); + + public abstract void ClearLog(); + + public abstract void DeleteLog(LogInfo logInfo); + + public abstract void DeleteLogType(string logTypeKey); + + public abstract void DeleteLogTypeConfigInfo(string id); + + public virtual List GetLogs(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords) + { +#pragma warning disable 612,618 + return GetLog(portalID, logType, pageSize, pageIndex, ref totalRecords).Cast().ToList(); +#pragma warning restore 612,618 + } + + public abstract ArrayList GetLogTypeConfigInfo(); + + public abstract ArrayList GetLogTypeInfo(); + + public abstract LogTypeConfigInfo GetLogTypeConfigInfoByID(string id); + + public abstract object GetSingleLog(LogInfo logInfo, ReturnType returnType); + + public abstract bool LoggingIsEnabled(string logType, int portalID); + + public abstract void PurgeLogBuffer(); + + public abstract void SendLogNotifications(); + + public abstract bool SupportsEmailNotification(); + + public abstract bool SupportsInternalViewer(); + + public abstract bool SupportsSendToCoreTeam(); + + public abstract bool SupportsSendViaEmail(); + + public abstract void UpdateLogType(string logTypeKey, string logTypeFriendlyName, string logTypeDescription, string logTypeCSSClass, string logTypeOwner); + + public abstract void UpdateLogTypeConfigInfo(string id, bool loggingIsActive, string logTypeKey, string logTypePortalID, string keepMostRecent, string logFileName, bool emailNotificationIsActive, string threshold, string notificationThresholdTime, string notificationThresholdTimeType, string mailFromAddress, string mailToAddress); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(string logType); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(int portalID); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(int portalID, string logType); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(int pageSize, int pageIndex, ref int totalRecords); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(string logType, int pageSize, int pageIndex, ref int totalRecords); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(int portalID, int pageSize, int pageIndex, ref int totalRecords); + + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Deprecated in 6.0. Replaced by GetLogs().")] + public abstract LogInfoArray GetLog(int portalID, string logType, int pageSize, int pageIndex, ref int totalRecords); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/PortalSortTitle.cs b/DNN Platform/Library/Services/Log/EventLog/PortalSortTitle.cs new file mode 100644 index 00000000000..48c464a4c87 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/PortalSortTitle.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.ComponentModel; + +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + [Obsolete("Deprecated in 6.0. No longer neccessary becuase of LINQ.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public class PortalSortTitle : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((PortalInfo) x).PortalName.CompareTo(((PortalInfo) y).PortalName); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/PurgeLogBuffer.cs b/DNN Platform/Library/Services/Log/EventLog/PurgeLogBuffer.cs new file mode 100644 index 00000000000..6c6cbc4be49 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/PurgeLogBuffer.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class PurgeLogBuffer : SchedulerClient + { + public PurgeLogBuffer(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); //OPTIONAL + LoggingProvider.Instance().PurgeLogBuffer(); + ScheduleHistoryItem.Succeeded = true; //REQUIRED + ScheduleHistoryItem.AddLogNote("Purged log entries successfully"); //OPTIONAL + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + ScheduleHistoryItem.AddLogNote("EXCEPTION: " + exc); //OPTIONAL + Errored(ref exc); //REQUIRED + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/EventLog/SendLogNotifications.cs b/DNN Platform/Library/Services/Log/EventLog/SendLogNotifications.cs new file mode 100644 index 00000000000..cec7af39661 --- /dev/null +++ b/DNN Platform/Library/Services/Log/EventLog/SendLogNotifications.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Log.EventLog +{ + public class SendLogNotifications : SchedulerClient + { + public SendLogNotifications(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); //OPTIONAL + LoggingProvider.Instance().SendLogNotifications(); + ScheduleHistoryItem.Succeeded = true; //REQUIRED + ScheduleHistoryItem.AddLogNote("Sent log notifications successfully"); //OPTIONAL + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + ScheduleHistoryItem.AddLogNote("EXCEPTION: " + exc); //OPTIONAL + Errored(ref exc); //REQUIRED + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/SiteLog/BufferedSiteLog.cs b/DNN Platform/Library/Services/Log/SiteLog/BufferedSiteLog.cs new file mode 100644 index 00000000000..819e2d88cac --- /dev/null +++ b/DNN Platform/Library/Services/Log/SiteLog/BufferedSiteLog.cs @@ -0,0 +1,87 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Data; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Log.SiteLog +{ + public class BufferedSiteLog + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (BufferedSiteLog)); + public ArrayList SiteLog; + public string SiteLogStorage; + + public void AddSiteLog() + { + try + { + SiteLogInfo objSiteLog; + var objSiteLogs = new SiteLogController(); + + //iterate through buffered sitelog items and insert into database + int intIndex; + for (intIndex = 0; intIndex <= SiteLog.Count - 1; intIndex++) + { + objSiteLog = (SiteLogInfo) SiteLog[intIndex]; + switch (SiteLogStorage) + { + case "D": //database + DataProvider.Instance().AddSiteLog(objSiteLog.DateTime, + objSiteLog.PortalId, + objSiteLog.UserId, + objSiteLog.Referrer, + objSiteLog.URL, + objSiteLog.UserAgent, + objSiteLog.UserHostAddress, + objSiteLog.UserHostName, + objSiteLog.TabId, + objSiteLog.AffiliateId); + break; + case "F": //file system + objSiteLogs.W3CExtendedLog(objSiteLog.DateTime, + objSiteLog.PortalId, + objSiteLog.UserId, + objSiteLog.Referrer, + objSiteLog.URL, + objSiteLog.UserAgent, + objSiteLog.UserHostAddress, + objSiteLog.UserHostName, + objSiteLog.TabId, + objSiteLog.AffiliateId); + break; + } + } + } + catch (Exception exc) + { + Logger.Error(exc); + + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/SiteLog/PurgeSiteLog.cs b/DNN Platform/Library/Services/Log/SiteLog/PurgeSiteLog.cs new file mode 100644 index 00000000000..0ee8b60cde6 --- /dev/null +++ b/DNN Platform/Library/Services/Log/SiteLog/PurgeSiteLog.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Log.SiteLog +{ + public class PurgeSiteLog : SchedulerClient + { + public PurgeSiteLog(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); //OPTIONAL + + DoPurgeSiteLog(); + + ScheduleHistoryItem.Succeeded = true; //REQUIRED + + ScheduleHistoryItem.AddLogNote("Site Log purged."); + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + + ScheduleHistoryItem.AddLogNote("Site Log purge failed. " + exc); //OPTIONAL + + //notification that we have errored + Errored(ref exc); + + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + + private void DoPurgeSiteLog() + { + var objSiteLog = new SiteLogController(); + var objPortals = new PortalController(); + ArrayList arrPortals = objPortals.GetPortals(); + PortalInfo objPortal; + DateTime PurgeDate; + int intIndex; + for (intIndex = 0; intIndex <= arrPortals.Count - 1; intIndex++) + { + objPortal = (PortalInfo) arrPortals[intIndex]; + if (objPortal.SiteLogHistory > 0) + { + PurgeDate = DateTime.Now.AddDays(-(objPortal.SiteLogHistory)); + objSiteLog.DeleteSiteLog(PurgeDate, objPortal.PortalID); + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/SiteLog/SiteLogController.cs b/DNN Platform/Library/Services/Log/SiteLog/SiteLogController.cs new file mode 100644 index 00000000000..abad7d5d8bb --- /dev/null +++ b/DNN Platform/Library/Services/Log/SiteLog/SiteLogController.cs @@ -0,0 +1,217 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Data; +using System.IO; +using System.Text; +using System.Threading; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.Log.SiteLog +{ + public class SiteLogController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SiteLogController)); + public void AddSiteLog(int PortalId, int UserId, string Referrer, string URL, string UserAgent, string UserHostAddress, string UserHostName, int TabId, int AffiliateId, int SiteLogBuffer, + string SiteLogStorage) + { + var objSecurity = new PortalSecurity(); + try + { + if (Host.PerformanceSetting == Globals.PerformanceSettings.NoCaching) + { + SiteLogBuffer = 1; + } + switch (SiteLogBuffer) + { + case 0: //logging disabled + break; + case 1: //no buffering + switch (SiteLogStorage) + { + case "D": //database + DataProvider.Instance().AddSiteLog(DateTime.Now, + PortalId, + UserId, + objSecurity.InputFilter(Referrer, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(URL, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserAgent, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserHostAddress, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserHostName, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + TabId, + AffiliateId); + break; + case "F": //file system + W3CExtendedLog(DateTime.Now, + PortalId, + UserId, + objSecurity.InputFilter(Referrer, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(URL, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserAgent, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserHostAddress, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + objSecurity.InputFilter(UserHostName, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup), + TabId, + AffiliateId); + break; + } + break; + default: //buffered logging + string key = "SiteLog" + PortalId; + var arrSiteLog = (ArrayList) DataCache.GetCache(key); + + //get buffered site log records from the cache + if (arrSiteLog == null) + { + arrSiteLog = new ArrayList(); + DataCache.SetCache(key, arrSiteLog); + } + + //create new sitelog object + var objSiteLog = new SiteLogInfo(); + objSiteLog.DateTime = DateTime.Now; + objSiteLog.PortalId = PortalId; + objSiteLog.UserId = UserId; + objSiteLog.Referrer = objSecurity.InputFilter(Referrer, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup); + objSiteLog.URL = objSecurity.InputFilter(URL, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup); + objSiteLog.UserAgent = objSecurity.InputFilter(UserAgent, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup); + objSiteLog.UserHostAddress = objSecurity.InputFilter(UserHostAddress, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup); + objSiteLog.UserHostName = objSecurity.InputFilter(UserHostName, PortalSecurity.FilterFlag.NoScripting | PortalSecurity.FilterFlag.NoMarkup); + objSiteLog.TabId = TabId; + objSiteLog.AffiliateId = AffiliateId; + + //add sitelog object to cache + arrSiteLog.Add(objSiteLog); + + if (arrSiteLog.Count >= SiteLogBuffer) + { + //create the buffered sitelog object + var objBufferedSiteLog = new BufferedSiteLog(); + objBufferedSiteLog.SiteLogStorage = SiteLogStorage; + objBufferedSiteLog.SiteLog = arrSiteLog; + + //clear the current sitelogs from the cache + DataCache.RemoveCache(key); + + //process buffered sitelogs on a background thread + var objThread = new Thread(objBufferedSiteLog.AddSiteLog); + objThread.Start(); + } + break; + } + } + catch (Exception exc) + { + Logger.Error(exc); + + } + } + + public IDataReader GetSiteLog(int PortalId, string PortalAlias, int ReportType, DateTime StartDate, DateTime EndDate) + { + return DataProvider.Instance().GetSiteLog(PortalId, PortalAlias, "GetSiteLog" + ReportType, StartDate, EndDate); + } + + public void DeleteSiteLog(DateTime DateTime, int PortalId) + { + DataProvider.Instance().DeleteSiteLog(DateTime, PortalId); + } + + public void W3CExtendedLog(DateTime DateTime, int PortalId, int UserId, string Referrer, string URL, string UserAgent, string UserHostAddress, string UserHostName, int TabId, int AffiliateId) + { + StreamWriter objStream; + + //create log file path + string LogFilePath = Globals.ApplicationMapPath + "\\Portals\\" + PortalId + "\\Logs\\"; + string LogFileName = "ex" + DateTime.Now.ToString("yyMMdd") + ".log"; + + //check if log file exists + if (!File.Exists(LogFilePath + LogFileName)) + { + try + { + //create log file + Directory.CreateDirectory(LogFilePath); + + //open log file for append ( position the stream at the end of the file ) + objStream = File.AppendText(LogFilePath + LogFileName); + + //add standard log file headers + objStream.WriteLine("#Software: Microsoft Internet Information Services 6.0"); + objStream.WriteLine("#Version: 1.0"); + objStream.WriteLine("#Date: " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")); + objStream.WriteLine("#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status"); + + //close stream + objStream.Flush(); + objStream.Close(); + } + catch (Exception ex) //can not create file + { + Logger.Error(ex); + } + } + try + { + //open log file for append ( position the stream at the end of the file ) + objStream = File.AppendText(LogFilePath + LogFileName); + + //declare a string builder + var objStringBuilder = new StringBuilder(1024); + + //build W3C extended log item + objStringBuilder.Append(DateTime.ToString("yyyy-MM-dd hh:mm:ss") + " "); + objStringBuilder.Append(UserHostAddress + " "); + objStringBuilder.Append("GET" + " "); + objStringBuilder.Append(URL + " "); + objStringBuilder.Append("-" + " "); + objStringBuilder.Append("80" + " "); + objStringBuilder.Append("-" + " "); + objStringBuilder.Append(UserHostAddress + " "); + objStringBuilder.Append(UserAgent.Replace(" ", "+") + " "); + objStringBuilder.Append("200" + " "); + objStringBuilder.Append("0" + " "); + objStringBuilder.Append("0"); + + //write to log file + objStream.WriteLine(objStringBuilder.ToString()); + + //close stream + objStream.Flush(); + objStream.Close(); + } + catch (Exception ex) //can not open file + { + Logger.Error(ex); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Log/SiteLog/SiteLogInfo.cs b/DNN Platform/Library/Services/Log/SiteLog/SiteLogInfo.cs new file mode 100644 index 00000000000..3e9f90609b5 --- /dev/null +++ b/DNN Platform/Library/Services/Log/SiteLog/SiteLogInfo.cs @@ -0,0 +1,163 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Log.SiteLog +{ + [Serializable] + public class SiteLogInfo + { + private int _AffiliateId; + private DateTime _DateTime; + private int _PortalId; + private string _Referrer; + private int _TabId; + private string _URL; + private string _UserAgent; + private string _UserHostAddress; + private string _UserHostName; + private int _UserId; + + public DateTime DateTime + { + get + { + return _DateTime; + } + set + { + _DateTime = value; + } + } + + public int PortalId + { + get + { + return _PortalId; + } + set + { + _PortalId = value; + } + } + + public int UserId + { + get + { + return _UserId; + } + set + { + _UserId = value; + } + } + + public string Referrer + { + get + { + return _Referrer; + } + set + { + _Referrer = value; + } + } + + public string URL + { + get + { + return _URL; + } + set + { + _URL = value; + } + } + + public string UserAgent + { + get + { + return _UserAgent; + } + set + { + _UserAgent = value; + } + } + + public string UserHostAddress + { + get + { + return _UserHostAddress; + } + set + { + _UserHostAddress = value; + } + } + + public string UserHostName + { + get + { + return _UserHostName; + } + set + { + _UserHostName = value; + } + } + + public int TabId + { + get + { + return _TabId; + } + set + { + _TabId = value; + } + } + + public int AffiliateId + { + get + { + return _AffiliateId; + } + set + { + _AffiliateId = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mail/Mail.cs b/DNN Platform/Library/Services/Mail/Mail.cs new file mode 100644 index 00000000000..b0fe3205eda --- /dev/null +++ b/DNN Platform/Library/Services/Mail/Mail.cs @@ -0,0 +1,487 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Mail; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Tokens; + +using Localize = DotNetNuke.Services.Localization.Localization; + +#endregion + +namespace DotNetNuke.Services.Mail +{ + public class Mail + { + #region Private Methods + + private static string SendMailInternal(MailMessage mailMessage, string subject, string body, MailPriority priority, + MailFormat bodyFormat, Encoding bodyEncoding, IEnumerable attachments, + string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + string retValue; + + mailMessage.Priority = (System.Net.Mail.MailPriority)priority; + mailMessage.IsBodyHtml = (bodyFormat == MailFormat.Html); + + //attachments + foreach (var attachment in attachments) + { + mailMessage.Attachments.Add(attachment); + } + + //message + mailMessage.SubjectEncoding = bodyEncoding; + mailMessage.Subject = HtmlUtils.StripWhiteSpace(subject, true); + mailMessage.BodyEncoding = bodyEncoding; + + //added support for multipart html messages + //add text part as alternate view + var PlainView = AlternateView.CreateAlternateViewFromString(ConvertToText(body), null, "text/plain"); + mailMessage.AlternateViews.Add(PlainView); + if (mailMessage.IsBodyHtml) + { + var HTMLView = AlternateView.CreateAlternateViewFromString(body, null, "text/html"); + mailMessage.AlternateViews.Add(HTMLView); + } + + if (!String.IsNullOrEmpty(smtpServer)) + { + try + { + var smtpClient = new SmtpClient(); + + var smtpHostParts = smtpServer.Split(':'); + smtpClient.Host = smtpHostParts[0]; + if (smtpHostParts.Length > 1) + { + smtpClient.Port = Convert.ToInt32(smtpHostParts[1]); + } + + switch (smtpAuthentication) + { + case "": + case "0": //anonymous + break; + case "1": //basic + if (!String.IsNullOrEmpty(smtpUsername) && !String.IsNullOrEmpty(smtpPassword)) + { + smtpClient.UseDefaultCredentials = false; + smtpClient.Credentials = new NetworkCredential(smtpUsername, smtpPassword); + } + break; + case "2": //NTLM + smtpClient.UseDefaultCredentials = true; + break; + } + smtpClient.EnableSsl = smtpEnableSSL; + smtpClient.Send(mailMessage); + retValue = ""; + } + catch (SmtpFailedRecipientException exc) + { + retValue = string.Format(Localize.GetString("FailedRecipient"), exc.FailedRecipient); + Exceptions.Exceptions.LogException(exc); + } + catch (SmtpException exc) + { + retValue = Localize.GetString("SMTPConfigurationProblem"); + Exceptions.Exceptions.LogException(exc); + } + catch (Exception exc) + { + //mail configuration problem + if (exc.InnerException != null) + { + retValue = string.Concat(exc.Message, Environment.NewLine, exc.InnerException.Message); + Exceptions.Exceptions.LogException(exc.InnerException); + } + else + { + retValue = exc.Message; + Exceptions.Exceptions.LogException(exc); + } + } + finally + { + mailMessage.Dispose(); + } + } + else + { + retValue = Localize.GetString("SMTPConfigurationProblem"); + } + + return retValue; + } + + #endregion + + #region Public Methods + + public static string ConvertToText(string sHTML) + { + string sContent = sHTML; + sContent = sContent.Replace("
    ", Environment.NewLine); + sContent = sContent.Replace("
    ", Environment.NewLine); + sContent = HtmlUtils.FormatText(sContent, true); + return HtmlUtils.StripTags(sContent, true); + } + + public static bool IsValidEmailAddress(string Email, int portalid) + { + string pattern = Null.NullString; + //During install Wizard we may not have a valid PortalID + if (portalid != Null.NullInteger) + { + pattern = Convert.ToString(UserController.GetUserSettings(portalid)["Security_EmailValidation"]); + } + pattern = string.IsNullOrEmpty(pattern) ? Globals.glbEmailRegEx : pattern; + return Regex.Match(Email, pattern).Success; + } + + public static void SendEmail(string fromAddress, string toAddress, string subject, string body) + { + SendEmail(fromAddress, fromAddress, toAddress, subject, body); + } + + public static void SendEmail(string fromAddress, string senderAddress, string toAddress, string subject, string body) + { + if ((string.IsNullOrEmpty(Host.SMTPServer))) + { + return; + } + + var emailMessage = new MailMessage(fromAddress, toAddress) { Sender = new MailAddress(senderAddress) }; + + SendMailInternal(emailMessage, subject, body, MailPriority.Normal, + HtmlUtils.IsHtml(body) ? MailFormat.Html : MailFormat.Text, + Encoding.UTF8, new List(), + Host.SMTPServer, Host.SMTPAuthentication, Host.SMTPUsername, + Host.SMTPPassword, Host.EnableSMTPSSL); + } + + public static string SendEmail(string fromAddress, string senderAddress, string toAddress, string subject, string body, List attachments) + { + if ((string.IsNullOrEmpty(Host.SMTPServer))) + { + return "SMTP Server not configured"; + } + + var emailMessage = new MailMessage(fromAddress, toAddress) { Sender = new MailAddress(senderAddress) }; + + return SendMailInternal(emailMessage, subject, body, MailPriority.Normal, + HtmlUtils.IsHtml(body) ? MailFormat.Html : MailFormat.Text, + Encoding.UTF8, attachments, + Host.SMTPServer, Host.SMTPAuthentication, Host.SMTPUsername, + Host.SMTPPassword, Host.EnableSMTPSSL); + + } + + /// ----------------------------------------------------------------------------- + /// + /// Send an email notification + /// + /// The user to whom the message is being sent + /// The type of message being sent + /// Portal Settings + /// + /// + /// + /// [cnurse] 09/29/2005 Moved to Mail class + /// [sLeupold] 02/07/2008 language used for admin mails corrected + /// + /// ----------------------------------------------------------------------------- + public static string SendMail(UserInfo user, MessageType msgType, PortalSettings settings) + { + //Send Notification to User + int toUser = user.UserID; + string locale = user.Profile.PreferredLocale; + string subject; + string body; + ArrayList custom = null; + switch (msgType) + { + case MessageType.UserRegistrationAdmin: + subject = "EMAIL_USER_REGISTRATION_ADMINISTRATOR_SUBJECT"; + body = "EMAIL_USER_REGISTRATION_ADMINISTRATOR_BODY"; + toUser = settings.AdministratorId; + UserInfo admin = UserController.GetUserById(settings.PortalId, settings.AdministratorId); + locale = admin.Profile.PreferredLocale; + break; + case MessageType.UserRegistrationPrivate: + subject = "EMAIL_USER_REGISTRATION_PRIVATE_SUBJECT"; + body = "EMAIL_USER_REGISTRATION_PRIVATE_BODY"; + break; + case MessageType.UserRegistrationPublic: + subject = "EMAIL_USER_REGISTRATION_PUBLIC_SUBJECT"; + body = "EMAIL_USER_REGISTRATION_PUBLIC_BODY"; + break; + case MessageType.UserRegistrationVerified: + subject = "EMAIL_USER_REGISTRATION_VERIFIED_SUBJECT"; + body = "EMAIL_USER_REGISTRATION_VERIFIED_BODY"; + var propertyNotFound = false; + if (HttpContext.Current != null) + { + custom = new ArrayList + { + HttpContext.Current.Server.UrlEncode(user.Username), + HttpContext.Current.Server.UrlEncode(user.GetProperty("verificationcode", String.Empty, null, user, Scope.SystemMessages, ref propertyNotFound)) + }; + } + break; + case MessageType.PasswordReminder: + subject = "EMAIL_PASSWORD_REMINDER_SUBJECT"; + body = "EMAIL_PASSWORD_REMINDER_BODY"; + break; + case MessageType.ProfileUpdated: + subject = "EMAIL_PROFILE_UPDATED_SUBJECT"; + body = "EMAIL_PROFILE_UPDATED_BODY"; + break; + default: + subject = "EMAIL_USER_UPDATED_OWN_PASSWORD_SUBJECT"; + body = "EMAIL_USER_UPDATED_OWN_PASSWORD_BODY"; + break; + } + + subject = Localize.GetSystemMessage(locale, settings, subject, user, Localize.GlobalResourceFile, custom, "", settings.AdministratorId); + body = Localize.GetSystemMessage(locale, settings, body, user, Localize.GlobalResourceFile, custom, "", settings.AdministratorId); + + SendEmail(settings.Email, UserController.GetUserById(settings.PortalId, toUser).Email, subject, body); + + return Null.NullString; + } + + /// ----------------------------------------------------------------------------- + /// + /// Send a simple email. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// [cnurse] 09/29/2005 Moved to Mail class + /// + /// ----------------------------------------------------------------------------- + public static string SendMail(string mailFrom, string mailTo, string bcc, string subject, string body, string attachment, string bodyType, string smtpServer, string smtpAuthentication, + string smtpUsername, string smtpPassword) + { + MailFormat bodyFormat = MailFormat.Text; + if (!String.IsNullOrEmpty(bodyType)) + { + switch (bodyType.ToLower()) + { + case "html": + bodyFormat = MailFormat.Html; + break; + case "text": + bodyFormat = MailFormat.Text; + break; + } + } + return SendMail(mailFrom, mailTo, "", bcc, MailPriority.Normal, subject, bodyFormat, Encoding.UTF8, body, attachment, smtpServer, smtpAuthentication, smtpUsername, smtpPassword); + } + + /// ----------------------------------------------------------------------------- + /// Send a simple email. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// [Nik Kalyani] 10/15/2004 Replaced brackets in member names + /// [cnurse] 09/29/2005 Moved to Mail class + /// + /// ----------------------------------------------------------------------------- + public static string SendMail(string mailFrom, string mailTo, string cc, string bcc, MailPriority priority, string subject, MailFormat bodyFormat, Encoding bodyEncoding, string body, + string attachment, string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword) + { + return SendMail(mailFrom, mailTo, cc, bcc, priority, subject, bodyFormat, bodyEncoding, body, attachment, smtpServer, smtpAuthentication, smtpUsername, smtpPassword, Host.EnableSMTPSSL); + } + + public static string SendMail(string mailFrom, string mailTo, string cc, string bcc, MailPriority priority, string subject, MailFormat bodyFormat, Encoding bodyEncoding, string body, + string attachment, string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + return SendMail(mailFrom, + mailTo, + cc, + bcc, + mailFrom, + priority, + subject, + bodyFormat, + bodyEncoding, + body, + attachment.Split('|'), + smtpServer, + smtpAuthentication, + smtpUsername, + smtpPassword, + smtpEnableSSL); + } + + public static string SendMail(string mailFrom, string mailTo, string cc, string bcc, MailPriority priority, string subject, MailFormat bodyFormat, Encoding bodyEncoding, string body, + string[] attachments, string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + return SendMail(mailFrom, + mailTo, + cc, + bcc, + mailFrom, + priority, + subject, + bodyFormat, + bodyEncoding, + body, + attachments, + smtpServer, + smtpAuthentication, + smtpUsername, + smtpPassword, + smtpEnableSSL); + } + + public static string SendMail(string mailFrom, string mailTo, string cc, string bcc, string replyTo, MailPriority priority, string subject, MailFormat bodyFormat, Encoding bodyEncoding, + string body, string[] attachments, string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + var attachmentList = (from attachment in attachments + where !String.IsNullOrEmpty(attachment) + select new Attachment(attachment)) + .ToList(); + + return SendMail(mailFrom, + mailTo, + cc, + bcc, + replyTo, + priority, + subject, + bodyFormat, + bodyEncoding, + body, + attachmentList, + smtpServer, + smtpAuthentication, + smtpUsername, + smtpPassword, + smtpEnableSSL); + } + + public static string SendMail(string mailFrom, string mailTo, string cc, string bcc, string replyTo, MailPriority priority, string subject, MailFormat bodyFormat, Encoding bodyEncoding, + string body, List attachments, string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + //SMTP server configuration + if (string.IsNullOrEmpty(smtpServer) && !string.IsNullOrEmpty(Host.SMTPServer)) + { + smtpServer = Host.SMTPServer; + } + if (string.IsNullOrEmpty(smtpAuthentication) && !string.IsNullOrEmpty(Host.SMTPAuthentication)) + { + smtpAuthentication = Host.SMTPAuthentication; + } + if (string.IsNullOrEmpty(smtpUsername) && !string.IsNullOrEmpty(Host.SMTPUsername)) + { + smtpUsername = Host.SMTPUsername; + } + if (string.IsNullOrEmpty(smtpPassword) && !string.IsNullOrEmpty(Host.SMTPPassword)) + { + smtpPassword = Host.SMTPPassword; + } + + //translate semi-colon delimiters to commas as ASP.NET 2.0 does not support semi-colons + mailTo = mailTo.Replace(";", ","); + cc = cc.Replace(";", ","); + bcc = bcc.Replace(";", ","); + + MailMessage mailMessage = null; + mailMessage = new MailMessage { From = new MailAddress(mailFrom) }; + if (!String.IsNullOrEmpty(mailTo)) + { + mailMessage.To.Add(mailTo); + } + if (!String.IsNullOrEmpty(cc)) + { + mailMessage.CC.Add(cc); + } + if (!String.IsNullOrEmpty(bcc)) + { + mailMessage.Bcc.Add(bcc); + } + if (replyTo != string.Empty) + { + mailMessage.ReplyToList.Add(new MailAddress(replyTo)); + } + + return SendMailInternal(mailMessage, subject, body, priority, bodyFormat, bodyEncoding, + attachments, smtpServer, smtpAuthentication, smtpUsername,smtpPassword, smtpEnableSSL); + } + + #endregion + + #region Obsolete Methods + + [Obsolete("Obsoleted in DotNetNuke 5.5. Use DotNetNuke.Common.Utilities.HtmlUtils.IsHtml()")] + public static bool IsHTMLMail(string Body) + { + return HtmlUtils.IsHtml(Body); + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Mail/MailFormat.cs b/DNN Platform/Library/Services/Mail/MailFormat.cs new file mode 100644 index 00000000000..7f7479d4e45 --- /dev/null +++ b/DNN Platform/Library/Services/Mail/MailFormat.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Mail +{ + public enum MailFormat + { + Text, + Html + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mail/MailPriority.cs b/DNN Platform/Library/Services/Mail/MailPriority.cs new file mode 100644 index 00000000000..57c11689540 --- /dev/null +++ b/DNN Platform/Library/Services/Mail/MailPriority.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Mail +{ + public enum MailPriority + { + Normal, + Low, + High + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mail/MessageType.cs b/DNN Platform/Library/Services/Mail/MessageType.cs new file mode 100644 index 00000000000..e748a873fa6 --- /dev/null +++ b/DNN Platform/Library/Services/Mail/MessageType.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Mail +{ + public enum MessageType + { + PasswordReminder, + ProfileUpdated, + UserRegistrationAdmin, + UserRegistrationPrivate, + UserRegistrationPublic, + UserRegistrationVerified, + UserUpdatedOwnPassword + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mail/SendTokenizedBulkEmail.cs b/DNN Platform/Library/Services/Mail/SendTokenizedBulkEmail.cs new file mode 100644 index 00000000000..091ed8d4f11 --- /dev/null +++ b/DNN Platform/Library/Services/Mail/SendTokenizedBulkEmail.cs @@ -0,0 +1,686 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net.Mail; +using System.Net.Mime; +using System.Text; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Roles; +using DotNetNuke.Security.Roles.Internal; +using DotNetNuke.Services.Messaging.Data; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.Services.Mail +{ + /// ----------------------------------------------------------------------------- + /// + /// SendTokenizedBulkEmail Class is a class to manage the sending of bulk mails + /// that contains tokens, which might be replaced with individual user properties + /// + /// + /// + /// + /// [sleupold] 8/15/2007 created to support tokens and localisation + /// [sleupold] 9/09/2007 refactored interface for enhanced type safety + /// + /// ----------------------------------------------------------------------------- + public class SendTokenizedBulkEmail : IDisposable + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SendTokenizedBulkEmail)); + #region AddressMethods enum + + /// + /// Addressing Methods (personalized or hidden) + /// + // ReSharper disable InconsistentNaming + // Existing public API + public enum AddressMethods + { + + Send_TO = 1, + Send_BCC = 2, + Send_Relay = 3 + } + // ReSharper restore InconsistentNaming + + #endregion + + #region "Private Members" + + private readonly List _addressedRoles = new List(); + private readonly List _addressedUsers = new List(); + private readonly List _attachments = new List(); + private UserInfo _replyToUser; + private bool _smtpEnableSSL; + private TokenReplace _tokenReplace; + private PortalSettings _portalSettings; + private UserInfo _sendingUser; + private string _body = ""; + private string _confirmBodyHTML; + private string _confirmBodyText; + private string _confirmSubject; + private string _noError; + private string _relayEmail; + private string _smtpAuthenticationMethod = ""; + private string _smtpPassword = ""; + private string _smtpServer = ""; + private string _smtpUsername = ""; + private string _strSenderLanguage; + private bool _isDisposed; + + #endregion + + #region "Constructs" + + public SendTokenizedBulkEmail() + { + ReportRecipients = true; + AddressMethod = AddressMethods.Send_TO; + BodyFormat = MailFormat.Text; + Subject = ""; + Priority = MailPriority.Normal; + Initialize(); + } + + public SendTokenizedBulkEmail(List addressedRoles, List addressedUsers, bool removeDuplicates, string subject, string body) + { + ReportRecipients = true; + AddressMethod = AddressMethods.Send_TO; + BodyFormat = MailFormat.Text; + Priority = MailPriority.Normal; + _addressedRoles = addressedRoles; + _addressedUsers = addressedUsers; + RemoveDuplicates = removeDuplicates; + Subject = subject; + Body = body; + SuppressTokenReplace = SuppressTokenReplace; + Initialize(); + } + + #endregion + + #region "Public Properties" + + /// + /// Priority of emails to be sent + /// + public MailPriority Priority { get; set; } + + /// + /// Subject of the emails to be sent + /// + /// may contain tokens + public string Subject { get; set; } + + /// + /// body text of the email to be sent + /// + /// may contain HTML tags and tokens. Side effect: sets BodyFormat autmatically + public string Body + { + get + { + return _body; + } + set + { + _body = value; + BodyFormat = HtmlUtils.IsHtml(_body) ? MailFormat.Html : MailFormat.Text; + } + } + + /// format of body text for the email to be sent. + /// by default activated, if tokens are found in Body and subject. + public MailFormat BodyFormat { get; set; } + + /// address method for the email to be sent (TO or BCC) + /// TO is default value + public AddressMethods AddressMethod { get; set; } + + /// portal alias http path to be used for links to images, ... + public string PortalAlias { get; set; } + + /// UserInfo of the user sending the mail + /// if not set explicitely, currentuser will be used + public UserInfo SendingUser + { + get + { + return _sendingUser; + } + set + { + _sendingUser = value; + if (_sendingUser.Profile.PreferredLocale != null) + { + _strSenderLanguage = _sendingUser.Profile.PreferredLocale; + } + else + { + PortalSettings portalSettings = PortalController.GetCurrentPortalSettings(); + _strSenderLanguage = portalSettings.DefaultLanguage; + } + } + } + + /// email of the user to be shown in the mail as replyTo address + /// if not set explicitely, sendingUser will be used + public UserInfo ReplyTo + { + get + { + return _replyToUser ?? SendingUser; + } + set + { + _replyToUser = value; + } + } + + /// shall duplicate email addresses be ignored? (default value: false) + /// Duplicate Users (e.g. from multiple role selections) will always be ignored. + public bool RemoveDuplicates { get; set; } + + /// Shall automatic TokenReplace be prohibited? + /// default value: false + public bool SuppressTokenReplace { get; set; } + + /// Shall List of recipients appended to confirmation report? + /// enabled by default. + public bool ReportRecipients { get; set; } + + public string RelayEmailAddress + { + get + { + return AddressMethod == AddressMethods.Send_Relay ? _relayEmail : string.Empty; + } + set + { + _relayEmail = value; + } + } + + public string[] LanguageFilter { get; set; } + + #endregion + + #region "Private Methods" + + /// internal method to initialize used objects, depending on parameters of construct method + private void Initialize() + { + _portalSettings = PortalController.GetCurrentPortalSettings(); + PortalAlias = _portalSettings.PortalAlias.HTTPAlias; + SendingUser = (UserInfo) HttpContext.Current.Items["UserInfo"]; + _tokenReplace = new TokenReplace(); + _confirmBodyHTML = Localization.Localization.GetString("EMAIL_BulkMailConf_Html_Body", Localization.Localization.GlobalResourceFile, _strSenderLanguage); + _confirmBodyText = Localization.Localization.GetString("EMAIL_BulkMailConf_Text_Body", Localization.Localization.GlobalResourceFile, _strSenderLanguage); + _confirmSubject = Localization.Localization.GetString("EMAIL_BulkMailConf_Subject", Localization.Localization.GlobalResourceFile, _strSenderLanguage); + _noError = Localization.Localization.GetString("NoErrorsSending", Localization.Localization.GlobalResourceFile, _strSenderLanguage); + _smtpEnableSSL = Host.EnableSMTPSSL; + } + + /// Send bulkmail confirmation to admin + /// number of email recipients + /// number of messages sent, -1 if not determinable + /// number of emails not sent + /// Subject of BulkMail sent (to be used as reference) + /// date/time, sendout started + /// mail error texts + /// List of recipients as formatted string + /// + private void SendConfirmationMail(int numRecipients, int numMessages, int numErrors, string subject, string startedAt, string mailErrors, string recipientList) + { + //send confirmation, use resource string like: + //Operation started at: [Custom:0]
    + //EmailRecipients: [Custom:1] + //Operation Completed: [Custom:3]
    + //Number of Errors: [Custom:4]
    + //Error Report:
    + //[Custom:5] + //-------------------------------------- + //Recipients: + //[custom:6] + var parameters = new ArrayList + { + startedAt, + numRecipients.ToString(CultureInfo.InvariantCulture), + numMessages >= 0 ? numMessages.ToString(CultureInfo.InvariantCulture) : "***", + DateTime.Now.ToString(CultureInfo.InvariantCulture), + numErrors > 0 ? numErrors.ToString(CultureInfo.InvariantCulture) : "", + mailErrors != string.Empty ? mailErrors : _noError, + ReportRecipients ? recipientList : "" + }; + _tokenReplace.User = _sendingUser; + string body = _tokenReplace.ReplaceEnvironmentTokens(BodyFormat == MailFormat.Html ? _confirmBodyHTML : _confirmBodyText, parameters, "Custom"); + string strSubject = string.Format(_confirmSubject, subject); + if (!SuppressTokenReplace) + { + strSubject = _tokenReplace.ReplaceEnvironmentTokens(strSubject); + } + var message = new Message {FromUserID = _sendingUser.UserID, ToUserID = _sendingUser.UserID, Subject = strSubject, Body = body, Status = MessageStatusType.Unread}; + + Mail.SendEmail(_sendingUser.Email, _sendingUser.Email, message.Subject, message.Body); + } + + /// check, if the user's language matches the current language filter + /// Language of the user + /// userlanguage matches current languageFilter + /// if filter not set, true is returned + private bool MatchLanguageFilter(string userLanguage) + { + if (LanguageFilter == null || LanguageFilter.Length == 0) + { + return true; + } + + if(string.IsNullOrEmpty(userLanguage)) + { + userLanguage = _portalSettings.DefaultLanguage; + } + + return LanguageFilter.Any(s => userLanguage.ToLowerInvariant().StartsWith(s.ToLowerInvariant())); + } + + /// add a user to the userlist, if it is not already in there + /// user to add + /// list of key (either email addresses or userid's) + /// List of users + /// for use by Recipients method only + private void ConditionallyAddUser(UserInfo user, ref List keyList, ref List userList) + { + if (((user.UserID <= 0 || user.Membership.Approved) && user.Email != string.Empty) && MatchLanguageFilter(user.Profile.PreferredLocale)) + { + string key; + if (RemoveDuplicates || user.UserID == Null.NullInteger) + { + key = user.Email; + } + else + { + key = user.UserID.ToString(CultureInfo.InvariantCulture); + } + if (key != string.Empty && !keyList.Contains(key)) + { + userList.Add(user); + keyList.Add(key); + } + } + } + + private List LoadAttachments() + { + var attachments = new List(); + foreach (var attachment in _attachments) + { + var buffer = new byte[4096]; + var memoryStream = new MemoryStream(); + while (true) + { + var read = attachment.ContentStream.Read(buffer, 0, 4096); + if (read <= 0) + { + break; + } + memoryStream.Write(buffer, 0, read); + } + + var newAttachment = new Attachment(memoryStream, attachment.ContentType); + newAttachment.ContentStream.Position = 0; + attachments.Add(newAttachment); + //reset original position + attachment.ContentStream.Position = 0; + } + + return attachments; + } + + #endregion + + #region "Public Methods" + + /// Specify SMTP server to be used + /// name of the SMTP server + /// authentication string (0: anonymous, 1: basic, 2: NTLM) + /// username to log in SMTP server + /// password to log in SMTP server + /// SSL used to connect tp SMTP server + /// always true + /// if not called, values will be taken from host settings + public bool SetSMTPServer(string smtpServer, string smtpAuthentication, string smtpUsername, string smtpPassword, bool smtpEnableSSL) + { + EnsureNotDisposed(); + + _smtpServer = smtpServer; + _smtpAuthenticationMethod = smtpAuthentication; + _smtpUsername = smtpUsername; + _smtpPassword = smtpPassword; + _smtpEnableSSL = smtpEnableSSL; + return true; + } + + /// Add a single attachment file to the email + /// path to file to attach + /// only local stored files can be added with a path + public void AddAttachment(string localPath) + { + EnsureNotDisposed(); + _attachments.Add(new Attachment(localPath)); + } + + public void AddAttachment(Stream contentStream, ContentType contentType) + { + EnsureNotDisposed(); + _attachments.Add(new Attachment(contentStream, contentType)); + } + + /// Add a single recipient + /// userinfo of user to add + /// emaiol will be used for addressing, other properties might be used for TokenReplace + public void AddAddressedUser(UserInfo recipient) + { + EnsureNotDisposed(); + _addressedUsers.Add(recipient); + } + + /// Add all members of a role to recipient list + /// name of a role, whose members shall be added to recipients + /// emaiol will be used for addressing, other properties might be used for TokenReplace + public void AddAddressedRole(string roleName) + { + EnsureNotDisposed(); + _addressedRoles.Add(roleName); + } + + /// All bulk mail recipients, derived from role names and individual adressees + /// List of userInfo objects, who receive the bulk mail + /// user.Email used for sending, other properties might be used for TokenReplace + public List Recipients() + { + EnsureNotDisposed(); + + var userList = new List(); + var keyList = new List(); + var roleController = new RoleController(); + + foreach (string roleName in _addressedRoles) + { + string role = roleName; + var roleInfo = TestableRoleController.Instance.GetRole(_portalSettings.PortalId, r => r.RoleName == role); + + foreach (UserInfo objUser in roleController.GetUsersByRoleName(_portalSettings.PortalId, roleName)) + { + UserInfo user = objUser; + ProfileController.GetUserProfile(ref user); + var userRole = roleController.GetUserRole(_portalSettings.PortalId, objUser.UserID, roleInfo.RoleID); + //only add if user role has not expired and effectivedate has been passed + if ((userRole.EffectiveDate <= DateTime.Now || Null.IsNull(userRole.EffectiveDate)) && (userRole.ExpiryDate >= DateTime.Now || Null.IsNull(userRole.ExpiryDate))) + { + ConditionallyAddUser(objUser, ref keyList, ref userList); + } + } + } + + foreach (UserInfo objUser in _addressedUsers) + { + ConditionallyAddUser(objUser, ref keyList, ref userList); + } + + return userList; + } + + /// Send bulkmail to all recipients according to settings + /// Number of emails sent, null.integer if not determinable + /// Detailed status report is sent by email to sending user + public int SendMails() + { + EnsureNotDisposed(); + + int recipients = 0; + int messagesSent = 0; + int errors = 0; + + try + { + //send to recipients + string body = _body; + if (BodyFormat == MailFormat.Html) //Add Base Href for any images inserted in to the email. + { + var host = PortalAlias.Contains("/") ? PortalAlias.Substring(0, PortalAlias.IndexOf('/')) : PortalAlias; + body = "" + Subject + "" + body + ""; + } + string subject = Subject; + string startedAt = DateTime.Now.ToString(CultureInfo.InvariantCulture); + + bool replaceTokens = !SuppressTokenReplace && (_tokenReplace.ContainsTokens(Subject) || _tokenReplace.ContainsTokens(_body)); + bool individualSubj = false; + bool individualBody = false; + + var mailErrors = new StringBuilder(); + var mailRecipients = new StringBuilder(); + + switch (AddressMethod) + { + case AddressMethods.Send_TO: + case AddressMethods.Send_Relay: + //optimization: + if (replaceTokens) + { + individualBody = (_tokenReplace.Cacheability(_body) == CacheLevel.notCacheable); + individualSubj = (_tokenReplace.Cacheability(Subject) == CacheLevel.notCacheable); + if (!individualBody) + { + body = _tokenReplace.ReplaceEnvironmentTokens(body); + } + if (!individualSubj) + { + subject = _tokenReplace.ReplaceEnvironmentTokens(subject); + } + } + foreach (UserInfo user in Recipients()) + { + recipients += 1; + if (individualBody || individualSubj) + { + _tokenReplace.User = user; + _tokenReplace.AccessingUser = user; + if (individualBody) + { + body = _tokenReplace.ReplaceEnvironmentTokens(_body); + } + if (individualSubj) + { + subject = _tokenReplace.ReplaceEnvironmentTokens(Subject); + } + } + string recipient = AddressMethod == AddressMethods.Send_TO ? user.Email : RelayEmailAddress; + + string mailError = Mail.SendMail(_sendingUser.Email, + recipient, + "", + "", + ReplyTo.Email, + Priority, + subject, + BodyFormat, + Encoding.UTF8, + body, + LoadAttachments(), + _smtpServer, + _smtpAuthenticationMethod, + _smtpUsername, + _smtpPassword, + _smtpEnableSSL); + if (!string.IsNullOrEmpty(mailError)) + { + mailErrors.Append(mailError); + mailErrors.AppendLine(); + errors += 1; + } + else + { + mailRecipients.Append(user.Email); + mailRecipients.Append(BodyFormat == MailFormat.Html ? "
    " : Environment.NewLine); + messagesSent += 1; + } + } + + break; + case AddressMethods.Send_BCC: + var distributionList = new StringBuilder(); + messagesSent = Null.NullInteger; + foreach (UserInfo user in Recipients()) + { + recipients += 1; + distributionList.Append(user.Email + "; "); + mailRecipients.Append(user.Email); + mailRecipients.Append(BodyFormat == MailFormat.Html ? "
    " : Environment.NewLine); + } + + if (distributionList.Length > 2) + { + if (replaceTokens) + { + //no access to User properties possible! + var tr = new TokenReplace(Scope.Configuration); + body = tr.ReplaceEnvironmentTokens(_body); + subject = tr.ReplaceEnvironmentTokens(Subject); + } + else + { + body = _body; + subject = Subject; + } + string mailError = Mail.SendMail(_sendingUser.Email, + _sendingUser.Email, + "", + distributionList.ToString(0, distributionList.Length - 2), + ReplyTo.Email, + Priority, + subject, + BodyFormat, + Encoding.UTF8, + body, + LoadAttachments(), + _smtpServer, + _smtpAuthenticationMethod, + _smtpUsername, + _smtpPassword, + _smtpEnableSSL); + if (mailError == string.Empty) + { + messagesSent = 1; + } + else + { + mailErrors.Append(mailError); + errors += 1; + } + } + break; + } + if (mailErrors.Length > 0) + { + mailRecipients = new StringBuilder(); + } + SendConfirmationMail(recipients, messagesSent, errors, subject, startedAt, mailErrors.ToString(), mailRecipients.ToString()); + } + catch (Exception exc) //send mail failure + { + Logger.Error(exc); + + Debug.Write(exc.Message); + } + finally + { + foreach (var attachment in _attachments) + { + attachment.Dispose(); + } + } + return messagesSent; + } + + /// Wrapper for Function SendMails + public void Send() + { + EnsureNotDisposed(); + SendMails(); + } + + #endregion + + private void EnsureNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("SharedDictionary"); + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + //get rid of managed resources + foreach (Attachment attachment in _attachments) + { + attachment.Dispose(); + _isDisposed = true; + } + } + // get rid of unmanaged resources + } + } + + ~SendTokenizedBulkEmail() + { + Dispose(false); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Messaging/Data/IMessagingDataService.cs b/DNN Platform/Library/Services/Messaging/Data/IMessagingDataService.cs new file mode 100644 index 00000000000..ca292754ef2 --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/Data/IMessagingDataService.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +#endregion + +namespace DotNetNuke.Services.Messaging.Data +{ + public interface IMessagingDataService + { + IDataReader GetMessageByID(int MessageID); + + IDataReader GetUserInbox(int PortalID, int UserID, int PageNumber, int PageSize); + + int GetInboxCount(int PortalID, int UserID); + + long SaveMessage(Message objMessaging); + + int GetNewMessageCount(int PortalID, int UserID); + + IDataReader GetNextMessageForDispatch(Guid SchedulerInstance); + + void MarkMessageAsDispatched(int MessageID); + + void UpdateMessage(Message message); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Messaging/Data/Message.cs b/DNN Platform/Library/Services/Messaging/Data/Message.cs new file mode 100644 index 00000000000..ae80df19431 --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/Data/Message.cs @@ -0,0 +1,374 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.Messaging.Data +{ + /// ----------------------------------------------------------------------------- + /// + /// The Info class for Messaging + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class Message : IHydratable + { + private string _Body; + private Guid _Conversation; + private bool _EmailSent; + private int _FromUserID; + private string _FromUserName; + private DateTime _MessageDate; + private int _MessageID; + private int _PortalID; + private int _ReplyTo; + private MessageStatusType _Status; + private string _Subject; + private int _ToRoleId; + private int _ToUserID; + private string _ToUserName; + + private bool _allowReply; + private bool _skipInbox; + + #region "Constructors" + + public Message() + { + Conversation = Guid.Empty; + Status = MessageStatusType.Draft; + MessageDate = DateTime.Now; + } + + #endregion + + #region "Public Properties" + + private Guid _EmailSchedulerInstance; + private DateTime _EmailSentDate; + + public string FromUserName + { + get + { + return _FromUserName; + } + private set + { + _FromUserName = value; + } + } + + + public int FromUserID + { + get + { + return _FromUserID; + } + set + { + _FromUserID = value; + } + } + + + public int ToRoleID + { + get + { + return _ToRoleId; + } + set + { + _ToRoleId = value; + } + } + + + public bool AllowReply + { + get + { + return _allowReply; + } + set + { + _allowReply = value; + } + } + + + public bool SkipInbox + { + get + { + return _skipInbox; + } + set + { + _skipInbox = value; + } + } + + public bool EmailSent + { + get + { + return _EmailSent; + } + set + { + _EmailSent = value; + } + } + + + public string Body + { + get + { + return _Body; + } + set + { + _Body = value; + } + } + + public DateTime MessageDate + { + get + { + return _MessageDate; + } + set + { + _MessageDate = value; + } + } + + public Guid Conversation + { + get + { + return _Conversation; + } + set + { + _Conversation = value; + } + } + + public int MessageID + { + get + { + return _MessageID; + } + private set + { + _MessageID = value; + } + } + + + public int PortalID + { + get + { + return _PortalID; + } + set + { + _PortalID = value; + } + } + + public int ReplyTo + { + get + { + return _ReplyTo; + } + private set + { + _ReplyTo = value; + } + } + + public MessageStatusType Status + { + get + { + return _Status; + } + set + { + _Status = value; + } + } + + public string Subject + { + get + { + var ps = new PortalSecurity(); + return ps.InputFilter(_Subject, PortalSecurity.FilterFlag.NoMarkup); + } + set + { + var ps = new PortalSecurity(); + ps.InputFilter(value, PortalSecurity.FilterFlag.NoMarkup); + _Subject = ps.InputFilter(value, PortalSecurity.FilterFlag.NoMarkup); + } + } + + + public int ToUserID + { + get + { + return _ToUserID; + } + set + { + _ToUserID = value; + } + } + + public string ToUserName + { + get + { + return _ToUserName; + } + private set + { + _ToUserName = value; + } + } + + + public DateTime EmailSentDate + { + get + { + return _EmailSentDate; + } + private set + { + _EmailSentDate = value; + } + } + + + public Guid EmailSchedulerInstance + { + get + { + return _EmailSchedulerInstance; + } + private set + { + _EmailSchedulerInstance = value; + } + } + + #endregion + + #region "Public Methods" + + public Message GetReplyMessage() + { + var message = new Message(); + message.AllowReply = AllowReply; + message.Body = string.Format("


    On {0} {1} wrote ", MessageDate, FromUserName) + Body; + message.Conversation = Conversation; + message.FromUserID = ToUserID; + message.ToUserID = FromUserID; + message.ToUserName = FromUserName; + message.PortalID = PortalID; + message.ReplyTo = MessageID; + message.SkipInbox = SkipInbox; + message.Subject = "RE:" + Subject; + + return message; + } + + #endregion + + #region "IHydratable Implementation" + + public void Fill(IDataReader dr) + { + MessageID = Null.SetNullInteger(dr["MessageID"]); + PortalID = Null.SetNullInteger(dr["PortalID"]); + FromUserID = Null.SetNullInteger(dr["FromUserID"]); + FromUserName = Null.SetNullString(dr["FromUserName"]); + ToUserID = Null.SetNullInteger(dr["ToUserID"]); + //'_ToUserName = Null.SetNullString(dr.Item("ToUserName")) + ReplyTo = Null.SetNullInteger(dr["ReplyTo"]); + Status = (MessageStatusType) Enum.Parse(typeof (MessageStatusType), Null.SetNullString(dr["Status"])); + Body = Null.SetNullString(dr["Body"]); + Subject = Null.SetNullString(dr["Subject"]); + MessageDate = Null.SetNullDateTime(dr["Date"]); + ToRoleID = Null.SetNullInteger(dr["ToRoleID"]); + AllowReply = Null.SetNullBoolean(dr["AllowReply"]); + SkipInbox = Null.SetNullBoolean(dr["SkipPortal"]); + EmailSent = Null.SetNullBoolean(dr["EmailSent"]); + ToUserName = Null.SetNullString(dr["ToUserName"]); + string g = Null.SetNullString(dr["Conversation"]); + EmailSentDate = Null.SetNullDateTime(dr["EmailSentDate"]); + EmailSchedulerInstance = Null.SetNullGuid(dr["EmailSchedulerInstance"]); + Conversation = Null.SetNullGuid(dr["Conversation"]); + + + //'Conversation = New Guid(g) + } + + public int KeyID + { + get + { + return MessageID; + } + set + { + MessageID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Messaging/Data/MessageStatusType.cs b/DNN Platform/Library/Services/Messaging/Data/MessageStatusType.cs new file mode 100644 index 00000000000..1d5d69f6962 --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/Data/MessageStatusType.cs @@ -0,0 +1,30 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Messaging.Data +{ + public enum MessageStatusType + { + Draft = 0, + Unread = 1, + Read = 2, + Deleted = 3 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Messaging/Data/MessagingDataService.cs b/DNN Platform/Library/Services/Messaging/Data/MessagingDataService.cs new file mode 100644 index 00000000000..777765c78ea --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/Data/MessagingDataService.cs @@ -0,0 +1,102 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; + +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Messaging.Data +{ + public class MessagingDataService : IMessagingDataService + { + private readonly DataProvider provider = DataProvider.Instance(); + + #region IMessagingDataService Members + + public IDataReader GetMessageByID(int messageId) + { + return provider.ExecuteReader("Messaging_GetMessage", messageId); + } + + public IDataReader GetUserInbox(int PortalID, int UserID, int PageNumber, int PageSize) + { + return provider.ExecuteReader("Messaging_GetInbox", PortalID, UserID, PageNumber, PageSize); + } + + public int GetInboxCount(int PortalID, int UserID) + { + return provider.ExecuteScalar("Messaging_GetInboxCount", PortalID, UserID); + } + + public long SaveMessage(Message objMessaging) + { + return provider.ExecuteScalar("Messaging_Save_Message", + objMessaging.PortalID, + objMessaging.FromUserID, + objMessaging.ToUserID, + objMessaging.ToRoleID, + (int) objMessaging.Status, + objMessaging.Subject, + objMessaging.Body, + objMessaging.MessageDate, + objMessaging.Conversation, + objMessaging.ReplyTo, + objMessaging.AllowReply, + objMessaging.SkipInbox); + } + + public int GetNewMessageCount(int PortalID, int UserID) + { + return provider.ExecuteScalar("Messaging_GetNewMessageCount", PortalID, UserID); + } + + public IDataReader GetNextMessageForDispatch(Guid SchedulerInstance) + { + return provider.ExecuteReader("Messaging_GetNextMessageForDispatch", SchedulerInstance); + } + + public void MarkMessageAsDispatched(int MessageID) + { + provider.ExecuteNonQuery("Messaging_MarkMessageAsDispatched", MessageID); + } + + public void UpdateMessage(Message message) + { + provider.ExecuteNonQuery("Messaging_UpdateMessage", + message.MessageID, + message.ToUserID, + message.ToRoleID, + (int) message.Status, + message.Subject, + message.Body, + message.MessageDate, + message.ReplyTo, + message.AllowReply, + message.SkipInbox); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Messaging/IMessagingController.cs b/DNN Platform/Library/Services/Messaging/IMessagingController.cs new file mode 100644 index 00000000000..a2ea5087d06 --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/IMessagingController.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Messaging.Data; + +#endregion + +namespace DotNetNuke.Services.Messaging +{ + public interface IMessagingController + { + Message GetMessageByID(int PortalID, int UserID, int MessageID); + + List GetUserInbox(int PortalID, int UserID, int PageNumber, int PageSize); + + int GetInboxCount(int PortalID, int UserID); + + int GetNewMessageCount(int PortalID, int UserID); + + Message GetNextMessageForDispatch(Guid SchedulerInstance); + + void SaveMessage(Message objMessage); + + void UpdateMessage(Message objMessage); + + void MarkMessageAsDispatched(int MessageID); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Messaging/MessagingController.cs b/DNN Platform/Library/Services/Messaging/MessagingController.cs new file mode 100644 index 00000000000..ff34603aca5 --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/MessagingController.cs @@ -0,0 +1,247 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Messaging.Data; +using DotNetNuke.Services.Social.Messaging; +using DotNetNuke.Services.Social.Messaging.Internal; + +using Message = DotNetNuke.Services.Messaging.Data.Message; + +#endregion + +namespace DotNetNuke.Services.Messaging +{ + /// ----------------------------------------------------------------------------- + /// + /// The Controller class for Messaging + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 6.2.0, please use DotNetNuke.Services.Social.Messaging.MessagingController")] + public class MessagingController : IMessagingController + { + private static TabInfo _MessagingPage; + + #region "Constructors" + + public MessagingController() + : this(GetDataService()) + { + } + + public MessagingController(IMessagingDataService dataService) + { + _DataService = dataService; + } + + #endregion + + #region "Private Shared Methods" + + private static IMessagingDataService GetDataService() + { + var ds = ComponentFactory.GetComponent(); + + if (ds == null) + { + ds = new MessagingDataService(); + ComponentFactory.RegisterComponentInstance(ds); + } + return ds; + } + + #endregion + + #region "Obsolete Methods" + + [Obsolete("Deprecated in DNN 6.2.0")] + public static string DefaultMessagingURL(string ModuleFriendlyName) + { + TabInfo page = MessagingPage(ModuleFriendlyName); + if (page != null) + { + return MessagingPage(ModuleFriendlyName).FullUrl; + } + else + { + return null; + } + } + + [Obsolete("Deprecated in DNN 6.2.0")] + public static TabInfo MessagingPage(string ModuleFriendlyName) + { + if (((_MessagingPage != null))) + { + return _MessagingPage; + } + + var mc = new ModuleController(); + ModuleInfo md = mc.GetModuleByDefinition(PortalSettings.Current.PortalId, ModuleFriendlyName); + if ((md != null)) + { + ArrayList a = mc.GetModuleTabs(md.ModuleID); + if ((a != null)) + { + var mi = a[0] as ModuleInfo; + if ((mi != null)) + { + var tc = new TabController(); + _MessagingPage = tc.GetTab(mi.TabID, PortalSettings.Current.PortalId, false); + } + } + } + + return _MessagingPage; + } + + [Obsolete("Deprecated in 6.2.0 - use DotNetNuke.Services.Social.Messaging.MessagingController.Instance(messageId)")] + public Message GetMessageByID(int PortalID, int UserID, int messageId) + { + var coreMessage = InternalMessagingController.Instance.GetMessage(messageId); + var coreMessageRecipient = InternalMessagingController.Instance.GetMessageRecipient(messageId, UserID); + return ConvertCoreMessageToServicesMessage(PortalID, UserID, coreMessageRecipient, coreMessage); + } + + + + [Obsolete("Deprecated in 6.2.0")] + public List GetUserInbox(int PortalID, int UserID, int PageNumber, int PageSize) + { + return CBO.FillCollection(_DataService.GetUserInbox(PortalID, UserID, PageNumber, PageSize)); + } + + [Obsolete("Deprecated in 6.2.0 - use DotNetNuke.Services.Social.Messaging.MessagingController.Instance.GetMessage(messageId)")] + public int GetInboxCount(int PortalID, int UserID) + { + return InternalMessagingController.Instance.CountConversations(UserID, PortalID); + } + + [Obsolete("Deprecated in 6.2.0 - use InternalMessagingController.Instance.GetMessage(messageId)")] + public int GetNewMessageCount(int PortalID, int UserID) + { + return InternalMessagingController.Instance.CountUnreadMessages(UserID, PortalID); + } + + [Obsolete("Deprecated in 6.2.0 - use InternalMessagingController.Instance.GetMessage(messageId)")] + public Message GetNextMessageForDispatch(Guid SchedulerInstance) + { + //does not need to run as scheduled task name was updated + return null; + } + + [Obsolete("Deprecated in 6.2.0 - use InternalMessagingController.Instance.GetMessage(messageId)")] + public void SaveMessage(Message message) + { + if ((PortalSettings.Current != null)) + { + message.PortalID = PortalSettings.Current.PortalId; + } + + if ((message.Conversation == null || message.Conversation == Guid.Empty)) + { + message.Conversation = Guid.NewGuid(); + } + + var users = new List(); + + var userController = new UserController(); + users.Add(userController.GetUser(message.PortalID, message.ToUserID)); + + List emptyRoles = null; + List files = null; + + var coremessage = new Social.Messaging.Message {Body = message.Body, Subject = message.Subject}; + + + Social.Messaging.MessagingController.Instance.SendMessage(coremessage, emptyRoles, users, files); + } + + [Obsolete("Deprecated in 6.2.0 - use InternalMessagingController.Instance.GetMessage(messageId)")] + public void UpdateMessage(Message message) + { + var user = UserController.GetCurrentUserInfo().UserID; + switch (message.Status) + { + case MessageStatusType.Unread: + InternalMessagingController.Instance.MarkUnRead(message.MessageID, user); + break; + case MessageStatusType.Draft: + //no equivalent + break; + case MessageStatusType.Deleted: + InternalMessagingController.Instance.MarkArchived(message.MessageID, user); + break; + case MessageStatusType.Read: + InternalMessagingController.Instance.MarkRead(message.MessageID, user); + break; + } + + _DataService.UpdateMessage(message); + } + + [Obsolete("Deprecated in 6.2.0 - use InternalMessagingController.Instance.GetMessage(messageId)")] + public void MarkMessageAsDispatched(int MessageID) + { + //does not need to run as scheduled task name was updated + } + + #endregion + + #region "functions to support obsolence" + private static Message ConvertCoreMessageToServicesMessage(int PortalID, int UserID, MessageRecipient coreMessageRecipeint, Social.Messaging.Message coreMessage) + { + var message = new Message { AllowReply = true, Body = coreMessage.Body, FromUserID = coreMessage.SenderUserID, MessageDate = coreMessage.CreatedOnDate, PortalID = PortalID }; + + switch (coreMessageRecipeint.Read) + { + case true: + message.Status = MessageStatusType.Read; + break; + case false: + message.Status = MessageStatusType.Unread; + break; + } + + message.ToUserID = UserID; + return message; + } + #endregion + + private readonly IMessagingDataService _DataService; + } +} diff --git a/DNN Platform/Library/Services/Messaging/Scheduler/MessagingScheduler.cs b/DNN Platform/Library/Services/Messaging/Scheduler/MessagingScheduler.cs new file mode 100644 index 00000000000..ab7e58394fc --- /dev/null +++ b/DNN Platform/Library/Services/Messaging/Scheduler/MessagingScheduler.cs @@ -0,0 +1,115 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Messaging.Scheduler +{[Obsolete("Deprecated in 6.2.0 - scheduled item type will automatically update.")] + public class MessagingScheduler : SchedulerClient + { + + private readonly MessagingController _mController = new MessagingController(); + private readonly PortalController _pController = new PortalController(); + + private readonly UserController _uController = new UserController(); + + public MessagingScheduler(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + Guid _schedulerInstance = Guid.NewGuid(); + ScheduleHistoryItem.AddLogNote("MessagingScheduler DoWork Starting " + _schedulerInstance); + + if ((string.IsNullOrEmpty(Host.SMTPServer))) + { + ScheduleHistoryItem.AddLogNote("No SMTP Servers have been configured for this host. Terminating task."); + ScheduleHistoryItem.Succeeded = true; + //'Return + } + else + { + Hashtable settings = ScheduleHistoryItem.GetSettings(); + + bool _messageLeft = true; + int _messagesSent = 0; + + + while (_messageLeft) + { + Data.Message currentMessage = _mController.GetNextMessageForDispatch(_schedulerInstance); + + if ((currentMessage != null)) + { + try + { + SendMessage(currentMessage); + _messagesSent = _messagesSent + 1; + } + catch (Exception e) + { + Errored(ref e); + } + } + else + { + _messageLeft = false; + } + } + + ScheduleHistoryItem.AddLogNote(string.Format("Message Scheduler '{0}' sent a total of {1} message(s)", _schedulerInstance, _messagesSent)); + ScheduleHistoryItem.Succeeded = true; + } + } + catch (Exception ex) + { + ScheduleHistoryItem.Succeeded = false; + ScheduleHistoryItem.AddLogNote("MessagingScheduler Failed: " + ex); + Errored(ref ex); + } + } + + private void SendMessage(Data.Message objMessage) + { + string senderAddress = UserController.GetUserById(objMessage.PortalID, objMessage.FromUserID).Email; + string fromAddress = _pController.GetPortal(objMessage.PortalID).Email; + string toAddress = _uController.GetUser(objMessage.PortalID, objMessage.ToUserID).Email; + + + Mail.Mail.SendEmail(fromAddress, senderAddress, toAddress, objMessage.Subject, objMessage.Body); + + _mController.MarkMessageAsDispatched(objMessage.MessageID); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mobile/IMatchRule.cs b/DNN Platform/Library/Services/Mobile/IMatchRule.cs new file mode 100644 index 00000000000..0e6aed9e438 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/IMatchRule.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public interface IMatchRule + { + /// + /// Primary Id. + /// + int Id { get; } + /// + /// capbility name. + /// + string Capability { get; set; } + + /// + /// reg expression to match the request + /// + string Expression { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Mobile/IPreviewProfile.cs b/DNN Platform/Library/Services/Mobile/IPreviewProfile.cs new file mode 100644 index 00000000000..86e274549d0 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/IPreviewProfile.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public interface IPreviewProfile + { + int Id { get; set; } + + int PortalId { get; set; } + + string Name { get; set; } + + int Width { get; set; } + + string UserAgent { get; set; } + + int Height { get; set; } + + int SortOrder { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Mobile/IPreviewProfileController.cs b/DNN Platform/Library/Services/Mobile/IPreviewProfileController.cs new file mode 100644 index 00000000000..a7c0011dd7e --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/IPreviewProfileController.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + + +namespace DotNetNuke.Services.Mobile +{ + public interface IPreviewProfileController + { + void Save(IPreviewProfile profile); + + void Delete(int portalId, int id); + + IList GetProfilesByPortal(int portalId); + + IPreviewProfile GetProfileById(int portalId, int id); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Mobile/IRedirection.cs b/DNN Platform/Library/Services/Mobile/IRedirection.cs new file mode 100644 index 00000000000..278775a01e7 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/IRedirection.cs @@ -0,0 +1,88 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public interface IRedirection + { + /// + /// Primary ID. + /// + int Id { get; } + /// + /// Portal Id. + /// + int PortalId { get; set; } + /// + /// Redirection name. + /// + string Name { get; set; } + + /// + /// if redirect by visit the whole portal, this value should be -1; + /// otherwise should be the exactly page id for redirection. + /// + int SourceTabId { get; set; } + + /// + /// This value will be available when SourceTabId have a specific value, in that way when this value is true, page will rediect + /// to target when request source tab and all child tabs under source tab. + /// + bool IncludeChildTabs { get; set; } + + /// + /// The redirection type: should be Mobile, Tablet, Both of mobile and tablet, and all other unknown devices. + /// if this value is Other, should use MatchRules to match the special request need to redirect. + /// + RedirectionType Type { get; set; } + + /// + /// request match rules. + /// + IList MatchRules { get; set; } + + /// + /// Redirection target type. + /// + TargetType TargetType { get; set; } + + /// + /// Redirection target value, can a portal id, tab id or a specific url. + /// + object TargetValue { get; set; } + + /// + /// Enabled the Redirection. + /// + bool Enabled { get; set; } + + /// + /// Redirection's Order + /// + int SortOrder { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Mobile/IRedirectionController.cs b/DNN Platform/Library/Services/Mobile/IRedirectionController.cs new file mode 100644 index 00000000000..270eb1e65fb --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/IRedirectionController.cs @@ -0,0 +1,61 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Web; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public interface IRedirectionController + { + void Save(IRedirection redirection); + + void PurgeInvalidRedirections(int portalId); + + void Delete(int portalId, int id); + + void DeleteRule(int portalId, int redirectionId, int ruleId); + + IList GetAllRedirections(); + + IList GetRedirectionsByPortal(int portalId); + + IRedirection GetRedirectionById(int portalId, int id); + + string GetRedirectUrl(string userAgent, int portalId, int currentTabId); + + string GetRedirectUrl(string userAgent); + + string GetFullSiteUrl(); + + string GetFullSiteUrl(int portalId, int currentTabId); + + string GetMobileSiteUrl(); + + string GetMobileSiteUrl(int portalId, int currentTabId); + + bool IsRedirectAllowedForTheSession(HttpApplication app); + } +} diff --git a/DNN Platform/Library/Services/Mobile/MatchRule.cs b/DNN Platform/Library/Services/Mobile/MatchRule.cs new file mode 100644 index 00000000000..e7ade5887e9 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/MatchRule.cs @@ -0,0 +1,103 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + [Serializable] + public class MatchRule : IMatchRule, IHydratable + { + private int _id = -1; + + /// + /// Match rule's primary key. + /// + [XmlAttribute] + public int Id + { + get + { + return _id; + } + set + { + _id = value; + } + } + + /// + /// Capability's name. + /// + [XmlAttribute] + public string Capability + { + get; + set; + } + + /// + /// The value to match the capability from request. + /// + [XmlAttribute] + public string Expression + { + get; + set; + } + + /// + /// IHydratable.KeyID. + /// + [XmlAttribute] + public int KeyID + { + get + { + return this.Id; + } + set + { + this.Id = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(System.Data.IDataReader dr) + { + this.Id = Convert.ToInt32(dr["Id"]); + this.Capability = dr["Capability"].ToString(); + this.Expression = dr["Expression"].ToString(); + } + } +} diff --git a/DNN Platform/Library/Services/Mobile/PreviewProfile.cs b/DNN Platform/Library/Services/Mobile/PreviewProfile.cs new file mode 100644 index 00000000000..695b361bdeb --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/PreviewProfile.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + [Serializable] + public class PreviewProfile : IPreviewProfile, IHydratable + { + private int _id = -1; + + /// + /// Primary key. + /// + [XmlAttribute] + public int Id + { + get + { + return _id; + } + set + { + _id = value; + } + } + + /// + /// the profiles' effected portal. + /// + [XmlAttribute] + public int PortalId + { + get; + set; + } + + /// + /// profile's name. + /// + [XmlAttribute] + public string Name + { + get; + set; + } + + /// + /// the preview device's width. + /// + [XmlAttribute] + public int Width { get; set; } + + /// + /// the preview device's height. + /// + [XmlAttribute] + public int Height { get; set; } + + /// + /// the preview device's user agent. + /// + [XmlAttribute] + public string UserAgent { get; set; } + + /// + /// Profile's sort order. + /// + [XmlAttribute] + public int SortOrder { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.Id; + } + set + { + this.Id = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.Id = Convert.ToInt32(dr["Id"]); + this.PortalId = Convert.ToInt32(dr["PortalId"]); + this.Name = dr["Name"].ToString(); + this.Width = Convert.ToInt32(dr["Width"]); + this.Height = Convert.ToInt32(dr["Height"]); + this.UserAgent = dr["UserAgent"].ToString(); + this.SortOrder = Convert.ToInt32(dr["SortOrder"]); + } + } +} diff --git a/DNN Platform/Library/Services/Mobile/PreviewProfileController.cs b/DNN Platform/Library/Services/Mobile/PreviewProfileController.cs new file mode 100644 index 00000000000..7c5e29bea96 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/PreviewProfileController.cs @@ -0,0 +1,205 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Serialization; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + /// + /// The business of mobile preview profiles. + /// + public class PreviewProfileController : IPreviewProfileController + { + #region "Public Methods" + /// + /// save a preview profile. If profile.Id equals Null.NullInteger(-1), that means need to add a new profile; + /// otherwise will update the profile by profile.Id. + /// + /// profile object. + public void Save(IPreviewProfile profile) + { + Requires.NotNull("The profile can't be null", profile); + + if (profile.Id == Null.NullInteger || profile.SortOrder == 0) + { + profile.SortOrder = GetProfilesByPortal(profile.PortalId, false).Count + 1; + } + + int id = DataProvider.Instance().SavePreviewProfile(profile.Id, + profile.PortalId, + profile.Name, + profile.Width, + profile.Height, + profile.UserAgent, + profile.SortOrder, + UserController.GetCurrentUserInfo().UserID); + + profile.Id = id; + + var logContent = string.Format("{0} Mobile Preview Profile '{1}'", profile.Id == Null.NullInteger ? "Add" : "Update", profile.Name); + AddLog(logContent); + + ClearCache(profile.PortalId); + } + + /// + /// delete a preview profile. + /// + /// Portal's id. + /// the profile's id. + public void Delete(int portalId, int id) + { + var delProfile = GetProfileById(portalId, id); + if (delProfile != null) + { + //update the list order + GetProfilesByPortal(portalId).Where(p => p.SortOrder > delProfile.SortOrder).ToList().ForEach(p => + { + p.SortOrder--; + Save(p); + }); + DataProvider.Instance().DeletePreviewProfile(id); + + var logContent = string.Format("Delete Mobile Preview Profile '{0}'", id); + AddLog(logContent); + + ClearCache(portalId); + } + } + + /// + /// get a preview profiles list for portal. + /// + /// portal id. + /// List of preview profile. + public IList GetProfilesByPortal(int portalId) + { + return GetProfilesByPortal(portalId, true); + } + + /// + /// get a specific preview profile by id. + /// + /// the profile belong's portal. + /// profile's id. + /// profile object. + public IPreviewProfile GetProfileById(int portalId, int id) + { + return GetProfilesByPortal(portalId).Where(r => r.Id == id).FirstOrDefault(); + } + + #endregion + + #region "Private Methods" + + private IList GetProfilesByPortal(int portalId, bool addDefault) + { + string cacheKey = string.Format(DataCache.PreviewProfilesCacheKey, portalId); + var cacheArg = new CacheItemArgs(cacheKey, DataCache.PreviewProfilesCacheTimeOut, DataCache.PreviewProfilesCachePriority, portalId, addDefault); + return CBO.GetCachedObject>(cacheArg, GetProfilesByPortalIdCallBack); + } + + private IList GetProfilesByPortalIdCallBack(CacheItemArgs cacheItemArgs) + { + int portalId = (int)cacheItemArgs.ParamList[0]; + bool addDefault = (bool)cacheItemArgs.ParamList[1]; + + var profiles = CBO.FillCollection(DataProvider.Instance().GetPreviewProfiles(portalId)); + if (profiles.Count == 0 && addDefault) + { + profiles = CreateDefaultDevices(portalId); + } + + return profiles.Cast().ToList(); + } + + private void ClearCache(int portalId) + { + DataCache.RemoveCache(string.Format(DataCache.PreviewProfilesCacheKey, portalId)); + } + + private void AddLog(string logContent) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("Message", logContent, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.ADMIN_ALERT); + } + + + private List CreateDefaultDevices(int portalId) + { + string defaultPreviewProfiles; + var settings = PortalController.GetPortalSettingsDictionary(portalId); + List profiles = new List(); + + if (!settings.TryGetValue("DefPreviewProfiles_Created", out defaultPreviewProfiles) || defaultPreviewProfiles != DotNetNukeContext.Current.Application.Name) + { + try + { + var defaultDeviceDBPath = Config.GetSetting("DefaultDevicesDatabase"); + if (!string.IsNullOrEmpty(defaultDeviceDBPath)) + { + var dataPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, defaultDeviceDBPath); + + if (!string.IsNullOrEmpty(dataPath) && File.Exists(dataPath)) + { + var serializer = new XmlSerializer(typeof (List)); + profiles = (List) serializer.Deserialize(File.OpenRead(dataPath)); + + if (profiles != null) + { + profiles.ForEach(p => + { + p.PortalId = portalId; + + Save(p); + }); + } + } + } + + PortalController.UpdatePortalSetting(portalId, "DefPreviewProfiles_Created", DotNetNukeContext.Current.Application.Name); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + + return profiles; + } + #endregion + } +} diff --git a/DNN Platform/Library/Services/Mobile/Redirection.cs b/DNN Platform/Library/Services/Mobile/Redirection.cs new file mode 100644 index 00000000000..65a818e9324 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/Redirection.cs @@ -0,0 +1,185 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.ComponentModel; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + [Serializable] + public class Redirection : IRedirection, IHydratable + { + private int _id = -1; + + /// + /// Redirection's primary key. + /// + public int Id + { + get + { + return _id; + } + set + { + _id = value; + _matchRules = null; + } + } + + /// + /// The portal Redirection is belong to. + /// + [XmlAttribute] + public int PortalId { get; set; } + + /// + /// Redirection name. + /// + [XmlAttribute] + public string Name { get; set; } + + /// + /// The redirection's match source tab. if this value is Null.NullInteger(-1) means should redirect when request the whole current portal; + /// otherwise means this redirection will be available for the specific tab. + /// + [XmlAttribute] + public int SourceTabId { get; set; } + + /// + /// This value will be available when SourceTabId have a specific value, in that way when this value is true, page will rediect + /// to target when request source tab and all child tabs under source tab. + /// + [XmlAttribute] + public bool IncludeChildTabs { get; set; } + + /// + /// Redirection Type: Mobile, Tablet, Both or Other. + /// + [XmlAttribute] + public RedirectionType Type { get; set; } + + [XmlIgnore] + private IList _matchRules; + + /// + /// When redirection type is RedirectionType.Other, should use this collection to match the request by capability info. + /// + [XmlIgnore] + public IList MatchRules + { + get + { + if (_matchRules == null) + { + if (_id == Null.NullInteger) + { + _matchRules = new List(); + } + else + { + //get from database + _matchRules = CBO.FillCollection(DataProvider.Instance().GetRedirectionRules(this.Id)).Cast().ToList(); + } + } + + return _matchRules; + } + set + { + _matchRules = value; + } + } + + /// + /// Redirection's target type, should be: Portal, Tab, Url + /// + [XmlAttribute] + public TargetType TargetType { get; set; } + + /// + /// the redirection's target value, this value will determine by TargetType as: + /// + /// TargetType.Portal: this value should be a portal id. + /// TargetType.Tab: this value should be a tab id. + /// TargetType.Url: this value should be a valid url. + /// + /// + [XmlAttribute] + public object TargetValue { get; set; } + + /// + /// Whether this redirection is available. + /// + [XmlAttribute] + public bool Enabled { get; set; } + + /// + /// Redirection's piority. + /// + [XmlAttribute] + public int SortOrder { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.Id; + } + set + { + this.Id = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(System.Data.IDataReader dr) + { + this.Id = Convert.ToInt32(dr["Id"]); + this.PortalId = Convert.ToInt32(dr["PortalId"]); + this.Name = dr["Name"].ToString(); + this.Type = (RedirectionType)Convert.ToInt32(dr["Type"]); + this.SourceTabId = Convert.ToInt32(dr["SourceTabId"]); + this.IncludeChildTabs = Convert.ToBoolean(dr["IncludeChildTabs"]); + this.SortOrder = Convert.ToInt32(dr["SortOrder"]); + this.TargetType = (TargetType)Convert.ToInt32(dr["TargetType"]); + this.TargetValue = dr["TargetValue"]; + this.Enabled = Convert.ToBoolean(dr["Enabled"]); + } + } +} diff --git a/DNN Platform/Library/Services/Mobile/RedirectionController.cs b/DNN Platform/Library/Services/Mobile/RedirectionController.cs new file mode 100644 index 00000000000..da1b90b9017 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/RedirectionController.cs @@ -0,0 +1,722 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web; +using System.Web.Caching; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.ClientCapability; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public class RedirectionController : IRedirectionController + { + #region Constants + private const string DisableMobileRedirectCookieName = "disablemobileredirect"; + private const string DisableRedirectPresistCookieName = "disableredirectpresist"; + private const string DisableMobileRedirectQueryStringName = "nomo"; //google uses the same name nomo=1 means do not redirect to mobile + #endregion + + #region Private Properties + + private const string UrlsCacheKey = "MobileRedirectAllUrls"; + private const string RedirectionUrlCacheKey = "RedirectionUrl_{0}_{1}_{2}"; + private const string FullSiteUrlCacheKey = "FullSiteUrl_{0}_{1}"; + private const string MobileSiteUrlCacheKey = "MobileSiteUrl_{0}_{1}"; + private const int UrlsCacheTimeout = 60; + + #endregion + + #region Public Methods + + /// + /// Is Redirection Allowed for the session. Method analyzes the query string for special parameters to enable / disable redirects. + /// Cookie is created to temporarily store those parameters so that they remain available till the interactions are active. + /// + /// boolean - True if redirection + /// app - HttpApplication. Request and Response properties are used + public bool IsRedirectAllowedForTheSession(HttpApplication app) + { + bool allowed = true; + + //Check for the existence of special query string to force enable / disable of redirect + if (app.Request.QueryString[DisableMobileRedirectQueryStringName] != null) + { + int val; + if (int.TryParse(app.Request.QueryString[DisableMobileRedirectQueryStringName], out val)) + { + if (val == 0) //forced enable. clear any cookie previously set + { + if (app.Response.Cookies[DisableMobileRedirectCookieName] != null) + { + HttpCookie cookie = new HttpCookie(DisableMobileRedirectCookieName); + cookie.Expires = DateTime.Now.AddMinutes(-1); + app.Response.Cookies.Add(cookie); + } + + if (app.Response.Cookies[DisableRedirectPresistCookieName] != null) + { + HttpCookie cookie = new HttpCookie(DisableRedirectPresistCookieName); + cookie.Expires = DateTime.Now.AddMinutes(-1); + app.Response.Cookies.Add(cookie); + } + } + else if (val == 1) //forced disable. need to setup cookie + { + allowed = false; + } + } + } + else if (app.Request.Cookies[DisableMobileRedirectCookieName] != null && app.Request.Cookies[DisableRedirectPresistCookieName] != null) //check for cookie + { + allowed = false; + } + + + if (!allowed) //redirect is not setup to be allowed, keep the cookie alive + { + //this cookie is set to re-enable redirect after 20 minutes + HttpCookie presistCookie = new HttpCookie(DisableRedirectPresistCookieName); + presistCookie.Expires = DateTime.Now.AddMinutes(20); + app.Response.Cookies.Add(presistCookie); + + //this cookie is set to re-enable redirect after close browser. + HttpCookie cookie = new HttpCookie(DisableMobileRedirectCookieName); + app.Response.Cookies.Add(cookie); + } + + return allowed; + } + + /// + /// Get Redirection Url based on UserAgent. + /// + /// string - Empty if redirection rules are not defined or no match found + /// User Agent - used for client capability detection. + public string GetRedirectUrl(string userAgent) + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings != null && portalSettings.ActiveTab != null) + { + string redirectUrl = GetRedirectUrl(userAgent, portalSettings.PortalId, portalSettings.ActiveTab.TabID); + if (!string.IsNullOrEmpty(redirectUrl) && string.Compare(redirectUrl, portalSettings.ActiveTab.FullUrl, true, CultureInfo.InvariantCulture) != 0) + { + return redirectUrl; + } + } + + return string.Empty; + } + + /// + /// Get Redirection Url based on Http Context and Portal Id. + /// + /// string - Empty if redirection rules are not defined or no match found + /// User Agent - used for client capability detection. + /// Portal Id from which Redirection Rules should be applied. + /// Current Tab Id that needs to be evaluated. + public string GetRedirectUrl(string userAgent, int portalId, int currentTabId) + { + Requires.NotNull("userAgent", userAgent); + + string redirectUrl = string.Empty; + + IList redirections = GetRedirectionsByPortal(portalId); + //check for redirect only when redirect rules are defined + if (redirections == null || redirections.Count == 0) + { + return redirectUrl; + } + + //try to get content from cache + var cacheKey = string.Format(RedirectionUrlCacheKey, userAgent, portalId, currentTabId); + redirectUrl = GetUrlFromCache(cacheKey); + if (!string.IsNullOrEmpty(redirectUrl)) + { + return redirectUrl; + } + + var clientCapability = ClientCapabilityProvider.Instance().GetClientCapability(userAgent); + var tabController = new TabController(); + foreach (var redirection in redirections) + { + if (redirection.Enabled) + { + bool checkFurther = false; + //redirection is based on source tab + if (redirection.SourceTabId != Null.NullInteger) + { + //source tab matches current tab + if (currentTabId == redirection.SourceTabId) + { + checkFurther = true; + } + //is child tabs to be included as well + else if (redirection.IncludeChildTabs) + { + //Get all the descendents of the source tab and find out if current tab is in source tab's hierarchy or not. + foreach (var childTab in tabController.GetTabsByPortal(portalId).DescendentsOf(redirection.SourceTabId)) + { + if (childTab.TabID == currentTabId) + { + checkFurther = true; + break; + } + } + } + } + //redirection is based on portal + else if (redirection.SourceTabId == Null.NullInteger) + { + checkFurther = true; + } + + if (checkFurther) + { + //check if client capability matches with this rule + if (DoesCapabilityMatchWithRule(clientCapability, redirection)) + { + //find the redirect url + redirectUrl = GetRedirectUrlFromRule(redirection, portalId, currentTabId); + + //update cache content + SetUrlInCache(cacheKey, redirectUrl); + break; + } + } + } + } + + return redirectUrl; + } + + /// + /// Get Url for the equivalent full site based on the current page of the mobile site + /// + /// string - Empty if redirection rules are not defined or no match found + public string GetFullSiteUrl() + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings != null && portalSettings.ActiveTab != null) + { + string fullSiteUrl = GetFullSiteUrl(portalSettings.PortalId, portalSettings.ActiveTab.TabID); + if (!string.IsNullOrEmpty(fullSiteUrl) && string.Compare(fullSiteUrl, portalSettings.ActiveTab.FullUrl, true, CultureInfo.InvariantCulture) != 0) + { + return fullSiteUrl; + } + } + + return string.Empty; + } + + /// + /// Get Url for the equivalent full site based on the current page of the mobile site + /// + /// string - Empty if redirection rules are not defined or no match found + /// Portal Id from which Redirection Rules should be applied. + /// Current Tab Id that needs to be evaluated. + public string GetFullSiteUrl(int portalId, int currentTabId) + { + string fullSiteUrl = string.Empty; + + IList redirections = GetAllRedirections(); + //check for redirect only when redirect rules are defined + if (redirections == null || redirections.Count == 0) + { + return fullSiteUrl; + } + + //try to get content from cache + var cacheKey = string.Format(FullSiteUrlCacheKey, portalId, currentTabId); + fullSiteUrl = GetUrlFromCache(cacheKey); + if (!string.IsNullOrEmpty(fullSiteUrl)) + { + return fullSiteUrl; + } + + bool foundRule = false; + foreach (var redirection in redirections) + { + if (redirection.Enabled) + { + if (redirection.TargetType == TargetType.Tab) //page within same site + { + int targetTabId = int.Parse(redirection.TargetValue.ToString()); + if (targetTabId == currentTabId) //target tab is same as current tab + { + foundRule = true; + } + } + else if (redirection.TargetType == TargetType.Portal) //home page of another portal + { + int targetPortalId = int.Parse(redirection.TargetValue.ToString()); + if (targetPortalId == portalId) //target portal is same as current portal + { + foundRule = true; + } + } + + //found the rule, let's find the url now + if (foundRule) + { + ////redirection is based on tab + //Following are being commented as NavigateURL method does not return correct url for a tab in a different portal + //always point to the home page of the other portal + //if (redirection.SourceTabId != Null.NullInteger) + //{ + // fullSiteUrl = Globals.NavigateURL(redirection.SourceTabId); + //} + //else //redirection is based on portal + { + var portalSettings = new PortalSettings(redirection.PortalId); + if (portalSettings.HomeTabId != Null.NullInteger && portalSettings.HomeTabId != currentTabId) //ensure it's not redirecting to itself + { + fullSiteUrl = GetPortalHomePageUrl(portalSettings); + } + } + break; + } + } + } + + //append special query string + if (!string.IsNullOrEmpty(fullSiteUrl)) + fullSiteUrl += string.Format("{0}{1}=1", fullSiteUrl.Contains("?") ? "&" : "?", DisableMobileRedirectQueryStringName); + + //update cache content + SetUrlInCache(cacheKey, fullSiteUrl); + + return fullSiteUrl; + } + + /// + /// Get Url for the equivalent mobile site based on the current page of the full site + /// + /// string - Empty if redirection rules are not defined or no match found + public string GetMobileSiteUrl() + { + var portalSettings = PortalController.GetCurrentPortalSettings(); + if (portalSettings != null && portalSettings.ActiveTab != null) + { + string fullSiteUrl = GetMobileSiteUrl(portalSettings.PortalId, portalSettings.ActiveTab.TabID); + if (!string.IsNullOrEmpty(fullSiteUrl) && string.Compare(fullSiteUrl, portalSettings.ActiveTab.FullUrl, true, CultureInfo.InvariantCulture) != 0) + { + return fullSiteUrl; + } + } + + return string.Empty; + } + + /// + /// Get Url for the equivalent mobile site based on the current page of the full site + /// + /// string - Empty if redirection rules are not defined or no match found + /// Portal Id from which Redirection Rules should be applied. + /// Current Tab Id that needs to be evaluated. + public string GetMobileSiteUrl(int portalId, int currentTabId) + { + string mobileSiteUrl = string.Empty; + IList redirections = GetRedirectionsByPortal(portalId); + //check for redirect only when redirect rules are defined + if (redirections == null || redirections.Count == 0) + { + return mobileSiteUrl; + } + + //try to get content from cache + var cacheKey = string.Format(MobileSiteUrlCacheKey, portalId, currentTabId); + mobileSiteUrl = GetUrlFromCache(cacheKey); + if (!string.IsNullOrEmpty(mobileSiteUrl)) + { + return mobileSiteUrl; + } + + //let's try to find if this tab has any specifc rules + foreach (var redirection in redirections) + { + if (redirection.Enabled) + { + if (redirection.SourceTabId != Null.NullInteger && currentTabId == redirection.SourceTabId) + { + mobileSiteUrl = GetRedirectUrlFromRule(redirection, portalId, currentTabId); + break; + } + } + } + + //tab has no specific rule, we can select the first rule + if (string.IsNullOrEmpty(mobileSiteUrl)) + { + var firstRedirection = redirections.FirstOrDefault(r => r.Enabled); + if (firstRedirection != null) + { + mobileSiteUrl = GetRedirectUrlFromRule(firstRedirection, portalId, currentTabId); + } + } + + //append special query string + if (!string.IsNullOrEmpty(mobileSiteUrl)) + mobileSiteUrl += string.Format("{0}{1}=0", mobileSiteUrl.Contains("?") ? "&" : "?", DisableMobileRedirectQueryStringName); + + //update cache content + SetUrlInCache(cacheKey, mobileSiteUrl); + + return mobileSiteUrl; + } + + /// + /// save a redirection. If redirection.Id equals Null.NullInteger(-1), that means need to add a new redirection; + /// otherwise will update the redirection by redirection.Id. + /// + /// redirection object. + public void Save(IRedirection redirection) + { + if(redirection.Id == Null.NullInteger || redirection.SortOrder == 0) + { + redirection.SortOrder = GetRedirectionsByPortal(redirection.PortalId).Count + 1; + } + + int id = DataProvider.Instance().SaveRedirection(redirection.Id, + redirection.PortalId, + redirection.Name, + (int) redirection.Type, + redirection.SortOrder, + redirection.SourceTabId, + redirection.IncludeChildTabs, + (int) redirection.TargetType, + redirection.TargetValue, + redirection.Enabled, + UserController.GetCurrentUserInfo().UserID); + + foreach (IMatchRule rule in redirection.MatchRules) + { + DataProvider.Instance().SaveRedirectionRule(rule.Id, id, rule.Capability, rule.Expression); + } + + var logContent = string.Format("'{0}' {1}", redirection.Name, redirection.Id == Null.NullInteger ? "Added" : "Updated"); + AddLog(logContent); + + ClearCache(redirection.PortalId); + } + + /// + /// Deletes all redirection rules that were set for pages that have been soft or hard deleted. + /// + /// + public void PurgeInvalidRedirections(int portalId) + { + var allTabs = new TabController().GetTabsByPortal(portalId); + var redirects = GetRedirectionsByPortal(portalId); + + //remove rules for deleted source tabs + foreach (var r in redirects.Where(r => r.SourceTabId != Null.NullInteger && allTabs.Where(t => t.Key == r.SourceTabId).Count() < 1)) + { + Delete(portalId, r.Id); + } + + //remove rules for deleted target tabs + redirects = GetRedirectionsByPortal(portalId); //fresh get of rules in case some were deleted above + foreach (var r in redirects.Where(r => r.TargetType == TargetType.Tab && allTabs.Where(t => t.Key == int.Parse(r.TargetValue.ToString())).Count() < 1)) + { + Delete(portalId, r.Id); + } + + //remove rules for deleted target portals + redirects = GetRedirectionsByPortal(portalId); //fresh get of rules in case some were deleted above + var allPortals = new PortalController().GetPortals(); + foreach (var r in redirects.Where(r => r.TargetType == TargetType.Portal)) + { + bool found = false; + foreach (PortalInfo portal in allPortals) + { + if (portal.PortalID == int.Parse(r.TargetValue.ToString())) + { + found = true; + break; + } + } + if (!found) + Delete(portalId, r.Id); + } + } + + /// + /// delete a redirection. + /// + /// Portal's id. + /// the redirection's id. + public void Delete(int portalId, int id) + { + var delRedirection = GetRedirectionById(portalId, id); + if (delRedirection != null) + { + //update the list order + GetRedirectionsByPortal(portalId).Where(p => p.SortOrder > delRedirection.SortOrder).ToList().ForEach(p => + { + p.SortOrder--; + Save(p); + }); + DataProvider.Instance().DeleteRedirection(id); + + var logContent = string.Format("Id '{0}' Deleted", id); + AddLog(logContent); + + ClearCache(portalId); + } + } + + /// + /// delete a redirection's match rule. + /// + /// Portal's id. + /// the redirection's id. + /// the rule's id. + public void DeleteRule(int portalId, int redirectionId, int ruleId) + { + DataProvider.Instance().DeleteRedirectionRule(ruleId); + + var logContent = string.Format("Id '{0}' Removed from Redirection Id '{1}'", ruleId, redirectionId); + AddLog(logContent); + + ClearCache(portalId); + } + + /// + /// get all redirections defined in system. + /// + /// List of redirection. + public IList GetAllRedirections() + { + var cacheArg = new CacheItemArgs(AllRedirectionsCacheKey, DataCache.RedirectionsCacheTimeOut, DataCache.RedirectionsCachePriority, ""); + return CBO.GetCachedObject>(cacheArg, GetAllRedirectionsCallBack); + } + + /// + /// get a redirection list for portal. + /// + /// redirection id. + /// List of redirection. + public IList GetRedirectionsByPortal(int portalId) + { + string cacheKey = string.Format(DataCache.RedirectionsCacheKey, portalId); + var cacheArg = new CacheItemArgs(cacheKey, DataCache.RedirectionsCacheTimeOut, DataCache.RedirectionsCachePriority, portalId); + return CBO.GetCachedObject>(cacheArg, GetRedirectionsByPortalCallBack); + } + + /// + /// get a specific redirection by id. + /// + /// the redirection belong's portal. + /// redirection's id. + /// redirection object. + public IRedirection GetRedirectionById(int portalId, int id) + { + return GetRedirectionsByPortal(portalId).Where(r => r.Id == id).FirstOrDefault(); + } + + /// + /// returns a target URL for the specific redirection + /// + /// + /// + /// + /// + public string GetRedirectUrlFromRule(IRedirection redirection, int portalId, int currentTabId) + { + string redirectUrl = string.Empty; + + if (redirection.TargetType == TargetType.Url) //independent url base + { + redirectUrl = redirection.TargetValue.ToString(); + } + else if (redirection.TargetType == TargetType.Tab) //page within same site + { + int targetTabId = int.Parse(redirection.TargetValue.ToString()); + if (targetTabId != currentTabId) //ensure it's not redirecting to itself + { + var tabController = new TabController(); + var tab = tabController.GetTab(targetTabId, portalId, false); + if (tab != null && !tab.IsDeleted) + { + redirectUrl = Globals.NavigateURL(targetTabId); + } + } + } + else if (redirection.TargetType == TargetType.Portal) //home page of another portal + { + int targetPortalId = int.Parse(redirection.TargetValue.ToString()); + if (targetPortalId != portalId) //ensure it's not redirecting to itself + { + //check whethter the target portal still exists + var portalController = new PortalController(); + if (portalController.GetPortals().Cast().Any(p => p.PortalID == targetPortalId)) + { + var portalSettings = new PortalSettings(targetPortalId); + if (portalSettings.HomeTabId != Null.NullInteger && portalSettings.HomeTabId != currentTabId) //ensure it's not redirecting to itself + { + redirectUrl = GetPortalHomePageUrl(portalSettings); + } + } + } + } + + return redirectUrl; + } + + #endregion + + #region "Private Methods" + + private string GetPortalHomePageUrl(PortalSettings portalSettings) + { + return Globals.AddHTTP(portalSettings.DefaultPortalAlias); + } + + private IList GetAllRedirectionsCallBack(CacheItemArgs cacheItemArgs) + { + return CBO.FillCollection(DataProvider.Instance().GetAllRedirections()).Cast().ToList(); + } + + private IList GetRedirectionsByPortalCallBack(CacheItemArgs cacheItemArgs) + { + int portalId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillCollection(DataProvider.Instance().GetRedirections(portalId)).Cast().ToList(); + } + + private void ClearCache(int portalId) + { + DataCache.RemoveCache(string.Format(DataCache.RedirectionsCacheKey, portalId)); + DataCache.RemoveCache(AllRedirectionsCacheKey); + DataCache.RemoveCache(UrlsCacheKey); + } + + private string GetUrlFromCache(string cacheKey) + { + var cachedUrls = DataCache.GetCache>(UrlsCacheKey); + + if (cachedUrls != null) + { + using (cachedUrls.GetReadLock()) + { + if (cachedUrls.ContainsKey(cacheKey)) + { + return cachedUrls[cacheKey]; + } + } + } + + return string.Empty; + } + + private void SetUrlInCache(string cacheKey, string url) + { + if (string.IsNullOrEmpty(cacheKey)) + { + return; + } + + var cachedUrls = DataCache.GetCache>(UrlsCacheKey); + + if (cachedUrls == null) + { + cachedUrls = new SharedDictionary(); + } + using (cachedUrls.GetWriteLock()) + { + cachedUrls[cacheKey] = url; + } + + DataCache.SetCache(UrlsCacheKey, cachedUrls, TimeSpan.FromMinutes(UrlsCacheTimeout)); + } + + private void AddLog(string logContent) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("Site Redirection Rule", logContent, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.ADMIN_ALERT); + } + + private bool DoesCapabilityMatchWithRule(IClientCapability clientCapability, IRedirection redirection) + { + bool match = false; + if (redirection.Type == RedirectionType.Tablet && clientCapability.IsTablet) + { + match = true; + } + else if (redirection.Type == RedirectionType.MobilePhone && clientCapability.IsMobile) + { + match = true; + } + else if (redirection.Type == RedirectionType.AllMobile && (clientCapability.IsMobile || clientCapability.IsTablet)) + { + match = true; + } + else if (redirection.Type == RedirectionType.Other) + { + //match all the capabilities defined in the rule + int matchCount = 0; + foreach (IMatchRule rule in redirection.MatchRules) + { + if (clientCapability.Capabilities != null && clientCapability.Capabilities.ContainsKey(rule.Capability)) + { + if (clientCapability.Capabilities[rule.Capability].Equals(rule.Expression, StringComparison.InvariantCultureIgnoreCase)) + { + matchCount++; + } + } + } + if(matchCount > 0 && matchCount == redirection.MatchRules.Count) + { + match = true; + } + } + + return match; + } + + #endregion + + #region Private Properties + private string AllRedirectionsCacheKey + { + get + { + return string.Format(DataCache.RedirectionsCacheKey, "All"); + } + } + #endregion + } +} diff --git a/DNN Platform/Library/Services/Mobile/RedirectionType.cs b/DNN Platform/Library/Services/Mobile/RedirectionType.cs new file mode 100644 index 00000000000..2ecb8383ec6 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/RedirectionType.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public enum RedirectionType + { + /// + /// Redirect when request from a mobile phone + /// + MobilePhone = 1, + + /// + /// Redirect when request from a tablet + /// + Tablet = 2, + + /// + /// Redirect when request from either a mobile phone or a tablet + /// + AllMobile = 3, + + /// + /// Redirect when request from some unknown device, should be determine by match rules; + /// + Other = 4, + + /// + /// Redirect when request from a smart phone + /// + SmartPhone = 5 + } +} diff --git a/DNN Platform/Library/Services/Mobile/TargetType.cs b/DNN Platform/Library/Services/Mobile/TargetType.cs new file mode 100644 index 00000000000..e6c2302d908 --- /dev/null +++ b/DNN Platform/Library/Services/Mobile/TargetType.cs @@ -0,0 +1,46 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Mobile +{ + public enum TargetType + { + /// + /// Redirect when request from a mobile + /// + Portal = 1, + + /// + /// Redirect when request from a tablet + /// + Tab = 2, + + /// + /// Redirect when request from some unknown device, should be determine by match rules; + /// + Url = 3 + } +} diff --git a/DNN Platform/Library/Services/ModuleCache/FileProvider.cs b/DNN Platform/Library/Services/ModuleCache/FileProvider.cs new file mode 100644 index 00000000000..b8a0a872e77 --- /dev/null +++ b/DNN Platform/Library/Services/ModuleCache/FileProvider.cs @@ -0,0 +1,324 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.ModuleCache +{ + public class FileProvider : ModuleCachingProvider + { + #region Private Members + + private const string DataFileExtension = ".data.resources"; + private const string AttribFileExtension = ".attrib.resources"; + private static readonly SharedDictionary CacheFolderPath = new SharedDictionary(LockingStrategy.ReaderWriter); + + #endregion + + #region Private Methods + + private string GenerateCacheKeyHash(int tabModuleId, string cacheKey) + { + byte[] hash = Encoding.ASCII.GetBytes(cacheKey); + var md5 = new MD5CryptoServiceProvider(); + hash = md5.ComputeHash(hash); + return tabModuleId + "_" + ByteArrayToString(hash); + } + + private static string GetAttribFileName(int tabModuleId, string cacheKey) + { + return string.Concat(GetCacheFolder(), cacheKey, AttribFileExtension); + } + + private static int GetCachedItemCount(int tabModuleId) + { + return Directory.GetFiles(GetCacheFolder(), String.Format("*{0}", DataFileExtension)).Length; + } + + private static string GetCachedOutputFileName(int tabModuleId, string cacheKey) + { + return string.Concat(GetCacheFolder(), cacheKey, DataFileExtension); + } + + /// + /// [jmarino] 2011-06-16 Check for ContainsKey for a write added + /// + /// + /// + private static string GetCacheFolder(int portalId) + { + string cacheFolder; + + using (var readerLock = CacheFolderPath.GetReadLock()) + { + if (CacheFolderPath.TryGetValue(portalId, out cacheFolder)) + { + return cacheFolder; + } + } + + var portalController = new PortalController(); + PortalInfo portalInfo = portalController.GetPortal(portalId); + + string homeDirectoryMapPath = portalInfo.HomeDirectoryMapPath; + + + if (!(string.IsNullOrEmpty(homeDirectoryMapPath))) + { + cacheFolder = string.Concat(homeDirectoryMapPath, "Cache\\Pages\\"); + if (!(Directory.Exists(cacheFolder))) + { + Directory.CreateDirectory(cacheFolder); + } + } + + using (var writerLock = CacheFolderPath.GetWriteLock()) + { + if (!CacheFolderPath.ContainsKey(portalId)) + CacheFolderPath.Add(portalId, cacheFolder); + } + + return cacheFolder; + } + + private static string GetCacheFolder() + { + int portalId = PortalController.GetCurrentPortalSettings().PortalId; + return GetCacheFolder(portalId); + } + + private bool IsFileExpired(string file) + { + StreamReader oRead = null; + try + { + oRead = File.OpenText(file); + DateTime expires = DateTime.Parse(oRead.ReadLine(), CultureInfo.InvariantCulture); + if (expires < DateTime.UtcNow) + { + return true; + } + else + { + return false; + } + } + catch + { + //if check expire time failed, then force to expire the cache. + return true; + } + finally + { + if (oRead != null) + { + oRead.Close(); + } + } + } + + private void PurgeCache(string folder) + { + var filesNotDeleted = new StringBuilder(); + int i = 0; + foreach (string File in Directory.GetFiles(folder, "*.resources")) + { + if (!FileSystemUtils.DeleteFileWithWait(File, 100, 200)) + { + filesNotDeleted.Append(String.Format("{0};", File)); + } + else + { + i += 1; + } + } + if (filesNotDeleted.Length > 0) + { + throw new IOException(String.Format("Deleted {0} files, however, some files are locked. Could not delete the following files: {1}", i, filesNotDeleted)); + } + } + + private static bool IsPathInApplication(string cacheFolder) + { + return cacheFolder.Contains(Globals.ApplicationMapPath); + } + + #endregion + + #region Abstract Method Implementation + + public override string GenerateCacheKey(int tabModuleId, SortedDictionary varyBy) + { + var cacheKey = new StringBuilder(); + if (varyBy != null) + { + SortedDictionary.Enumerator varyByParms = varyBy.GetEnumerator(); + while ((varyByParms.MoveNext())) + { + string key = varyByParms.Current.Key.ToLower(); + cacheKey.Append(string.Concat(key, "=", varyByParms.Current.Value, "|")); + } + } + return GenerateCacheKeyHash(tabModuleId, cacheKey.ToString()); + } + + public override int GetItemCount(int tabModuleId) + { + return GetCachedItemCount(tabModuleId); + } + + public override byte[] GetModule(int tabModuleId, string cacheKey) + { + string cachedModule = GetCachedOutputFileName(tabModuleId, cacheKey); + BinaryReader br = null; + FileStream fStream = null; + byte[] data; + try + { + if (!File.Exists(cachedModule)) + { + return null; + } + var fInfo = new FileInfo(cachedModule); + long numBytes = fInfo.Length; + fStream = new FileStream(cachedModule, FileMode.Open, FileAccess.Read); + br = new BinaryReader(fStream); + data = br.ReadBytes(Convert.ToInt32(numBytes)); + } + finally + { + if (br != null) + { + br.Close(); + } + if (fStream != null) + { + fStream.Close(); + } + } + return data; + } + + public override void PurgeCache(int portalId) + { + PurgeCache(GetCacheFolder(portalId)); + } + + public override void PurgeExpiredItems(int portalId) + { + var filesNotDeleted = new StringBuilder(); + int i = 0; + string cacheFolder = GetCacheFolder(portalId); + if (Directory.Exists(cacheFolder) && IsPathInApplication(cacheFolder)) + { + foreach (string File in Directory.GetFiles(cacheFolder, String.Format("*{0}", AttribFileExtension))) + { + if (IsFileExpired(File)) + { + string fileToDelete = File.Replace(AttribFileExtension, DataFileExtension); + if (!FileSystemUtils.DeleteFileWithWait(fileToDelete, 100, 200)) + { + filesNotDeleted.Append(String.Format("{0};", fileToDelete)); + } + else + { + i += 1; + } + } + } + } + if (filesNotDeleted.Length > 0) + { + throw new IOException(String.Format("Deleted {0} files, however, some files are locked. Could not delete the following files: {1}", i, filesNotDeleted)); + } + } + + public override void SetModule(int tabModuleId, string cacheKey, TimeSpan duration, byte[] output) + { + try + { + + string cachedOutputFile = GetCachedOutputFileName(tabModuleId, cacheKey); + + if (File.Exists(cachedOutputFile)) + { + FileSystemUtils.DeleteFileWithWait(cachedOutputFile, 100, 200); + } + + string attribFile = GetAttribFileName(tabModuleId, cacheKey); + + File.WriteAllBytes(cachedOutputFile, output); + File.WriteAllLines(attribFile, new[] { DateTime.UtcNow.Add(duration).ToString(CultureInfo.InvariantCulture) }); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + + public override void Remove(int tabModuleId) + { + var controller = new ModuleController(); + ModuleInfo tabModule = controller.GetTabModule(tabModuleId); + + int portalId = tabModule.PortalID; + if (portalId == Null.NullInteger) + { + portalId = PortalSettings.Current.PortalId; + } + + string cacheFolder = GetCacheFolder(portalId); + var filesNotDeleted = new StringBuilder(); + int i = 0; + foreach (string File in Directory.GetFiles(cacheFolder, tabModuleId + "_*.*")) + { + if (!FileSystemUtils.DeleteFileWithWait(File, 100, 200)) + { + filesNotDeleted.Append(File + ";"); + } + else + { + i += 1; + } + } + if (filesNotDeleted.Length > 0) + { + throw new IOException("Deleted " + i + " files, however, some files are locked. Could not delete the following files: " + filesNotDeleted); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/ModuleCache/MemoryProvider.cs b/DNN Platform/Library/Services/ModuleCache/MemoryProvider.cs new file mode 100644 index 00000000000..8546de79f97 --- /dev/null +++ b/DNN Platform/Library/Services/ModuleCache/MemoryProvider.cs @@ -0,0 +1,98 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Web.Caching; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Cache; + +#endregion + +namespace DotNetNuke.Services.ModuleCache +{ + public class MemoryProvider : ModuleCachingProvider + { + private const string cachePrefix = "ModuleCache:"; + + private List GetCacheKeys(int tabModuleId) + { + var keys = new List(); + IDictionaryEnumerator CacheEnum = CachingProvider.Instance().GetEnumerator(); + while ((CacheEnum.MoveNext())) + { + if (CacheEnum.Key.ToString().StartsWith(string.Concat(cachePrefix, "|", tabModuleId.ToString(), "|"))) + { + keys.Add(CacheEnum.Key.ToString()); + } + } + return keys; + } + + public override string GenerateCacheKey(int tabModuleId, SortedDictionary varyBy) + { + var cacheKey = new StringBuilder(); + if (varyBy != null) + { + foreach (KeyValuePair kvp in varyBy) + { + cacheKey.Append(string.Concat(kvp.Key.ToLower(), "=", kvp.Value, "|")); + } + } + return string.Concat(cachePrefix, "|", tabModuleId.ToString(), "|", cacheKey.ToString()); + } + + public override int GetItemCount(int tabModuleId) + { + return GetCacheKeys(tabModuleId).Count; + } + + public override byte[] GetModule(int tabModuleId, string cacheKey) + { + return DataCache.GetCache(cacheKey); + } + + public override void PurgeCache(int portalId) + { + DataCache.ClearCache(cachePrefix); + } + + public override void Remove(int tabModuleId) + { + DataCache.ClearCache(string.Concat(cachePrefix, "|", tabModuleId.ToString())); + } + + public override void SetModule(int tabModuleId, string cacheKey, TimeSpan duration, byte[] moduleOutput) + { + DNNCacheDependency dep = null; + DataCache.SetCache(cacheKey, moduleOutput, dep, DateTime.UtcNow.Add(duration), System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, null); + } + + public override void PurgeExpiredItems(int portalId) + { + //throw new NotSupportedException(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/ModuleCache/ModuleCachingProvider.cs b/DNN Platform/Library/Services/ModuleCache/ModuleCachingProvider.cs new file mode 100644 index 00000000000..7bd2c5e34f1 --- /dev/null +++ b/DNN Platform/Library/Services/ModuleCache/ModuleCachingProvider.cs @@ -0,0 +1,104 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Text; + +using DotNetNuke.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.ModuleCache +{ + public abstract class ModuleCachingProvider + { + public static Dictionary GetProviderList() + { + return ComponentFactory.GetComponents(); + } + + public static ModuleCachingProvider Instance(string FriendlyName) + { + return ComponentFactory.GetComponent(FriendlyName); + } + + public static void RemoveItemFromAllProviders(int tabModuleId) + { + foreach (KeyValuePair kvp in GetProviderList()) + { + kvp.Value.Remove(tabModuleId); + } + } + + protected string ByteArrayToString(byte[] arrInput) + { + int i; + var sOutput = new StringBuilder(arrInput.Length); + for (i = 0; i <= arrInput.Length - 1; i++) + { + sOutput.Append(arrInput[i].ToString("X2")); + } + return sOutput.ToString(); + } + + #region Abstract methods + + public abstract string GenerateCacheKey(int tabModuleId, SortedDictionary varyBy); + + public abstract int GetItemCount(int tabModuleId); + + public abstract byte[] GetModule(int tabModuleId, string cacheKey); + + public abstract void Remove(int tabModuleId); + + public abstract void SetModule(int tabModuleId, string cacheKey, TimeSpan duration, byte[] moduleOutput); + + #endregion + + #region Virtual Methods + + public virtual void PurgeCache(int portalId) + { + } + + public virtual void PurgeExpiredItems(int portalId) + { + } + + #endregion + + #region Obsolete Methods + + [Obsolete("This method was deprecated in 5.2.1")] + public virtual void PurgeCache() + { + } + + [Obsolete("This method was deprecated in 5.2.1")] + public virtual void PurgeExpiredItems() + { + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/ModuleCache/PurgeModuleCache.cs b/DNN Platform/Library/Services/ModuleCache/PurgeModuleCache.cs new file mode 100644 index 00000000000..f3d1bc25249 --- /dev/null +++ b/DNN Platform/Library/Services/ModuleCache/PurgeModuleCache.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.ModuleCache +{ + public class PurgeModuleCache : SchedulerClient + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (PurgeModuleCache)); + public PurgeModuleCache(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; //REQUIRED + } + + public override void DoWork() + { + try + { + ArrayList portals; + var portalController = new PortalController(); + portals = portalController.GetPortals(); + foreach (KeyValuePair kvp in ModuleCachingProvider.GetProviderList()) + { + try + { + foreach (PortalInfo portal in portals) + { + kvp.Value.PurgeExpiredItems(portal.PortalID); + ScheduleHistoryItem.AddLogNote(string.Format("Purged Module cache for {0}. ", kvp.Key)); + } + } + catch (NotSupportedException exc) + { + //some Module caching providers don't use this feature + Logger.Debug(exc); + + } + } + ScheduleHistoryItem.Succeeded = true; //REQUIRED + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + + ScheduleHistoryItem.AddLogNote(string.Format("Purging Module cache task failed: {0}.", exc.ToString())); + + //notification that we have errored + Errored(ref exc); //REQUIRED + + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/OutputCache/OutputCacheResponseFilter.cs b/DNN Platform/Library/Services/OutputCache/OutputCacheResponseFilter.cs new file mode 100644 index 00000000000..7c29876aa11 --- /dev/null +++ b/DNN Platform/Library/Services/OutputCache/OutputCacheResponseFilter.cs @@ -0,0 +1,195 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Text; + +#endregion + +namespace DotNetNuke.Services.OutputCache +{ + // helper class to capture the response into a file + public abstract class OutputCacheResponseFilter : Stream + { + private Stream _captureStream; + + #region "Constructors" + + public OutputCacheResponseFilter(Stream filterChain, string cacheKey, TimeSpan cacheDuration, int maxVaryByCount) + { + ChainedStream = filterChain; + CacheKey = cacheKey; + CacheDuration = cacheDuration; + MaxVaryByCount = maxVaryByCount; + _captureStream = CaptureStream; + } + + #endregion + + #region "Public Properties" + + public TimeSpan CacheDuration { get; set; } + + public virtual string CacheKey { get; set; } + + public Stream CaptureStream + { + get + { + return _captureStream; + } + set + { + _captureStream = value; + } + } + + public Stream ChainedStream { get; set; } + + public bool HasErrored { get; set; } + + public int MaxVaryByCount { get; set; } + + public override bool CanRead + { + get + { + return false; + } + } + + public override bool CanSeek + { + get + { + return false; + } + } + + public override bool CanWrite + { + get + { + return true; + } + } + + public override long Length + { + get + { + throw new NotSupportedException(); + } + } + + public override long Position + { + get + { + throw new NotSupportedException(); + } + set + { + throw new NotSupportedException(); + } + } + + #endregion + + #region "Public Methods" + + public override void Flush() + { + ChainedStream.Flush(); + if (HasErrored) + { + return; + } + if ((((_captureStream) != null))) + { + _captureStream.Flush(); + } + } + + public override void Write(byte[] buffer, int offset, int count) + { + ChainedStream.Write(buffer, offset, count); + if (HasErrored) + { + return; + } + if ((((_captureStream) != null))) + { + _captureStream.Write(buffer, offset, count); + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + #endregion + + protected virtual void AddItemToCache(int itemId, string output) + { + } + + protected virtual void RemoveItemFromCache(int itemId) + { + } + + public virtual byte[] StopFiltering(int itemId, bool deleteData) + { + if (HasErrored) + { + return null; + } + + if ((((CaptureStream) != null))) + { + CaptureStream.Position = 0; + var reader = new StreamReader(CaptureStream, Encoding.Default); + string output = reader.ReadToEnd(); + AddItemToCache(itemId, output); + CaptureStream.Close(); + CaptureStream = null; + } + if (deleteData) + { + RemoveItemFromCache(itemId); + } + return null; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/OutputCache/OutputCachingProvider.cs b/DNN Platform/Library/Services/OutputCache/OutputCachingProvider.cs new file mode 100644 index 00000000000..27ee1384429 --- /dev/null +++ b/DNN Platform/Library/Services/OutputCache/OutputCachingProvider.cs @@ -0,0 +1,165 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Web; + +using DotNetNuke.ComponentModel; + +#endregion + +namespace DotNetNuke.Services.OutputCache +{ + public abstract class OutputCachingProvider + { + #region "Protected Methods" + + protected string ByteArrayToString(byte[] arrInput) + { + int i = 0; + var sOutput = new StringBuilder(arrInput.Length); + for (i = 0; i <= arrInput.Length - 1; i++) + { + sOutput.Append(arrInput[i].ToString("X2")); + } + return sOutput.ToString(); + } + + protected string GenerateCacheKeyHash(int tabId, string cacheKey) + { + byte[] hash = Encoding.ASCII.GetBytes(cacheKey); + var md5 = new MD5CryptoServiceProvider(); + hash = md5.ComputeHash(hash); + return string.Concat(tabId.ToString(), "_", ByteArrayToString(hash)); + } + + protected void WriteStreamAsText(HttpContext context, Stream stream, long offset, long length) + { + if ((length < 0)) + { + length = (stream.Length - offset); + } + + if ((length > 0)) + { + if ((offset > 0)) + { + stream.Seek(offset, SeekOrigin.Begin); + } + var buffer = new byte[Convert.ToInt32(length)]; + int count = stream.Read(buffer, 0, Convert.ToInt32(length)); + char[] output = Encoding.UTF8.GetChars(buffer, 0, count); + context.Response.ContentEncoding = Encoding.UTF8; + context.Response.Output.Write(output); + } + } + + #endregion + + #region "Shared/Static Methods" + + public static Dictionary GetProviderList() + { + return ComponentFactory.GetComponents(); + } + + public static OutputCachingProvider Instance(string FriendlyName) + { + return ComponentFactory.GetComponent(FriendlyName); + } + + public static void RemoveItemFromAllProviders(int tabId) + { + foreach (KeyValuePair kvp in GetProviderList()) + { + kvp.Value.Remove(tabId); + } + } + + #endregion + + #region "Abstract Methods" + + public abstract int GetItemCount(int tabId); + + public abstract byte[] GetOutput(int tabId, string cacheKey); + + public abstract OutputCacheResponseFilter GetResponseFilter(int tabId, int maxVaryByCount, Stream responseFilter, string cacheKey, TimeSpan cacheDuration); + + public abstract void Remove(int tabId); + + public abstract void SetOutput(int tabId, string cacheKey, TimeSpan duration, byte[] output); + + public abstract bool StreamOutput(int tabId, string cacheKey, HttpContext context); + + #endregion + + #region "Virtual Methods" + + public virtual string GenerateCacheKey(int tabId, StringCollection includeVaryByKeys, StringCollection excludeVaryByKeys, SortedDictionary varyBy) + { + var cacheKey = new StringBuilder(); + if (varyBy != null) + { + SortedDictionary.Enumerator varyByParms = varyBy.GetEnumerator(); + while ((varyByParms.MoveNext())) + { + string key = varyByParms.Current.Key.ToLower(); + if (includeVaryByKeys.Contains(key) && !excludeVaryByKeys.Contains(key)) + { + cacheKey.Append(string.Concat(key, "=", varyByParms.Current.Value, "|")); + } + } + } + return GenerateCacheKeyHash(tabId, cacheKey.ToString()); + } + + public virtual void PurgeCache(int portalId) + { + } + + public virtual void PurgeExpiredItems(int portalId) + { + } + + #endregion + + #region "Obsolete Methods" + + [Obsolete("This method was deprecated in 5.2.1")] + public virtual void PurgeCache() + { + } + + [Obsolete("This method was deprecated in 5.2.1")] + public virtual void PurgeExpiredItems() + { + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/OutputCache/PurgeOutputCache.cs b/DNN Platform/Library/Services/OutputCache/PurgeOutputCache.cs new file mode 100644 index 00000000000..6f588291a49 --- /dev/null +++ b/DNN Platform/Library/Services/OutputCache/PurgeOutputCache.cs @@ -0,0 +1,83 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.OutputCache +{ + public class PurgeOutputCache : SchedulerClient + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (PurgeOutputCache)); + + public PurgeOutputCache(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; //REQUIRED + } + + public override void DoWork() + { + try + { + ArrayList portals; + var portalController = new PortalController(); + portals = portalController.GetPortals(); + foreach (KeyValuePair kvp in OutputCachingProvider.GetProviderList()) + { + try + { + foreach (PortalInfo portal in portals) + { + kvp.Value.PurgeExpiredItems(portal.PortalID); + ScheduleHistoryItem.AddLogNote(string.Format("Purged output cache for {0}. ", kvp.Key)); + } + } + catch (NotSupportedException exc) + { + //some output caching providers don't use this feature + Logger.Debug(exc); + } + } + ScheduleHistoryItem.Succeeded = true; //REQUIRED + } + catch (Exception exc) //REQUIRED + { + ScheduleHistoryItem.Succeeded = false; //REQUIRED + + ScheduleHistoryItem.AddLogNote(string.Format("Purging output cache task failed: {0}.", exc.ToString())); //OPTIONAL + + //notification that we have errored + Errored(ref exc); + + //log the exception + Exceptions.Exceptions.LogException(exc); //OPTIONAL + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Personalization/Personalization.cs b/DNN Platform/Library/Services/Personalization/Personalization.cs new file mode 100644 index 00000000000..b9ea9de0756 --- /dev/null +++ b/DNN Platform/Library/Services/Personalization/Personalization.cs @@ -0,0 +1,204 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; + +#endregion + +namespace DotNetNuke.Services.Personalization +{ + public class Personalization + { + #region Private Methods + + private static PersonalizationInfo LoadProfile() + { + HttpContext context = HttpContext.Current; + + //First try and load Personalization object from the Context + var personalization = (PersonalizationInfo) context.Items["Personalization"]; + + //If the Personalization object is nothing load it and store it in the context for future calls + if (personalization == null) + { + var _portalSettings = (PortalSettings) context.Items["PortalSettings"]; + + //load the user info object + UserInfo UserInfo = UserController.GetCurrentUserInfo(); + + //get the personalization object + var personalizationController = new PersonalizationController(); + personalization = personalizationController.LoadProfile(UserInfo.UserID, _portalSettings.PortalId); + + //store it in the context + context.Items.Add("Personalization", personalization); + } + return personalization; + } + + #endregion + + #region Public Shared Methods + + /// + /// load users profile and extract value base on naming container and key + /// + /// Container for related set of values + /// Individual profile key + /// + public static object GetProfile(string namingContainer, string key) + { + return GetProfile(LoadProfile(), namingContainer, key); + } + + /// + /// extract value base on naming container and key from PersonalizationInfo object + /// + /// Object containing user personalization info + /// Container for related set of values + /// Individual profile key + /// + public static object GetProfile(PersonalizationInfo personalization, string namingContainer, string key) + { + return personalization != null ? personalization.Profile[namingContainer + ":" + key] : ""; + } + + /// + /// load users profile and extract secure value base on naming container and key + /// + /// Container for related set of values + /// Individual profile key + /// + public static object GetSecureProfile(string namingContainer, string key) + { + return GetSecureProfile(LoadProfile(), namingContainer, key); + } + + /// + /// extract value base on naming container and key from PersonalizationInfo object + /// function will automatically decrypt value to plaintext + /// + /// Object containing user personalization info + /// Container for related set of values + /// Individual profile key + /// + public static object GetSecureProfile(PersonalizationInfo personalization, string namingContainer, string key) + { + if (personalization != null) + { + var ps = new PortalSecurity(); + return ps.DecryptString(personalization.Profile[namingContainer + ":" + key].ToString(), Config.GetDecryptionkey()); + } + return ""; + } + + /// + /// remove value from profile + /// uses namingcontainer and key to locate approriate value + /// + /// Container for related set of values + /// Individual profile key + public static void RemoveProfile(string namingContainer, string key) + { + RemoveProfile(LoadProfile(), namingContainer, key); + } + + /// + /// remove value from users PersonalizationInfo object (if it exists) + /// uses namingcontainer and key to locate approriate value + /// + /// Object containing user personalization info + /// Container for related set of values + /// Individual profile key + public static void RemoveProfile(PersonalizationInfo personalization, string namingContainer, string key) + { + if (personalization != null) + { + (personalization.Profile).Remove(namingContainer + ":" + key); + personalization.IsModified = true; + } + } + + /// + /// persist profile value -use naming container and key to orgainize + /// + /// Container for related set of values + /// Individual profile key + /// Individual profile value + public static void SetProfile(string namingContainer, string key, object value) + { + SetProfile(LoadProfile(), namingContainer, key, value); + } + + /// + /// persist value stored in PersonalizationInfo obhect - use naming container and key to organize + /// + /// Object containing user personalization info + /// Container for related set of values + /// Individual profile key + /// Individual profile value + public static void SetProfile(PersonalizationInfo personalization, string namingContainer, string key, object value) + { + if (personalization != null) + { + personalization.Profile[namingContainer + ":" + key] = value; + personalization.IsModified = true; + } + } + + /// + /// persist profile value -use naming container and key to orgainize + /// function calls an overload which automatically encrypts the value + /// + /// Object containing user personalization info + /// Individual profile key + /// Individual profile value + public static void SetSecureProfile(string namingContainer, string key, object value) + { + SetSecureProfile(LoadProfile(), namingContainer, key, value); + } + + /// + /// persist profile value from PersonalizationInfo object, using naming container and key to organise + /// function will automatically encrypt the value to plaintext + /// + /// Object containing user personalization info + /// Container for related set of values + /// Individual profile key + /// Individual profile value + public static void SetSecureProfile(PersonalizationInfo personalization, string namingContainer, string key, object value) + { + if (personalization != null) + { + var ps = new PortalSecurity(); + personalization.Profile[namingContainer + ":" + key] = ps.EncryptString(value.ToString(), Config.GetDecryptionkey()); + personalization.IsModified = true; + } + } + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Personalization/PersonalizationController.cs b/DNN Platform/Library/Services/Personalization/PersonalizationController.cs new file mode 100644 index 00000000000..1b188049a6e --- /dev/null +++ b/DNN Platform/Library/Services/Personalization/PersonalizationController.cs @@ -0,0 +1,140 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Data; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Personalization +{ + public class PersonalizationController + { + //default implementation relies on HTTPContext + public void LoadProfile(HttpContext httpContext, int userId, int portalId) + { + LoadProfile(new HttpContextWrapper(httpContext), userId, portalId); + } + + public void LoadProfile(HttpContextBase httpContext, int userId, int portalId) + { + if (HttpContext.Current.Items["Personalization"] == null) + { + httpContext.Items.Add("Personalization", LoadProfile(userId, portalId)); + } + } + + //override allows for manipulation of PersonalizationInfo outside of HTTPContext + public PersonalizationInfo LoadProfile(int userId, int portalId) + { + var personalization = new PersonalizationInfo {UserId = userId, PortalId = portalId, IsModified = false}; + string profileData = Null.NullString; + if (userId > Null.NullInteger) + { + IDataReader dr = null; + try + { + dr = DataProvider.Instance().GetProfile(userId, portalId); + if (dr.Read()) + { + profileData = dr["ProfileData"].ToString(); + } + else //does not exist + { + DataProvider.Instance().AddProfile(userId, portalId); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + else + { + //Anon User - so try and use cookie. + HttpContext context = HttpContext.Current; + if (context != null && context.Request.Cookies["DNNPersonalization"] != null) + { + profileData = context.Request.Cookies["DNNPersonalization"].Value; + } + } + if (string.IsNullOrEmpty(profileData)) + { + personalization.Profile = new Hashtable(); + } + else + { + personalization.Profile = Globals.DeserializeHashTableXml(profileData); + } + return personalization; + } + + public void SaveProfile(PersonalizationInfo personalization) + { + SaveProfile(personalization, personalization.UserId, personalization.PortalId); + } + + //default implementation relies on HTTPContext + public void SaveProfile(HttpContext httpContext, int userId, int portalId) + { + var objPersonalization = (PersonalizationInfo) httpContext.Items["Personalization"]; + SaveProfile(objPersonalization, userId, portalId); + } + + //override allows for manipulation of PersonalizationInfo outside of HTTPContext + public void SaveProfile(PersonalizationInfo personalization, int userId, int portalId) + { + if (personalization != null) + { + if (personalization.IsModified) + { + string ProfileData = Globals.SerializeHashTableXml(personalization.Profile); + if (userId > Null.NullInteger) + { + DataProvider.Instance().UpdateProfile(userId, portalId, ProfileData); + } + else + { + //Anon User - so try and use cookie. + HttpContext context = HttpContext.Current; + if (context != null) + { + var personalizationCookie = new HttpCookie("DNNPersonalization") + {Value = ProfileData, Expires = DateTime.Now.AddDays(30)}; + context.Response.Cookies.Add(personalizationCookie); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Personalization/PersonalizationInfo.cs b/DNN Platform/Library/Services/Personalization/PersonalizationInfo.cs new file mode 100644 index 00000000000..d5efecbf11e --- /dev/null +++ b/DNN Platform/Library/Services/Personalization/PersonalizationInfo.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Personalization +{ + [Serializable] + public class PersonalizationInfo + { + #region Private Members + + #endregion + + #region Public Properties + + public int UserId { get; set; } + + public int PortalId { get; set; } + + public bool IsModified { get; set; } + + public Hashtable Profile { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/DNNScheduler.cs b/DNN Platform/Library/Services/Scheduling/DNNScheduler.cs new file mode 100644 index 00000000000..1818d7bc993 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/DNNScheduler.cs @@ -0,0 +1,297 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Threading; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Framework; + +using Microsoft.VisualBasic; + +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + public class DNNScheduler : SchedulingProvider + { + + #region Public Properties + + public override Dictionary Settings + { + get + { + return ComponentFactory.GetComponentSettings() as Dictionary; + } + } + + #endregion + + #region Private Methods + + private bool CanRunOnThisServer(string servers) + { + string lwrServers = ""; + if (servers != null) + { + lwrServers = servers.ToLower(); + } + if (String.IsNullOrEmpty(lwrServers) || lwrServers.Contains(Globals.ServerName.ToLower())) + { + return true; + } + + return false; + } + + #endregion + + #region Public Methods + + public override int AddSchedule(ScheduleItem scheduleItem) + { + //Remove item from queue + Scheduler.CoreScheduler.RemoveFromScheduleQueue(scheduleItem); + //save item + scheduleItem.ScheduleID = SchedulingController.AddSchedule(scheduleItem.TypeFullName, + scheduleItem.TimeLapse, + scheduleItem.TimeLapseMeasurement, + scheduleItem.RetryTimeLapse, + scheduleItem.RetryTimeLapseMeasurement, + scheduleItem.RetainHistoryNum, + scheduleItem.AttachToEvent, + scheduleItem.CatchUpEnabled, + scheduleItem.Enabled, + scheduleItem.ObjectDependencies, + scheduleItem.Servers, + scheduleItem.FriendlyName); + //Add schedule to queue + RunScheduleItemNow(scheduleItem); + + //Return Id + return scheduleItem.ScheduleID; + } + + public override void AddScheduleItemSetting(int scheduleID, string name, string value) + { + SchedulingController.AddScheduleItemSetting(scheduleID, name, value); + } + + public override void DeleteSchedule(ScheduleItem scheduleItem) + { + SchedulingController.DeleteSchedule(scheduleItem.ScheduleID); + Scheduler.CoreScheduler.RemoveFromScheduleQueue(scheduleItem); + DataCache.RemoveCache("ScheduleLastPolled"); + } + + public override void ExecuteTasks() + { + if (Enabled) + { + Scheduler.CoreScheduler.InitializeThreadPool(Debug, MaxThreads); + Scheduler.CoreScheduler.KeepRunning = true; + Scheduler.CoreScheduler.KeepThreadAlive = false; + Scheduler.CoreScheduler.Start(); + } + } + + public override int GetActiveThreadCount() + { + return SchedulingController.GetActiveThreadCount(); + } + + public override int GetFreeThreadCount() + { + return SchedulingController.GetFreeThreadCount(); + } + + public override int GetMaxThreadCount() + { + return SchedulingController.GetMaxThreadCount(); + } + + public override ScheduleItem GetNextScheduledTask(string server) + { + return SchedulingController.GetNextScheduledTask(server); + } + + public override ArrayList GetSchedule() + { + return new ArrayList(SchedulingController.GetSchedule().ToArray()); + } + + public override ArrayList GetSchedule(string server) + { + return new ArrayList(SchedulingController.GetSchedule(server).ToArray()); + } + + public override ScheduleItem GetSchedule(int scheduleID) + { + return SchedulingController.GetSchedule(scheduleID); + } + + public override ScheduleItem GetSchedule(string typeFullName, string server) + { + return SchedulingController.GetSchedule(typeFullName, server); + } + + public override ArrayList GetScheduleHistory(int scheduleID) + { + return new ArrayList(SchedulingController.GetScheduleHistory(scheduleID).ToArray()); + } + + public override Hashtable GetScheduleItemSettings(int scheduleID) + { + return SchedulingController.GetScheduleItemSettings(scheduleID); + } + + public override Collection GetScheduleProcessing() + { + return SchedulingController.GetScheduleProcessing(); + } + + public override Collection GetScheduleQueue() + { + return SchedulingController.GetScheduleQueue(); + } + + public override ScheduleStatus GetScheduleStatus() + { + return SchedulingController.GetScheduleStatus(); + } + + public override void Halt(string sourceOfHalt) + { + Scheduler.CoreScheduler.InitializeThreadPool(Debug, MaxThreads); + Scheduler.CoreScheduler.Halt(sourceOfHalt); + Scheduler.CoreScheduler.KeepRunning = false; + } + + public override void PurgeScheduleHistory() + { + Scheduler.CoreScheduler.InitializeThreadPool(false, MaxThreads); + Scheduler.CoreScheduler.PurgeScheduleHistory(); + } + + public override void ReStart(string sourceOfRestart) + { + Halt(sourceOfRestart); + StartAndWaitForResponse(); + } + + public override void RunEventSchedule(EventName eventName) + { + if (Enabled) + { + Scheduler.CoreScheduler.InitializeThreadPool(Debug, MaxThreads); + Scheduler.CoreScheduler.RunEventSchedule(eventName); + } + } + + public override void RunScheduleItemNow(ScheduleItem scheduleItem) + { + //Remove item from queue + Scheduler.CoreScheduler.RemoveFromScheduleQueue(scheduleItem); + var scheduleHistoryItem = new ScheduleHistoryItem(scheduleItem); + scheduleHistoryItem.NextStart = DateTime.Now; + if (scheduleHistoryItem.TimeLapse != Null.NullInteger && scheduleHistoryItem.TimeLapseMeasurement != Null.NullString && scheduleHistoryItem.Enabled && + CanRunOnThisServer(scheduleItem.Servers)) + { + scheduleHistoryItem.ScheduleSource = ScheduleSource.STARTED_FROM_SCHEDULE_CHANGE; + Scheduler.CoreScheduler.AddToScheduleQueue(scheduleHistoryItem); + } + DataCache.RemoveCache("ScheduleLastPolled"); + } + + public override void Start() + { + if (Enabled) + { + Scheduler.CoreScheduler.InitializeThreadPool(Debug, MaxThreads); + Scheduler.CoreScheduler.KeepRunning = true; + Scheduler.CoreScheduler.KeepThreadAlive = true; + Scheduler.CoreScheduler.Start(); + } + } + + public override void StartAndWaitForResponse() + { + if (Enabled) + { + var newThread = new Thread(Start) {IsBackground = true}; + newThread.Start(); + + //wait for up to 30 seconds for thread + //to start up + for (int i = 0; i <= 30; i++) + { + if (GetScheduleStatus() != ScheduleStatus.STOPPED) + { + return; + } + Thread.Sleep(1000); + } + } + } + + public override void UpdateSchedule(ScheduleItem scheduleItem) + { + //Remove item from queue + Scheduler.CoreScheduler.RemoveFromScheduleQueue(scheduleItem); + //save item + SchedulingController.UpdateSchedule(scheduleItem.ScheduleID, + scheduleItem.TypeFullName, + scheduleItem.TimeLapse, + scheduleItem.TimeLapseMeasurement, + scheduleItem.RetryTimeLapse, + scheduleItem.RetryTimeLapseMeasurement, + scheduleItem.RetainHistoryNum, + scheduleItem.AttachToEvent, + scheduleItem.CatchUpEnabled, + scheduleItem.Enabled, + scheduleItem.ObjectDependencies, + scheduleItem.Servers, + scheduleItem.FriendlyName); + //Update items that are already scheduled + var futureHistory = GetScheduleHistory(scheduleItem.ScheduleID).Cast().Where(h => h.NextStart > DateTime.Now); + + foreach (var scheduleHistoryItem in futureHistory) + { + scheduleHistoryItem.NextStart = scheduleItem.NextStart; + SchedulingController.UpdateScheduleHistory(scheduleHistoryItem); + } + + + //Add schedule to queue + RunScheduleItemNow(scheduleItem); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/ProcessGroup.cs b/DNN Platform/Library/Services/Scheduling/ProcessGroup.cs new file mode 100644 index 00000000000..c1d8794b496 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/ProcessGroup.cs @@ -0,0 +1,211 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Reflection; +using System.Threading; +using System.Web.Compilation; + +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + public class ProcessGroup + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ProcessGroup)); + //'''''''''''''''''''''''''''''''''''''''''''''''''' + //This class represents a process group for + //our threads to run in. + //'''''''''''''''''''''''''''''''''''''''''''''''''' + #region Delegates + + public delegate void CompletedEventHandler(); + + #endregion + + private static int numberOfProcessesInQueue; + private static int numberOfProcesses; + private static int processesCompleted; + private static int ticksElapsed; + + private static int GetTicksElapsed + { + get + { + return ticksElapsed; + } + } + + private static int GetProcessesCompleted + { + get + { + return processesCompleted; + } + } + + private static int GetProcessesInQueue + { + get + { + return numberOfProcessesInQueue; + } + } + + public event CompletedEventHandler Completed; + + public void Run(ScheduleHistoryItem objScheduleHistoryItem) + { + SchedulerClient Process = null; + try + { + //This is called from RunPooledThread() + ticksElapsed = Environment.TickCount - ticksElapsed; + Process = GetSchedulerClient(objScheduleHistoryItem.TypeFullName, objScheduleHistoryItem); + Process.ScheduleHistoryItem = objScheduleHistoryItem; + + //Set up the handlers for the CoreScheduler + Process.ProcessStarted += Scheduler.CoreScheduler.WorkStarted; + Process.ProcessProgressing += Scheduler.CoreScheduler.WorkProgressing; + Process.ProcessCompleted += Scheduler.CoreScheduler.WorkCompleted; + Process.ProcessErrored += Scheduler.CoreScheduler.WorkErrored; + //This kicks off the DoWork method of the class + //type specified in the configuration. + + Process.Started(); + try + { + Process.ScheduleHistoryItem.Succeeded = false; + Process.DoWork(); + } + catch (Exception exc) + { + //in case the scheduler client + //didn't have proper exception handling + //make sure we fire the Errored event + Logger.Error(exc); + + if (Process != null) + { + if (Process.ScheduleHistoryItem != null) + { + Process.ScheduleHistoryItem.Succeeded = false; + } + Process.Errored(ref exc); + } + } + if (Process.ScheduleHistoryItem.Succeeded) + { + Process.Completed(); + } + + //If all processes in this ProcessGroup have + //completed, set the ticksElapsed and raise + //the Completed event. + //I don't think this is necessary with the + //other events. I'll leave it for now and + //will probably take it out later. + + if (processesCompleted == numberOfProcesses) + { + if (processesCompleted == numberOfProcesses) + { + ticksElapsed = Environment.TickCount - ticksElapsed; + if (Completed != null) + { + Completed(); + } + } + } + } + catch (Exception exc) + { + //in case the scheduler client + //didn't have proper exception handling + //make sure we fire the Errored event + if (Process != null) + { + if (Process.ScheduleHistoryItem != null) + { + Process.ScheduleHistoryItem.Succeeded = false; + } + Process.Errored(ref exc); + } + } + finally + { + //Track how many processes have completed for + //this instanciation of the ProcessGroup + numberOfProcessesInQueue -= 1; + processesCompleted += 1; + } + } + + private SchedulerClient GetSchedulerClient(string strProcess, ScheduleHistoryItem objScheduleHistoryItem) + { + //This is a method to encapsulate returning + //an object whose class inherits SchedulerClient. + Type t = BuildManager.GetType(strProcess, true, true); + var param = new ScheduleHistoryItem[1]; + param[0] = objScheduleHistoryItem; + var types = new Type[1]; + + //Get the constructor for the Class + types[0] = typeof (ScheduleHistoryItem); + ConstructorInfo objConstructor; + objConstructor = t.GetConstructor(types); + + //Return an instance of the class as an object + return (SchedulerClient) objConstructor.Invoke(param); + } + + //This subroutine is callback for Threadpool.QueueWorkItem. This is the necessary + //subroutine signature for QueueWorkItem, and Run() is proper for creating a Thread + //so the two subroutines cannot be combined, so instead just call Run from here. + private void RunPooledThread(object objScheduleHistoryItem) + { + Run((ScheduleHistoryItem) objScheduleHistoryItem); + } + + //Add a queue request to Threadpool with a + //callback to RunPooledThread which calls Run() + public void AddQueueUserWorkItem(ScheduleItem s) + { + numberOfProcessesInQueue += 1; + numberOfProcesses += 1; + var obj = new ScheduleHistoryItem(s); + try + { + //Create a callback to subroutine RunPooledThread + WaitCallback callback = RunPooledThread; + //And put in a request to ThreadPool to run the process. + ThreadPool.QueueUserWorkItem(callback, obj); + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/PurgeScheduleHistory.cs b/DNN Platform/Library/Services/Scheduling/PurgeScheduleHistory.cs new file mode 100644 index 00000000000..04c684cce30 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/PurgeScheduleHistory.cs @@ -0,0 +1,63 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + public class PurgeScheduleHistory : SchedulerClient + { + public PurgeScheduleHistory(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + public override void DoWork() + { + try + { + //notification that the event is progressing + Progressing(); + + SchedulingProvider.Instance().PurgeScheduleHistory(); + + //update the result to success since no exception was thrown + ScheduleHistoryItem.Succeeded = true; + ScheduleHistoryItem.AddLogNote("Schedule history purged."); + } + catch (Exception exc) + { + ScheduleHistoryItem.Succeeded = false; + ScheduleHistoryItem.AddLogNote("Schedule history purge failed." + exc); + ScheduleHistoryItem.Succeeded = false; + + //notification that we have errored + Errored(ref exc); + + //log the exception + Exceptions.Exceptions.LogException(exc); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/ScheduleHistoryItem.cs b/DNN Platform/Library/Services/Scheduling/ScheduleHistoryItem.cs new file mode 100644 index 00000000000..3c10693082b --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/ScheduleHistoryItem.cs @@ -0,0 +1,245 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Text; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + [Serializable] + public class ScheduleHistoryItem : ScheduleItem + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ScheduleHistoryItem)); + private StringBuilder _LogNotes; + private int _ScheduleHistoryID; + private string _Server; + private DateTime _StartDate; + private bool _Succeeded; + + public ScheduleHistoryItem() + { + _ScheduleHistoryID = Null.NullInteger; + _StartDate = Null.NullDate; + EndDate = Null.NullDate; + _Succeeded = Null.NullBoolean; + _LogNotes = new StringBuilder(); + _Server = Null.NullString; + } + + public ScheduleHistoryItem(ScheduleItem objScheduleItem) + { + AttachToEvent = objScheduleItem.AttachToEvent; + CatchUpEnabled = objScheduleItem.CatchUpEnabled; + Enabled = objScheduleItem.Enabled; + NextStart = objScheduleItem.NextStart; + ObjectDependencies = objScheduleItem.ObjectDependencies; + ProcessGroup = objScheduleItem.ProcessGroup; + RetainHistoryNum = objScheduleItem.RetainHistoryNum; + RetryTimeLapse = objScheduleItem.RetryTimeLapse; + RetryTimeLapseMeasurement = objScheduleItem.RetryTimeLapseMeasurement; + ScheduleID = objScheduleItem.ScheduleID; + ScheduleSource = objScheduleItem.ScheduleSource; + ThreadID = objScheduleItem.ThreadID; + TimeLapse = objScheduleItem.TimeLapse; + TimeLapseMeasurement = objScheduleItem.TimeLapseMeasurement; + TypeFullName = objScheduleItem.TypeFullName; + Servers = objScheduleItem.Servers; + FriendlyName = objScheduleItem.FriendlyName; + _ScheduleHistoryID = Null.NullInteger; + _StartDate = Null.NullDate; + EndDate = Null.NullDate; + _Succeeded = Null.NullBoolean; + _LogNotes = new StringBuilder(); + _Server = Null.NullString; + } + + public double ElapsedTime + { + get + { + try + { + if (EndDate == Null.NullDate && _StartDate != Null.NullDate) + { + return DateTime.Now.Subtract(_StartDate).TotalSeconds; + } + else if (_StartDate != Null.NullDate) + { + return EndDate.Subtract(_StartDate).TotalSeconds; + } + else + { + return 0; + } + } + catch + { + return 0; + } + } + } + + public DateTime EndDate { get; set; } + + public string LogNotes + { + get + { + return _LogNotes.ToString(); + } + set + { + _LogNotes = new StringBuilder(value); + } + } + + public bool Overdue + { + get + { + if (NextStart < DateTime.Now && EndDate == Null.NullDate) + { + return true; + } + else + { + return false; + } + } + } + + public double OverdueBy + { + get + { + try + { + if (NextStart <= DateTime.Now && EndDate == Null.NullDate) + { + return Math.Round(DateTime.Now.Subtract(NextStart).TotalSeconds); + } + else + { + return 0; + } + } + catch + { + return 0; + } + } + } + + public double RemainingTime + { + get + { + try + { + if (NextStart > DateTime.Now && EndDate == Null.NullDate) + { + return Math.Round(NextStart.Subtract(DateTime.Now).TotalSeconds); + } + else + { + return 0; + } + } + catch + { + return 0; + } + } + } + + public int ScheduleHistoryID + { + get + { + return _ScheduleHistoryID; + } + set + { + _ScheduleHistoryID = value; + } + } + + public string Server + { + get + { + return _Server; + } + set + { + _Server = value; + } + } + + public DateTime StartDate + { + get + { + return _StartDate; + } + set + { + _StartDate = value; + } + } + + public bool Succeeded + { + get + { + return _Succeeded; + } + set + { + _Succeeded = value; + } + } + + public virtual void AddLogNote(string notes) + { + _LogNotes.Append(notes); + Logger.Trace(notes.Replace(@"
    ", Environment.NewLine)); + } + + public override void Fill(IDataReader dr) + { + ScheduleHistoryID = Null.SetNullInteger(dr["ScheduleHistoryID"]); + StartDate = Null.SetNullDateTime(dr["StartDate"]); + EndDate = Null.SetNullDateTime(dr["EndDate"]); + Succeeded = Null.SetNullBoolean(dr["Succeeded"]); + LogNotes = Null.SetNullString(dr["LogNotes"]); + Server = Null.SetNullString(dr["Server"]); + base.FillInternal(dr); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/ScheduleHistorySortStartDate.cs b/DNN Platform/Library/Services/Scheduling/ScheduleHistorySortStartDate.cs new file mode 100644 index 00000000000..3db8bbbe8a8 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/ScheduleHistorySortStartDate.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + /// ----------------------------------------------------------------------------- + /// + /// The ScheduleHistorySortStartDate Class is a custom IComparer Implementation + /// used to sort the Schedule Items + /// + /// + /// + /// + /// [cnurse] 9/28/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + public class ScheduleHistorySortStartDate : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((ScheduleHistoryItem) y).StartDate.CompareTo(((ScheduleHistoryItem) x).StartDate); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Scheduling/ScheduleItem.cs b/DNN Platform/Library/Services/Scheduling/ScheduleItem.cs new file mode 100644 index 00000000000..f7aad3f40b7 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/ScheduleItem.cs @@ -0,0 +1,223 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + [Serializable] + public class ScheduleItem : BaseEntityInfo, IHydratable + { + #region "Private Members" + + private DateTime _NextStart; + private Hashtable _ScheduleItemSettings; + + #endregion + + #region "Constructors" + + public ScheduleItem() + { + ScheduleID = Null.NullInteger; + TypeFullName = Null.NullString; + TimeLapse = Null.NullInteger; + TimeLapseMeasurement = Null.NullString; + RetryTimeLapse = Null.NullInteger; + RetryTimeLapseMeasurement = Null.NullString; + ObjectDependencies = Null.NullString; + RetainHistoryNum = Null.NullInteger; + _NextStart = Null.NullDate; + CatchUpEnabled = Null.NullBoolean; + Enabled = Null.NullBoolean; + AttachToEvent = Null.NullString; + ThreadID = Null.NullInteger; + ProcessGroup = Null.NullInteger; + Servers = Null.NullString; + } + + #endregion + + + #region "Persisted Properties" + + public string AttachToEvent { get; set; } + + public bool CatchUpEnabled { get; set; } + + public bool Enabled { get; set; } + + public string FriendlyName { get; set; } + + public DateTime NextStart + { + get + { + if (_NextStart == Null.NullDate) + { + _NextStart = DateTime.Now; + } + return _NextStart; + } + set + { + _NextStart = value; + } + } + + public string ObjectDependencies { get; set; } + + public int RetainHistoryNum { get; set; } + + public int RetryTimeLapse { get; set; } + + public string RetryTimeLapseMeasurement { get; set; } + + public int ScheduleID { get; set; } + + public string Servers { get; set; } + + public int TimeLapse { get; set; } + + public string TimeLapseMeasurement { get; set; } + + public string TypeFullName { get; set; } + + public int ProcessGroup { get; set; } + + public ScheduleSource ScheduleSource { get; set; } + + public int ThreadID { get; set; } + + #endregion + + #region IHydratable Members + + public int KeyID + { + get + { + return ScheduleID; + } + set + { + ScheduleID = value; + } + } + + public virtual void Fill(IDataReader dr) + { + FillInternal(dr); + } + + #endregion + + public bool HasObjectDependencies(string strObjectDependencies) + { + if (strObjectDependencies.IndexOf(",") > -1) + { + string[] a; + a = strObjectDependencies.ToLower().Split(','); + int i; + for (i = 0; i <= a.Length - 1; i++) + { + if (ObjectDependencies.ToLower().IndexOf(a[i].Trim()) > -1) + { + return true; + } + } + } + else if (ObjectDependencies.ToLower().IndexOf(strObjectDependencies.ToLower()) > -1) + { + return true; + } + return false; + } + + #region "Public Methods" + + public void AddSetting(string Key, string Value) + { + _ScheduleItemSettings.Add(Key, Value); + } + + public virtual string GetSetting(string Key) + { + if (_ScheduleItemSettings == null) + { + GetSettings(); + } + if (_ScheduleItemSettings != null && _ScheduleItemSettings.ContainsKey(Key)) + { + return Convert.ToString(_ScheduleItemSettings[Key]); + } + else + { + return ""; + } + } + + public virtual Hashtable GetSettings() + { + _ScheduleItemSettings = SchedulingProvider.Instance().GetScheduleItemSettings(ScheduleID); + return _ScheduleItemSettings; + } + + protected override void FillInternal(IDataReader dr) + { + ScheduleID = Null.SetNullInteger(dr["ScheduleID"]); + FriendlyName = Null.SetNullString(dr["FriendlyName"]); + TypeFullName = Null.SetNullString(dr["TypeFullName"]); + TimeLapse = Null.SetNullInteger(dr["TimeLapse"]); + TimeLapseMeasurement = Null.SetNullString(dr["TimeLapseMeasurement"]); + RetryTimeLapse = Null.SetNullInteger(dr["RetryTimeLapse"]); + RetryTimeLapseMeasurement = Null.SetNullString(dr["RetryTimeLapseMeasurement"]); + ObjectDependencies = Null.SetNullString(dr["ObjectDependencies"]); + AttachToEvent = Null.SetNullString(dr["AttachToEvent"]); + RetainHistoryNum = Null.SetNullInteger(dr["RetainHistoryNum"]); + CatchUpEnabled = Null.SetNullBoolean(dr["CatchUpEnabled"]); + Enabled = Null.SetNullBoolean(dr["Enabled"]); + Servers = Null.SetNullString(dr["Servers"]); + try + { + NextStart = Null.SetNullDateTime(dr["NextStart"]); + } + catch (IndexOutOfRangeException) + { + //Ignore + } + + //Fill BaseEntityInfo + base.FillInternal(dr); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/ScheduleStatusSortRemainingTimeDescending.cs b/DNN Platform/Library/Services/Scheduling/ScheduleStatusSortRemainingTimeDescending.cs new file mode 100644 index 00000000000..29f7a266d79 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/ScheduleStatusSortRemainingTimeDescending.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + /// ----------------------------------------------------------------------------- + /// + /// The ScheduleStatusSortRemainingTimeDescending Class is a custom IComparer Implementation + /// used to sort the Schedule Items + /// + /// + /// + /// + /// [cnurse] 9/28/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + public class ScheduleStatusSortRemainingTimeDescending : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + return ((ScheduleHistoryItem) x).RemainingTime.CompareTo(((ScheduleHistoryItem) y).RemainingTime); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Scheduling/Scheduler.cs b/DNN Platform/Library/Services/Scheduling/Scheduler.cs new file mode 100644 index 00000000000..f250621b294 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/Scheduler.cs @@ -0,0 +1,1248 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Log.EventLog; +using Microsoft.VisualBasic; + +namespace DotNetNuke.Services.Scheduling +{ + internal static class Scheduler + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Scheduler)); + internal static class CoreScheduler + { + //This is the heart of the scheduler mechanism. + //This class manages running new events according + //to the schedule. + // + //This class can also react to the three + //scheduler events (Started, Progressing and Completed) + private static bool _threadPoolInitialized; + + //The MaxThreadCount establishes the maximum + //threads you want running simultaneously + //for spawning SchedulerClient processes + private static int _maxThreadCount; + private static int _activeThreadCount; + + //If KeepRunning gets switched to false, + //the scheduler stops running. + private static bool _forceReloadSchedule; + private static bool _debug; + + private static int _numberOfProcessGroups; + + private static readonly SharedList ScheduleQueue; + private static readonly SharedList ScheduleInProgress; + + //This is our array that holds the process group + //where our threads will be kicked off. + private static ProcessGroup[] _processGroup; + + //A ReaderWriterLock will protect our objects + //in memory from being corrupted by simultaneous + //thread operations. This block of code below + //establishes variables to help keep track + //of the ReaderWriter locks. + private static int _readerTimeouts; + private static int _writerTimeouts; + private static readonly TimeSpan LockTimeout = TimeSpan.FromSeconds(45); + private static readonly ReaderWriterLock StatusLock = new ReaderWriterLock(); + private static ScheduleStatus _status = ScheduleStatus.STOPPED; + + //If KeepRunning gets switched to false, + //the scheduler stops running. + public static bool KeepThreadAlive = true; + public static bool KeepRunning = true; + + static CoreScheduler() + { + var lockStrategy = new ReaderWriterLockStrategy(LockRecursionPolicy.SupportsRecursion); + + ScheduleQueue = new SharedList(lockStrategy); + ScheduleInProgress = new SharedList(lockStrategy); + } + + /// + /// tracks how many threads we have free to work with at any given time. + /// + public static int FreeThreads + { + get + { + return _maxThreadCount - _activeThreadCount; + } + } + + /// + /// adds an item to the collection of schedule items in progress. + /// + /// Item to add + /// Thread Safe + private static void AddToScheduleInProgress(ScheduleHistoryItem scheduleHistoryItem) + { + if (!(ScheduleInProgressContains(scheduleHistoryItem))) + { + try + { + using (ScheduleInProgress.GetWriteLock(LockTimeout)) + { + if (!(ScheduleInProgressContains(scheduleHistoryItem))) + { + ScheduleInProgress.Add(scheduleHistoryItem); + } + } + } + catch (ApplicationException ex) + { + // The writer lock request timed out. + Interlocked.Increment(ref _writerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + } + } + + private static int GetProcessGroup() + { + //return a random process group + var r = new Random(); + return r.Next(0, _numberOfProcessGroups - 1); + } + + private static bool IsInProgress(ScheduleItem scheduleItem) + { + try + { + using (ScheduleInProgress.GetReadLock(LockTimeout)) + { + return ScheduleInProgress.Any(si => si.ScheduleID == scheduleItem.ScheduleID); + } + } + catch (ApplicationException ex) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + Logger.Debug(ex); + return false; + } + } + + /// + /// Removes an item from the collection of schedule items in progress. + /// + /// + /// Thread Safe + private static void RemoveFromScheduleInProgress(ScheduleItem scheduleItem) + { + try + { + using (ScheduleInProgress.GetWriteLock(LockTimeout)) + { + ScheduleHistoryItem item = ScheduleInProgress.Where(si => si.ScheduleID == scheduleItem.ScheduleID).SingleOrDefault(); + if (item != null) + { + ScheduleInProgress.Remove(item); + } + } + } + catch (ApplicationException ex) + { + // The writer lock request timed out. + Interlocked.Increment(ref _writerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + } + + private static bool ScheduleInProgressContains(ScheduleHistoryItem scheduleHistoryItem) + { + try + { + using (ScheduleInProgress.GetReadLock(LockTimeout)) + { + return ScheduleInProgress.Any(si => si.ScheduleID == scheduleHistoryItem.ScheduleID); + } + } + catch (ApplicationException ex) + { + Interlocked.Increment(ref _readerTimeouts); + Exceptions.Exceptions.LogException(ex); + return false; + } + } + + private static bool ScheduleQueueContains(ScheduleItem objScheduleItem) + { + try + { + using (ScheduleQueue.GetReadLock(LockTimeout)) + { + return ScheduleQueue.Any(si => si.ScheduleID == objScheduleItem.ScheduleID); + } + } + catch (ApplicationException ex) + { + Interlocked.Increment(ref _readerTimeouts); + Exceptions.Exceptions.LogException(ex); + return false; + } + } + + internal static bool IsInQueue(ScheduleItem scheduleItem) + { + try + { + using (ScheduleQueue.GetReadLock(LockTimeout)) + { + return ScheduleQueue.Any(si => si.ScheduleID == scheduleItem.ScheduleID); + } + } + catch (ApplicationException) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + return false; + } + } + + public static ScheduleHistoryItem AddScheduleHistory(ScheduleHistoryItem scheduleHistoryItem) + { + try + { + int scheduleHistoryID = SchedulingController.AddScheduleHistory(scheduleHistoryItem); + scheduleHistoryItem.ScheduleHistoryID = scheduleHistoryID; + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + + return scheduleHistoryItem; + } + + /// + /// Adds an item to the collection of schedule items in queue. + /// + /// + /// Thread Safe + public static void AddToScheduleQueue(ScheduleHistoryItem scheduleHistoryItem) + { + if (!ScheduleQueueContains(scheduleHistoryItem)) + { + try + { + //objQueueReadWriteLock.AcquireWriterLock(WriteTimeout) + using (ScheduleQueue.GetWriteLock(LockTimeout)) + { + //Do a second check just in case + if (!ScheduleQueueContains(scheduleHistoryItem) && + !IsInProgress(scheduleHistoryItem)) + { + // It is safe for this thread to read or write + // from the shared resource. + ScheduleQueue.Add(scheduleHistoryItem); + } + } + } + catch (ApplicationException ex) + { + // The writer lock request timed out. + Interlocked.Increment(ref _writerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + } + } + + private delegate void AddToScheduleInProgressDelegate(ScheduleHistoryItem item); + public static void FireEvents() + { + //This method uses a thread pool to + //call the SchedulerClient methods that need + //to be called. + + //For each item in the queue that there + //is an open thread for, set the object + //in the array to a new ProcessGroup object. + //Pass in the ScheduleItem to the ProcessGroup + //so the ProcessGroup can pass it around for + //logging and notifications. + lock (ScheduleQueue) + { + var scheduleList = new List(); + using (ScheduleQueue.GetReadLock(LockTimeout)) + { + foreach (ScheduleItem scheduleItem in ScheduleQueue) + { + scheduleList.Add(scheduleItem); + } + } + + int numToRun = scheduleList.Count; + int numRun = 0; + + foreach (ScheduleItem scheduleItem in scheduleList) + { + if (!KeepRunning) + { + return; + } + + int processGroup = GetProcessGroup(); + + if (scheduleItem.NextStart <= DateTime.Now && + scheduleItem.Enabled && + !IsInProgress(scheduleItem) && + !HasDependenciesConflict(scheduleItem) && + numRun < numToRun) + { + scheduleItem.ProcessGroup = processGroup; + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) + { + scheduleItem.ScheduleSource = ScheduleSource.STARTED_FROM_TIMER; + } + else if (SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD) + { + scheduleItem.ScheduleSource = ScheduleSource.STARTED_FROM_BEGIN_REQUEST; + } + + var delegateFunc = new AddToScheduleInProgressDelegate(AddToScheduleInProgress); + var result = delegateFunc.BeginInvoke(new ScheduleHistoryItem(scheduleItem), null, null); + Thread.Sleep(1000); + + _processGroup[processGroup].AddQueueUserWorkItem(scheduleItem); + + LogEventAddedToProcessGroup(scheduleItem); + numRun += 1; + } + else + { + LogWhyTaskNotRun(scheduleItem); + } + } + } + } + + private static void LogWhyTaskNotRun(ScheduleItem scheduleItem) + { + if (_debug) + { + bool appended = false; + var strDebug = new StringBuilder("Task not run because "); + if (!(scheduleItem.NextStart <= DateTime.Now)) + { + strDebug.Append(" task is scheduled for " + scheduleItem.NextStart); + appended = true; + } + + + if (!scheduleItem.Enabled) + { + if (appended) + { + strDebug.Append(" and"); + } + strDebug.Append(" task is not enabled"); + appended = true; + } + if (IsInProgress(scheduleItem)) + { + if (appended) + { + strDebug.Append(" and"); + } + strDebug.Append(" task is already in progress"); + appended = true; + } + if (HasDependenciesConflict(scheduleItem)) + { + if (appended) + { + strDebug.Append(" and"); + } + strDebug.Append(" task has conflicting dependency"); + } + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("EVENT NOT RUN REASON", strDebug.ToString()); + objEventLogInfo.AddProperty("SCHEDULE ID", scheduleItem.ScheduleID.ToString()); + objEventLogInfo.AddProperty("TYPE FULL NAME", scheduleItem.TypeFullName); + objEventLogInfo.LogTypeKey = "DEBUG"; + objEventLog.AddLog(objEventLogInfo); + } + } + + private static void LogEventAddedToProcessGroup(ScheduleItem scheduleItem) + { + if (_debug) + { + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("EVENT ADDED TO PROCESS GROUP " + scheduleItem.ProcessGroup, scheduleItem.TypeFullName); + objEventLogInfo.AddProperty("SCHEDULE ID", scheduleItem.ScheduleID.ToString()); + objEventLogInfo.LogTypeKey = "DEBUG"; + objEventLog.AddLog(objEventLogInfo); + } + } + + public static int GetActiveThreadCount() + { + return _activeThreadCount; + } + + public static int GetFreeThreadCount() + { + return FreeThreads; + } + + public static int GetMaxThreadCount() + { + return _maxThreadCount; + } + + /// + /// Gets a copy of the collection of schedule items in progress. + /// + /// Copy of the schedule items currently in progress + /// This is a snapshot of the collection scheduled items could start or complete at any time + public static Collection GetScheduleInProgress() + { + var c = new Collection(); + try + { + using (ScheduleInProgress.GetReadLock(LockTimeout)) + { + foreach (ScheduleHistoryItem item in ScheduleInProgress) + { + c.Add(item, item.ScheduleID.ToString(), null, null); + } + } + } + catch (ApplicationException ex) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + return c; + } + + /// + /// Gets the number of items in the collection of schedule items in progress. + /// + /// Number of items in progress + /// Thread Safe + /// This count is a snapshot and may change at any time + /// + public static int GetScheduleInProgressCount() + { + try + { + using (ScheduleInProgress.GetReadLock(LockTimeout)) + { + return ScheduleInProgress.Count; + } + } + catch (ApplicationException ex) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + Logger.Debug(ex); + return 0; + } + } + + /// + /// Gets a copy of collection of all schedule items in queue. + /// + /// A copy of the ScheduleQueue + /// Thread Safe + /// The returned collection is a snapshot in time the real ScheduleQueue may change at any time. + /// + public static Collection GetScheduleQueue() + { + var c = new Collection(); + try + { + using (ScheduleQueue.GetReadLock(LockTimeout)) + { + foreach (ScheduleItem item in ScheduleQueue) + { + c.Add(item, item.ScheduleID.ToString(), null, null); + } + } + return c; + } + catch (ApplicationException ex) + { + Interlocked.Increment(ref _readerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + return c; + } + + /// + /// Gets the number of items in the collection of schedule items in progress. + /// + /// Number of items in progress + /// Thread Safe + /// This count is a snapshot and may change at any time + /// + public static int GetScheduleQueueCount() + { + try + { + using (ScheduleQueue.GetReadLock(LockTimeout)) + { + return ScheduleQueue.Count; + } + } + catch (ApplicationException) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + return 0; + } + } + + public static ScheduleStatus GetScheduleStatus() + { + try + { + StatusLock.AcquireReaderLock(LockTimeout); + try + { + //ScheduleStatus is a value type a copy is returned (enumeration) + return _status; + } + finally + { + StatusLock.ReleaseReaderLock(); + } + } + catch (ApplicationException) + { + //The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + return ScheduleStatus.NOT_SET; + } + } + + /// + /// Halt the Scheduler + /// + /// Initiator of Halt + public static void Halt(string sourceOfHalt) + { + //should do nothing if the scheduler havn't start yet. + var currentStatus = GetScheduleStatus(); + if(currentStatus == ScheduleStatus.NOT_SET || currentStatus == ScheduleStatus.STOPPED) + { + return; + } + var eventLogController = new EventLogController(); + SetScheduleStatus(ScheduleStatus.SHUTTING_DOWN); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("Initiator", sourceOfHalt); + eventLogInfo.LogTypeKey = "SCHEDULER_SHUTTING_DOWN"; + eventLogController.AddLog(eventLogInfo); + + KeepRunning = false; + + //wait for up to 120 seconds for thread + //to shut down + for (int i = 0; i <= 120; i++) + { + if (GetScheduleStatus() == ScheduleStatus.STOPPED) + { + return; + } + Thread.Sleep(1000); + } + + _activeThreadCount = 0; + } + + public static bool HasDependenciesConflict(ScheduleItem scheduleItem) + { + try + { + using (ScheduleInProgress.GetReadLock(LockTimeout)) + { + if (scheduleItem.ObjectDependencies.Any()) + { + foreach (ScheduleHistoryItem item in ScheduleInProgress.Where(si => si.ObjectDependencies.Any())) + { + if (item.HasObjectDependencies(scheduleItem.ObjectDependencies)) + { + return true; + } + } + } + } + + return false; + } + catch (ApplicationException ex) + { + // The reader lock request timed out. + Interlocked.Increment(ref _readerTimeouts); + Logger.Debug(ex); + return false; + } + } + + public static void LoadQueueFromEvent(EventName eventName) + { + List schedule = SchedulingController.GetScheduleByEvent(eventName.ToString(), ServerController.GetExecutingServerName()); + + foreach (ScheduleItem scheduleItem in schedule) + { + var historyItem = new ScheduleHistoryItem(scheduleItem); + + if (!IsInQueue(historyItem) && + !IsInProgress(historyItem) && + !HasDependenciesConflict(historyItem) && + historyItem.Enabled) + { + historyItem.ScheduleSource = ScheduleSource.STARTED_FROM_EVENT; + AddToScheduleQueue(historyItem); + } + } + } + + public static void LoadQueueFromTimer() + { + _forceReloadSchedule = false; + + List schedule = SchedulingController.GetSchedule(ServerController.GetExecutingServerName()); + + foreach (ScheduleItem scheduleItem in schedule) + { + var historyItem = new ScheduleHistoryItem(scheduleItem); + + if (!IsInQueue(historyItem) && + historyItem.TimeLapse != Null.NullInteger && + historyItem.TimeLapseMeasurement != Null.NullString && + historyItem.Enabled) + { + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) + { + historyItem.ScheduleSource = ScheduleSource.STARTED_FROM_TIMER; + } + else if (SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD) + { + historyItem.ScheduleSource = ScheduleSource.STARTED_FROM_BEGIN_REQUEST; + } + AddToScheduleQueue(historyItem); + } + } + } + + public static void PurgeScheduleHistory() + { + SchedulingController.PurgeScheduleHistory(); + } + + public static void ReloadSchedule() + { + _forceReloadSchedule = true; + } + + /// + /// Removes an item from the collection of schedule items in queue. + /// + /// Item to remove + public static void RemoveFromScheduleQueue(ScheduleItem scheduleItem) + { + try + { + using (ScheduleQueue.GetWriteLock(LockTimeout)) + { + //the scheduleitem instances may not be equal even though the scheduleids are equal + ScheduleItem item = ScheduleQueue.Where(si => si.ScheduleID == scheduleItem.ScheduleID).SingleOrDefault(); + if (item != null) + { + ScheduleQueue.Remove(item); + } + } + } + catch (ApplicationException ex) + { + // The writer lock request timed out. + Interlocked.Increment(ref _writerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + } + + public static void RunEventSchedule(EventName eventName) + { + try + { + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("EVENT", eventName.ToString()); + eventLogInfo.LogTypeKey = "SCHEDULE_FIRED_FROM_EVENT"; + eventLogController.AddLog(eventLogInfo); + + //We allow for three threads to run simultaneously. + //As long as we have an open thread, continue. + + //Load the queue to determine which schedule + //items need to be run. + LoadQueueFromEvent(eventName); + + while (GetScheduleQueueCount() > 0) + { + SetScheduleStatus(ScheduleStatus.RUNNING_EVENT_SCHEDULE); + + //Fire off the events that need running. + if (GetScheduleQueueCount() > 0) + { + FireEvents(); + } + + + if (_writerTimeouts > 20 || _readerTimeouts > 20) + { + //Wait for 10 minutes so we don't fill up the logs + Thread.Sleep(TimeSpan.FromMinutes(10)); + } + else + { + //Wait for 10 seconds to avoid cpu overutilization + Thread.Sleep(TimeSpan.FromSeconds(10)); + } + + if (GetScheduleQueueCount() == 0) + { + return; + } + } + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + public static void SetScheduleStatus(ScheduleStatus newStatus) + { + try + { + //note:locking inside this method is highly misleading + //as there is no lock in place between when the caller + //decides to call this method and when the lock is acquired + //the value could easily change in that time + StatusLock.AcquireWriterLock(LockTimeout); + try + { + // It is safe for this thread to read or write + // from the shared resource. + _status = newStatus; + } + finally + { + // Ensure that the lock is released. + StatusLock.ReleaseWriterLock(); + } + } + catch (ApplicationException ex) + { + // The writer lock request timed out. + Interlocked.Increment(ref _writerTimeouts); + Exceptions.Exceptions.LogException(ex); + } + } + + public static void Start() + { + try + { + AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); + + _activeThreadCount = 0; + + //This is where the action begins. + //Loop until KeepRunning = false + if (SchedulingProvider.SchedulerMode != SchedulerMode.REQUEST_METHOD || _debug) + { + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.LogTypeKey = "SCHEDULER_STARTED"; + eventLogController.AddLog(eventLogInfo); + } + + while (KeepRunning) + { + try + { + if (Common.Globals.ElapsedSinceAppStart.TotalSeconds < SchedulingProvider.DelayAtAppStart) + { + if (!KeepThreadAlive) + return; + + Thread.Sleep(1000); + continue; + } + + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) + { + SetScheduleStatus(ScheduleStatus.RUNNING_TIMER_SCHEDULE); + } + else + { + SetScheduleStatus(ScheduleStatus.RUNNING_REQUEST_SCHEDULE); + } + //Load the queue to determine which schedule + //items need to be run. + + LoadQueueFromTimer(); + + //Keep track of when the queue was last refreshed + //so we can perform a refresh periodically + DateTime lastQueueRefresh = DateTime.Now; + bool refreshQueueSchedule = false; + + //We allow for [MaxThreadCount] threads to run + //simultaneously. As long as we have an open thread + //and we don't have to refresh the queue, continue + //to loop. + //refreshQueueSchedule can get set to true near bottom of loop + //not sure why R# thinks it is always false + // ReSharper disable ConditionIsAlwaysTrueOrFalse + while (FreeThreads > 0 && !refreshQueueSchedule && KeepRunning && !_forceReloadSchedule) + // ReSharper restore ConditionIsAlwaysTrueOrFalse + { + //Fire off the events that need running. + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) + { + SetScheduleStatus(ScheduleStatus.RUNNING_TIMER_SCHEDULE); + } + else + { + SetScheduleStatus(ScheduleStatus.RUNNING_REQUEST_SCHEDULE); + } + + // It is safe for this thread to read from + // the shared resource. + if (GetScheduleQueueCount() > 0) + { + FireEvents(); + } + if (KeepThreadAlive == false) + { + return; + } + + + if (_writerTimeouts > 20 || _readerTimeouts > 20) + { + //Some kind of deadlock on a resource. + //Wait for 10 minutes so we don't fill up the logs + if (KeepRunning) + { + Thread.Sleep(TimeSpan.FromMinutes(10)); + } + else + { + return; + } + } + else + { + //Wait for 10 seconds to avoid cpu overutilization + if (KeepRunning) + { + Thread.Sleep(TimeSpan.FromSeconds(10)); + } + else + { + return; + } + + //Refresh queue from database every 10 minutes + //if there are no items currently in progress + if ((lastQueueRefresh.AddMinutes(10) <= DateTime.Now || _forceReloadSchedule) && FreeThreads == _maxThreadCount) + { + refreshQueueSchedule = true; + break; + } + } + } + + //There are no available threads, all threads are being + //used. Wait 10 seconds until one is available + if (KeepRunning) + { + if (refreshQueueSchedule == false) + { + SetScheduleStatus(ScheduleStatus.WAITING_FOR_OPEN_THREAD); + Thread.Sleep(10000); //sleep for 10 seconds + } + } + else + { + return; + } + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + //sleep for 10 minutes + Thread.Sleep(600000); + } + } + } + finally + { + if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD || SchedulingProvider.SchedulerMode == SchedulerMode.DISABLED) + { + SetScheduleStatus(ScheduleStatus.STOPPED); + } + else + { + SetScheduleStatus(ScheduleStatus.WAITING_FOR_REQUEST); + } + if (SchedulingProvider.SchedulerMode != SchedulerMode.REQUEST_METHOD || _debug) + { + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo { LogTypeKey = "SCHEDULER_STOPPED" }; + eventLogController.AddLog(eventLogInfo); + } + } + } + + public static void UpdateScheduleHistory(ScheduleHistoryItem scheduleHistoryItem) + { + try + { + SchedulingController.UpdateScheduleHistory(scheduleHistoryItem); + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + public static void WorkCompleted(SchedulerClient schedulerClient) + { + try + { + ScheduleHistoryItem scheduleHistoryItem = schedulerClient.ScheduleHistoryItem; + + //Remove the object in the ScheduleInProgress collection + RemoveFromScheduleInProgress(scheduleHistoryItem); + + //A SchedulerClient is notifying us that their + //process has completed. Decrease our ActiveThreadCount + Interlocked.Decrement(ref _activeThreadCount); + + //Update the schedule item object property + //to note the end time and next start + scheduleHistoryItem.EndDate = DateTime.Now; + + if (scheduleHistoryItem.ScheduleSource == ScheduleSource.STARTED_FROM_EVENT) + { + scheduleHistoryItem.NextStart = Null.NullDate; + } + else + { + if (scheduleHistoryItem.CatchUpEnabled) + { + switch (scheduleHistoryItem.TimeLapseMeasurement) + { + case "s": + scheduleHistoryItem.NextStart = scheduleHistoryItem.NextStart.AddSeconds(scheduleHistoryItem.TimeLapse); + break; + case "m": + scheduleHistoryItem.NextStart = scheduleHistoryItem.NextStart.AddMinutes(scheduleHistoryItem.TimeLapse); + break; + case "h": + scheduleHistoryItem.NextStart = scheduleHistoryItem.NextStart.AddHours(scheduleHistoryItem.TimeLapse); + break; + case "d": + scheduleHistoryItem.NextStart = scheduleHistoryItem.NextStart.AddDays(scheduleHistoryItem.TimeLapse); + break; + } + } + else + { + switch (scheduleHistoryItem.TimeLapseMeasurement) + { + case "s": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddSeconds(scheduleHistoryItem.TimeLapse); + break; + case "m": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddMinutes(scheduleHistoryItem.TimeLapse); + break; + case "h": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddHours(scheduleHistoryItem.TimeLapse); + break; + case "d": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddDays(scheduleHistoryItem.TimeLapse); + break; + } + } + } + + //Update the ScheduleHistory in the database + UpdateScheduleHistory(scheduleHistoryItem); + var eventLogInfo = new LogInfo(); + + if (scheduleHistoryItem.NextStart != Null.NullDate) + { + //Put the object back into the ScheduleQueue + //collection with the new NextStart date. + scheduleHistoryItem.StartDate = Null.NullDate; + scheduleHistoryItem.EndDate = Null.NullDate; + scheduleHistoryItem.LogNotes = ""; + scheduleHistoryItem.ProcessGroup = -1; + AddToScheduleQueue(scheduleHistoryItem); + } + + + if (schedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0) + { + //Write out the log entry for this event + var objEventLog = new EventLogController(); + + eventLogInfo.AddProperty("TYPE", schedulerClient.GetType().FullName); + eventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString()); + eventLogInfo.AddProperty("NEXT START", Convert.ToString(scheduleHistoryItem.NextStart)); + eventLogInfo.AddProperty("SOURCE", schedulerClient.ScheduleHistoryItem.ScheduleSource.ToString()); + eventLogInfo.AddProperty("ACTIVE THREADS", _activeThreadCount.ToString()); + eventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString()); + eventLogInfo.AddProperty("READER TIMEOUTS", _readerTimeouts.ToString()); + eventLogInfo.AddProperty("WRITER TIMEOUTS", _writerTimeouts.ToString()); + eventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString()); + eventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString()); + eventLogInfo.LogTypeKey = "SCHEDULER_EVENT_COMPLETED"; + objEventLog.AddLog(eventLogInfo); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + public static void WorkErrored(SchedulerClient schedulerClient, Exception exception) + { + try + { + ScheduleHistoryItem scheduleHistoryItem = schedulerClient.ScheduleHistoryItem; + //Remove the object in the ScheduleInProgress collection + RemoveFromScheduleInProgress(scheduleHistoryItem); + + //A SchedulerClient is notifying us that their + //process has errored. Decrease our ActiveThreadCount + Interlocked.Decrement(ref _activeThreadCount); + + + Exceptions.Exceptions.ProcessSchedulerException(exception); + + //Update the schedule item object property + //to note the end time and next start + scheduleHistoryItem.EndDate = DateTime.Now; + if (scheduleHistoryItem.ScheduleSource == ScheduleSource.STARTED_FROM_EVENT) + { + scheduleHistoryItem.NextStart = Null.NullDate; + } + else if (scheduleHistoryItem.RetryTimeLapse != Null.NullInteger) + { + switch (scheduleHistoryItem.RetryTimeLapseMeasurement) + { + case "s": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddSeconds(scheduleHistoryItem.RetryTimeLapse); + break; + case "m": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddMinutes(scheduleHistoryItem.RetryTimeLapse); + break; + case "h": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddHours(scheduleHistoryItem.RetryTimeLapse); + break; + case "d": + scheduleHistoryItem.NextStart = scheduleHistoryItem.StartDate.AddDays(scheduleHistoryItem.RetryTimeLapse); + break; + } + } + //Update the ScheduleHistory in the database + UpdateScheduleHistory(scheduleHistoryItem); + + if (scheduleHistoryItem.NextStart != Null.NullDate && scheduleHistoryItem.RetryTimeLapse != Null.NullInteger) + { + //Put the object back into the ScheduleQueue + //collection with the new NextStart date. + scheduleHistoryItem.StartDate = Null.NullDate; + scheduleHistoryItem.EndDate = Null.NullDate; + scheduleHistoryItem.LogNotes = ""; + scheduleHistoryItem.ProcessGroup = -1; + AddToScheduleQueue(scheduleHistoryItem); + } + + if (schedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0) + { + //Write out the log entry for this event + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString()); + eventLogInfo.AddProperty("TYPE", schedulerClient.GetType().FullName); + if (exception != null) + { + eventLogInfo.AddProperty("EXCEPTION", exception.Message); + } + eventLogInfo.AddProperty("RESCHEDULED FOR", Convert.ToString(scheduleHistoryItem.NextStart)); + eventLogInfo.AddProperty("SOURCE", schedulerClient.ScheduleHistoryItem.ScheduleSource.ToString()); + eventLogInfo.AddProperty("ACTIVE THREADS", _activeThreadCount.ToString()); + eventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString()); + eventLogInfo.AddProperty("READER TIMEOUTS", _readerTimeouts.ToString()); + eventLogInfo.AddProperty("WRITER TIMEOUTS", _writerTimeouts.ToString()); + eventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString()); + eventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString()); + eventLogInfo.LogTypeKey = "SCHEDULER_EVENT_FAILURE"; + eventLogController.AddLog(eventLogInfo); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + public static void WorkProgressing(SchedulerClient schedulerClient) + { + try + { + //A SchedulerClient is notifying us that their + //process is in progress. Informational only. + if (schedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0) + { + //Write out the log entry for this event + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString()); + eventLogInfo.AddProperty("TYPE", schedulerClient.GetType().FullName); + eventLogInfo.AddProperty("SOURCE", schedulerClient.ScheduleHistoryItem.ScheduleSource.ToString()); + eventLogInfo.AddProperty("ACTIVE THREADS", _activeThreadCount.ToString()); + eventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString()); + eventLogInfo.AddProperty("READER TIMEOUTS", _readerTimeouts.ToString()); + eventLogInfo.AddProperty("WRITER TIMEOUTS", _writerTimeouts.ToString()); + eventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString()); + eventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString()); + eventLogInfo.LogTypeKey = "SCHEDULER_EVENT_PROGRESSING"; + eventLogController.AddLog(eventLogInfo); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + public static void WorkStarted(SchedulerClient schedulerClient) + { + bool activeThreadCountIncremented = false; + try + { + schedulerClient.ScheduleHistoryItem.ThreadID = Thread.CurrentThread.GetHashCode(); + + //Put the object in the ScheduleInProgress collection + //and remove it from the ScheduleQueue + RemoveFromScheduleQueue(schedulerClient.ScheduleHistoryItem); + AddToScheduleInProgress(schedulerClient.ScheduleHistoryItem); + + //A SchedulerClient is notifying us that their + //process has started. Increase our ActiveThreadCount + Interlocked.Increment(ref _activeThreadCount); + activeThreadCountIncremented = true; + + //Update the schedule item + //object property to note the start time. + schedulerClient.ScheduleHistoryItem.StartDate = DateTime.Now; + AddScheduleHistory(schedulerClient.ScheduleHistoryItem); + + + if (schedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0) + { + //Write out the log entry for this event + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString()); + eventLogInfo.AddProperty("TYPE", schedulerClient.GetType().FullName); + eventLogInfo.AddProperty("SOURCE", schedulerClient.ScheduleHistoryItem.ScheduleSource.ToString()); + eventLogInfo.AddProperty("ACTIVE THREADS", _activeThreadCount.ToString()); + eventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString()); + eventLogInfo.AddProperty("READER TIMEOUTS", _readerTimeouts.ToString()); + eventLogInfo.AddProperty("WRITER TIMEOUTS", _writerTimeouts.ToString()); + eventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString()); + eventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString()); + eventLogInfo.LogTypeKey = "SCHEDULER_EVENT_STARTED"; + eventLogController.AddLog(eventLogInfo); + } + } + catch (Exception exc) + { + //Decrement the ActiveThreadCount because + //otherwise the number of active threads + //will appear to be climbing when in fact + //no tasks are being executed. + if (activeThreadCountIncremented) + { + Interlocked.Decrement(ref _activeThreadCount); + } + Exceptions.Exceptions.ProcessSchedulerException(exc); + } + } + + internal static void InitializeThreadPool(bool boolDebug, int maxThreads) + { + _debug = boolDebug; + lock (typeof (CoreScheduler)) + { + if (!_threadPoolInitialized) + { + _threadPoolInitialized = true; + if (maxThreads == -1) + { + maxThreads = 1; + } + _numberOfProcessGroups = maxThreads; + _maxThreadCount = maxThreads; + for (int i = 0; i < _numberOfProcessGroups; i++) + { + Array.Resize(ref _processGroup, i + 1); + _processGroup[i] = new ProcessGroup(); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/SchedulerClient.cs b/DNN Platform/Library/Services/Scheduling/SchedulerClient.cs new file mode 100644 index 00000000000..a32cb9605a0 --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/SchedulerClient.cs @@ -0,0 +1,109 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Threading; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + /// + /// This class is inherited by any class that wants to run tasks in the scheduler. + /// + public abstract class SchedulerClient + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SchedulerClient)); + public SchedulerClient() + { + SchedulerEventGUID = Null.NullString; + aProcessMethod = Null.NullString; + Status = Null.NullString; + ScheduleHistoryItem = new ScheduleHistoryItem(); + } + + public ScheduleHistoryItem ScheduleHistoryItem { get; set; } + + public string SchedulerEventGUID { get; set; } + + public string aProcessMethod { get; set; } + + public string Status { get; set; } + + public int ThreadID + { + get + { + return Thread.CurrentThread.ManagedThreadId; + } + } + + public event WorkStarted ProcessStarted; + public event WorkProgressing ProcessProgressing; + public event WorkCompleted ProcessCompleted; + public event WorkErrored ProcessErrored; + + public void Started() + { + if (ProcessStarted != null) + { + ProcessStarted(this); + } + } + + public void Progressing() + { + if (ProcessProgressing != null) + { + ProcessProgressing(this); + } + } + + public void Completed() + { + if (ProcessCompleted != null) + { + ProcessCompleted(this); + } + } + + public void Errored(ref Exception objException) + { + Logger.Error(objException); + if (ProcessErrored != null) + { + ProcessErrored(this, objException); + } + } + + /// ''''''''''''''''''''''''''''''''''''''''''''''''''' + /// + /// This is the sub that kicks off the actual + /// work within the SchedulerClient's subclass + /// + /// ''''''''''''''''''''''''''''''''''''''''''''''''''' + public abstract void DoWork(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/SchedulingController.cs b/DNN Platform/Library/Services/Scheduling/SchedulingController.cs new file mode 100644 index 00000000000..ca4c6736acb --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/SchedulingController.cs @@ -0,0 +1,223 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Log.EventLog; + +using Microsoft.VisualBasic; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + public class SchedulingController + { + [Obsolete("Obsoleted in 5.2.1 - use overload that pass's a FriendlyName")] + public static int AddSchedule(string TypeFullName, int TimeLapse, string TimeLapseMeasurement, int RetryTimeLapse, string RetryTimeLapseMeasurement, int RetainHistoryNum, string AttachToEvent, + bool CatchUpEnabled, bool Enabled, string ObjectDependencies, string Servers) + { + return AddSchedule(TypeFullName, + TimeLapse, + TimeLapseMeasurement, + RetryTimeLapse, + RetryTimeLapseMeasurement, + RetainHistoryNum, + AttachToEvent, + CatchUpEnabled, + Enabled, + ObjectDependencies, + Servers, + TypeFullName); + } + + public static int AddSchedule(string TypeFullName, int TimeLapse, string TimeLapseMeasurement, int RetryTimeLapse, string RetryTimeLapseMeasurement, int RetainHistoryNum, string AttachToEvent, + bool CatchUpEnabled, bool Enabled, string ObjectDependencies, string Servers, string FriendlyName) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("TypeFullName", TypeFullName, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.SCHEDULE_CREATED); + return DataProvider.Instance().AddSchedule(TypeFullName, + TimeLapse, + TimeLapseMeasurement, + RetryTimeLapse, + RetryTimeLapseMeasurement, + RetainHistoryNum, + AttachToEvent, + CatchUpEnabled, + Enabled, + ObjectDependencies, + Servers, + UserController.GetCurrentUserInfo().UserID, + FriendlyName); + } + + public static int AddScheduleHistory(ScheduleHistoryItem objScheduleHistoryItem) + { + return DataProvider.Instance().AddScheduleHistory(objScheduleHistoryItem.ScheduleID, objScheduleHistoryItem.StartDate, ServerController.GetExecutingServerName()); + } + + public static void AddScheduleItemSetting(int ScheduleID, string Name, string Value) + { + DataProvider.Instance().AddScheduleItemSetting(ScheduleID, Name, Value); + } + + public static void DeleteSchedule(int ScheduleID) + { + DataProvider.Instance().DeleteSchedule(ScheduleID); + var objEventLog = new EventLogController(); + objEventLog.AddLog("ScheduleID", + ScheduleID.ToString(), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.SCHEDULE_DELETED); + } + + public static int GetActiveThreadCount() + { + return Scheduler.CoreScheduler.GetActiveThreadCount(); + } + + public static int GetFreeThreadCount() + { + return Scheduler.CoreScheduler.GetFreeThreadCount(); + } + + public static int GetMaxThreadCount() + { + return Scheduler.CoreScheduler.GetMaxThreadCount(); + } + + public static ScheduleItem GetNextScheduledTask(string Server) + { + return CBO.FillObject(DataProvider.Instance().GetNextScheduledTask(Server)); + } + + public static List GetSchedule() + { + return CBO.FillCollection(DataProvider.Instance().GetSchedule()); + } + + public static List GetSchedule(string Server) + { + return CBO.FillCollection(DataProvider.Instance().GetSchedule(Server)); + } + + public static ScheduleItem GetSchedule(string TypeFullName, string Server) + { + return CBO.FillObject(DataProvider.Instance().GetSchedule(TypeFullName, Server)); + } + + public static ScheduleItem GetSchedule(int ScheduleID) + { + return CBO.FillObject(DataProvider.Instance().GetSchedule(ScheduleID)); + } + + public static List GetScheduleByEvent(string EventName, string Server) + { + return CBO.FillCollection(DataProvider.Instance().GetScheduleByEvent(EventName, Server)); + } + + public static List GetScheduleHistory(int ScheduleID) + { + return CBO.FillCollection(DataProvider.Instance().GetScheduleHistory(ScheduleID)); + } + + public static Hashtable GetScheduleItemSettings(int ScheduleID) + { + var h = new Hashtable(); + IDataReader r = DataProvider.Instance().GetScheduleItemSettings(ScheduleID); + while (r.Read()) + { + h.Add(r["SettingName"], r["SettingValue"]); + } + //close datareader + if (r != null) + { + r.Close(); + } + return h; + } + + public static Collection GetScheduleProcessing() + { + return Scheduler.CoreScheduler.GetScheduleInProgress(); + } + + public static Collection GetScheduleQueue() + { + return Scheduler.CoreScheduler.GetScheduleQueue(); + } + + public static ScheduleStatus GetScheduleStatus() + { + return Scheduler.CoreScheduler.GetScheduleStatus(); + } + + public static void PurgeScheduleHistory() + { + DataProvider.Instance().PurgeScheduleHistory(); + } + + public static void ReloadSchedule() + { + Scheduler.CoreScheduler.ReloadSchedule(); + } + + public static void UpdateSchedule(int ScheduleID, string TypeFullName, int TimeLapse, string TimeLapseMeasurement, int RetryTimeLapse, string RetryTimeLapseMeasurement, int RetainHistoryNum, + string AttachToEvent, bool CatchUpEnabled, bool Enabled, string ObjectDependencies, string Servers, string FriendlyName) + { + DataProvider.Instance().UpdateSchedule(ScheduleID, + TypeFullName, + TimeLapse, + TimeLapseMeasurement, + RetryTimeLapse, + RetryTimeLapseMeasurement, + RetainHistoryNum, + AttachToEvent, + CatchUpEnabled, + Enabled, + ObjectDependencies, + Servers, + UserController.GetCurrentUserInfo().UserID, + FriendlyName); + var objEventLog = new EventLogController(); + objEventLog.AddLog("TypeFullName", TypeFullName, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.SCHEDULE_UPDATED); + } + + public static void UpdateScheduleHistory(ScheduleHistoryItem objScheduleHistoryItem) + { + DataProvider.Instance().UpdateScheduleHistory(objScheduleHistoryItem.ScheduleHistoryID, + objScheduleHistoryItem.EndDate, + objScheduleHistoryItem.Succeeded, + objScheduleHistoryItem.LogNotes, + objScheduleHistoryItem.NextStart); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Scheduling/SchedulingProvider.cs b/DNN Platform/Library/Services/Scheduling/SchedulingProvider.cs new file mode 100644 index 00000000000..4c8aee62b8c --- /dev/null +++ b/DNN Platform/Library/Services/Scheduling/SchedulingProvider.cs @@ -0,0 +1,244 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Host; + +using Microsoft.VisualBasic; + +#endregion + +namespace DotNetNuke.Services.Scheduling +{ + // ReSharper disable InconsistentNaming + public enum EventName + { + //do not add APPLICATION_END + //it will not reliably complete + APPLICATION_START + } + + public enum ScheduleSource + { + NOT_SET, + STARTED_FROM_SCHEDULE_CHANGE, + STARTED_FROM_EVENT, + STARTED_FROM_TIMER, + STARTED_FROM_BEGIN_REQUEST + } + + public enum ScheduleStatus + { + NOT_SET, + WAITING_FOR_OPEN_THREAD, + RUNNING_EVENT_SCHEDULE, + RUNNING_TIMER_SCHEDULE, + RUNNING_REQUEST_SCHEDULE, + WAITING_FOR_REQUEST, + SHUTTING_DOWN, + STOPPED + } + + public enum SchedulerMode + { + DISABLED = 0, + TIMER_METHOD = 1, + REQUEST_METHOD = 2 + } + // ReSharper restore InconsistentNaming + + //set up our delegates so we can track and react to events of the scheduler clients + public delegate void WorkStarted(SchedulerClient objSchedulerClient); + + public delegate void WorkProgressing(SchedulerClient objSchedulerClient); + + public delegate void WorkCompleted(SchedulerClient objSchedulerClient); + + public delegate void WorkErrored(SchedulerClient objSchedulerClient, Exception objException); + + public abstract class SchedulingProvider + { + public EventName EventName; + + protected SchedulingProvider() + { + var settings = Settings; + if (settings != null) + { + ProviderPath = settings["providerPath"]; + + string str; + bool dbg; + + if (settings.TryGetValue("debug", out str) && bool.TryParse(str, out dbg)) + { + Debug = dbg; + } + + int value; + if (!settings.TryGetValue("maxThreads", out str) || !int.TryParse(str, out value)) + { + value = 1; + } + MaxThreads = value; + + if (!settings.TryGetValue("delayAtAppStart", out str) || !int.TryParse(str, out value)) + { + value = 60; + } + DelayAtAppStart = value; + } + else + { + MaxThreads = 1; + DelayAtAppStart = 60; + } + } + + /// + /// The number of seconds since application start where no timer-initiated + /// schedulers are allowed to run before. This safeguards against ovelapped + /// application re-starts. See "Disable Ovelapped Recycling" under Recycling + /// of IIS Manager Application Pool's Advanced Settings. + /// + public static int DelayAtAppStart { get; private set; } + + public static bool Debug { get; private set; } + + public static bool Enabled + { + get + { + return SchedulerMode != SchedulerMode.DISABLED; + } + } + + public static int MaxThreads { get; private set; } + + public string ProviderPath { get; private set; } + + public static bool ReadyForPoll + { + get + { + return DataCache.GetCache("ScheduleLastPolled") == null; + } + } + + public static DateTime ScheduleLastPolled + { + get + { + return DataCache.GetCache("ScheduleLastPolled") != null + ? (DateTime)DataCache.GetCache("ScheduleLastPolled") : DateTime.MinValue; + } + set + { + var nextScheduledTask = Instance().GetNextScheduledTask(ServerController.GetExecutingServerName()); + var nextStart = nextScheduledTask != null && nextScheduledTask.NextStart > DateTime.Now + ? nextScheduledTask.NextStart : DateTime.Now.AddMinutes(1); + DataCache.SetCache("ScheduleLastPolled", value, nextStart); + } + } + + public static SchedulerMode SchedulerMode + { + get + { + return Host.SchedulerMode; + } + } + + public virtual Dictionary Settings + { + get + { + return new Dictionary(); + } + } + + public static SchedulingProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + + public abstract void Start(); + + public abstract void ExecuteTasks(); + + public abstract void ReStart(string sourceOfRestart); + + public abstract void StartAndWaitForResponse(); + + public abstract void Halt(string sourceOfHalt); + + public abstract void PurgeScheduleHistory(); + + public abstract void RunEventSchedule(EventName eventName); + + public abstract ArrayList GetSchedule(); + + public abstract ArrayList GetSchedule(string server); + + public abstract ScheduleItem GetSchedule(int scheduleID); + + public abstract ScheduleItem GetSchedule(string typeFullName, string server); + + public abstract ScheduleItem GetNextScheduledTask(string server); + + public abstract ArrayList GetScheduleHistory(int scheduleID); + + public abstract Hashtable GetScheduleItemSettings(int scheduleID); + + public abstract void AddScheduleItemSetting(int scheduleID, string name, string value); + + public abstract Collection GetScheduleQueue(); + + public abstract Collection GetScheduleProcessing(); + + public abstract int GetFreeThreadCount(); + + public abstract int GetActiveThreadCount(); + + public abstract int GetMaxThreadCount(); + + public abstract ScheduleStatus GetScheduleStatus(); + + public abstract int AddSchedule(ScheduleItem scheduleItem); + + public abstract void UpdateSchedule(ScheduleItem scheduleItem); + + public abstract void DeleteSchedule(ScheduleItem scheduleItem); + + public virtual void RunScheduleItemNow(ScheduleItem scheduleItem) + { + //Do Nothing + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Controllers/BaseResultController.cs b/DNN Platform/Library/Services/Search/Controllers/BaseResultController.cs new file mode 100644 index 00000000000..6304894db14 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/BaseResultController.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + /// + /// BaseResult to be implemented by the different Crawlers to provide Permission and Url Services + /// + /// The abstract methods in this Class will be called by Search Result engine for every Hit found in Search Index. + public abstract class BaseResultController + { + #region Abstract + + /// + /// Does the user in the Context have View Permission on the Document + /// + /// Search Result + /// True or False + public abstract bool HasViewPermission(SearchResult searchResult); + + /// + /// Return a Url that can be shown in search results. + /// + /// Search Result + /// Url + /// The Query Strings in the Document (if present) should be appended while returning the Url + public abstract string GetDocUrl(SearchResult searchResult); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Controllers/ISearchController.cs b/DNN Platform/Library/Services/Search/Controllers/ISearchController.cs new file mode 100644 index 00000000000..cbff5407038 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/ISearchController.cs @@ -0,0 +1,52 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + public interface ISearchController + { + #region Core Search APIs + + /// + /// Get Search Result for the searchQuery at the Site Level + /// + /// SearchQuery object with various search criteria + /// SearchResults + SearchResults SiteSearch(SearchQuery searchQuery); + + /// + /// Get Search Result for the searchQuery at the Module Level + /// + /// SearchQuery object with various search criteria + /// SearchResults + /// SearchTypeIds provided in the searchQuery will be ignored + SearchResults ModuleSearch(SearchQuery searchQuery); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Controllers/ModuleResultController.cs b/DNN Platform/Library/Services/Search/Controllers/ModuleResultController.cs new file mode 100644 index 00000000000..cc4e0ad69fb --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/ModuleResultController.cs @@ -0,0 +1,132 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Linq; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + /// + /// Search Result Controller for Module Crawler + /// + /// + public class ModuleResultController : BaseResultController + { + #region Abstract Class Implmentation + + public override bool HasViewPermission(SearchResult searchResult) + { + var viewable = false; + if (searchResult.ModuleId > 0) + { + //Get All related tabIds from moduleId (while minimizing DB access; using caching) + var tabController = new TabController(); + var moduleId = searchResult.ModuleId; + // The next call has over 30% performance enhancement over the above one + var tabModules = tabController.GetTabsByPortal(searchResult.PortalId).Values + .SelectMany(tabinfo => tabinfo.ChildModules.Where(kv => kv.Key == moduleId)).Select(m => m.Value); + + foreach (ModuleInfo module in tabModules) + { + var tab = tabController.GetTab(module.TabID, searchResult.PortalId, false); + if (!module.IsDeleted && !tab.IsDeleted && TabPermissionController.CanViewPage(tab)) + { + //Check If authorised to View Module + if (ModulePermissionController.CanViewModule(module)) + { + //Verify against search document permissions + if (string.IsNullOrEmpty(searchResult.Permissions) || PortalSecurity.IsInRoles(searchResult.Permissions)) + { + viewable = true; + if (string.IsNullOrEmpty(searchResult.Url)) + searchResult.Url = Globals.NavigateURL(module.TabID, string.Empty, searchResult.QueryString); + break; + } + } + } + } + } + else + { + viewable = true; + } + + return viewable; + } + + // Returns the URL to the first instance of the module the user has access to view + public override string GetDocUrl(SearchResult searchResult) + { + if (!string.IsNullOrEmpty(searchResult.Url)) + return searchResult.Url; + + var url = Localization.Localization.GetString("SEARCH_NoLink"); + var tabController = new TabController(); + //Get All related tabIds from moduleId + var tabModules = GetModuleTabs(searchResult.ModuleId); + + foreach (ModuleInfo module in tabModules) + { + var tab = tabController.GetTab(module.TabID, searchResult.PortalId, false); + if (TabPermissionController.CanViewPage(tab) && ModulePermissionController.CanViewModule(module)) + { + var portalSettings = new PortalSettings(searchResult.PortalId); + portalSettings.PortalAlias = TestablePortalAliasController.Instance.GetPortalAlias(portalSettings.DefaultPortalAlias); + url = Globals.NavigateURL(module.TabID, portalSettings, string.Empty, searchResult.QueryString); + break; + } + } + + return url; + } + + private const string ModuleByIdCacheKey = "ModuleById{0}"; + private const CacheItemPriority ModuleByIdCachePriority = CacheItemPriority.Normal; + private const int ModuleByIdCacheTimeOut = 20; + + private static ArrayList GetModuleTabs(int moduleID) + { + // no manual clearing of the cache exists; let is just expire + var cacheKey = string.Format(ModuleByIdCacheKey, moduleID); + return CBO.GetCachedObject( + new CacheItemArgs(cacheKey, ModuleByIdCacheTimeOut, ModuleByIdCachePriority, moduleID), + (args) => CBO.FillCollection(DataProvider.Instance().GetModule(moduleID, Null.NullInteger), typeof(ModuleInfo))); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Controllers/SearchController.cs b/DNN Platform/Library/Services/Search/Controllers/SearchController.cs new file mode 100644 index 00000000000..c02b3a1247b --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/SearchController.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + /// + /// Business Layer to manage Search. + /// + public class SearchController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new SearchControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Search/Controllers/SearchControllerImpl.cs b/DNN Platform/Library/Services/Search/Controllers/SearchControllerImpl.cs new file mode 100644 index 00000000000..7f354e84e43 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/SearchControllerImpl.cs @@ -0,0 +1,424 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; + +using Lucene.Net.Documents; +using Lucene.Net.Index; +using Lucene.Net.QueryParsers; +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + /// ----------------------------------------------------------------------------- + /// + /// The Impl Controller class for Search + /// + /// ----------------------------------------------------------------------------- + internal class SearchControllerImpl : ISearchController + { + #region Private Properties + + private const string SeacrchContollersCacheKey = "SearchControllers"; + private const int MaxLucenceRefetches = 10; + private const int MaxLucenceLookBacks = 10; + + private readonly int _moduleSearchTypeId = SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId; + + #endregion + + #region Core Search APIs + + public SearchResults SiteSearch(SearchQuery searchQuery) + { + var results = GetResults(searchQuery); + return new SearchResults{TotalHits = results.Item1, Results = results.Item2}; + } + + public SearchResults ModuleSearch(SearchQuery searchQuery) + { + searchQuery.SearchTypeIds = new List { _moduleSearchTypeId }; + var results = GetResults(searchQuery); + return new SearchResults { TotalHits = results.Item1, Results = results.Item2 }; + } + + #endregion + + #region Private Methods + + private Tuple> GetResults(SearchQuery searchQuery) + { + Requires.NotNull("Query", searchQuery); + Requires.PropertyNotEqualTo("searchQuery", "SearchTypeIds", searchQuery.SearchTypeIds.Count(), 0); + + if((searchQuery.ModuleId > 0) && (searchQuery.SearchTypeIds.Count() > 1 || !searchQuery.SearchTypeIds.Contains(_moduleSearchTypeId))) + throw new ArgumentException("ModuleId based search must have SearchTypeId for a module only"); + + //TODO - Explore Slop factor for Phrase query + + var query = new BooleanQuery(); + if (!string.IsNullOrEmpty(searchQuery.KeyWords)) + { + try + { + var keywords = SearchHelper.Instance.RephraseSearchText(searchQuery.KeyWords, searchQuery.WildCardSearch); + // don't use stemming analyzer for exact matches or non-analyzed fields (e.g. Tags) + var analyzer = new SearchQueryAnalyzer(true); + var nonStemmerAnalyzer = new SearchQueryAnalyzer(false); + var keywordQuery = new BooleanQuery(); + foreach (var fieldToSearch in Constants.KeyWordSearchFields) + { + var parserContent = new QueryParser(Constants.LuceneVersion, fieldToSearch, + fieldToSearch == Constants.Tag ? nonStemmerAnalyzer : analyzer); + var parsedQueryContent = parserContent.Parse(keywords); + keywordQuery.Add(parsedQueryContent, Occur.SHOULD); + } + query.Add(keywordQuery, Occur.MUST); + } + catch (Exception) + { + foreach (var word in searchQuery.KeyWords.Split(' ')) + { + query.Add(new TermQuery(new Term(Constants.ContentTag, word.ToLower())), Occur.SHOULD); + } + } + } + + var portalIdQuery = new BooleanQuery(); + foreach (var portalId in searchQuery.PortalIds) + { + portalIdQuery.Add(NumericRangeQuery.NewIntRange(Constants.PortalIdTag, portalId, portalId, true, true), Occur.SHOULD); + } + if (searchQuery.PortalIds.Any()) query.Add(portalIdQuery, Occur.MUST); + + ApplySearchTypeIdFilter(query, searchQuery); + + if (searchQuery.BeginModifiedTimeUtc > DateTime.MinValue && searchQuery.EndModifiedTimeUtc >= searchQuery.BeginModifiedTimeUtc) + { + query.Add(NumericRangeQuery.NewLongRange(Constants.ModifiedTimeTag, long.Parse(searchQuery.BeginModifiedTimeUtc.ToString(Constants.DateTimeFormat)), long.Parse(searchQuery.EndModifiedTimeUtc.ToString(Constants.DateTimeFormat)), true, true), Occur.MUST); + } + + foreach (var tag in searchQuery.Tags) + { + query.Add(new TermQuery(new Term(Constants.Tag, tag.ToLower())), Occur.MUST); + } + + if (!string.IsNullOrEmpty(searchQuery.CultureCode)) + { + var localeQuery = new BooleanQuery(); + + var languageId = Localization.Localization.GetCultureLanguageID(searchQuery.CultureCode); + localeQuery.Add(NumericRangeQuery.NewIntRange(Constants.LocaleTag, languageId, languageId, true, true), Occur.SHOULD); + localeQuery.Add(NumericRangeQuery.NewIntRange(Constants.LocaleTag, Null.NullInteger, Null.NullInteger, true, true), Occur.SHOULD); + query.Add(localeQuery, Occur.MUST); + } + + var sort = Sort.RELEVANCE; + if (searchQuery.SortField == SortFields.LastModified) + sort = new Sort(new SortField(Constants.ModifiedTimeTag, SortField.LONG, true)); + + var luceneQuery = new LuceneQuery + { + Query = query, + Sort = sort, + PageIndex = searchQuery.PageIndex, + PageSize = searchQuery.PageSize, + TitleSnippetLength = searchQuery.TitleSnippetLength, + BodySnippetLength = searchQuery.BodySnippetLength + }; + + return GetSecurityTrimmedResults(searchQuery, luceneQuery); + } + + private void ApplySearchTypeIdFilter(BooleanQuery query, SearchQuery searchQuery) + { + //Special handling for Module Search + if (searchQuery.SearchTypeIds.Count() == 1 && searchQuery.SearchTypeIds.Contains(_moduleSearchTypeId)) + { + //When moduleid is specified, we ignore other searchtypeid or moduledefinitionid. Major security check + if (searchQuery.ModuleId > 0) + { + //this is the main hook for module based search. Occur.MUST is a requirement for this condition or else results from other modules will be found + query.Add(NumericRangeQuery.NewIntRange(Constants.ModuleIdTag, searchQuery.ModuleId, searchQuery.ModuleId, true, true), Occur.MUST); + } + else + { + var modDefQuery = new BooleanQuery(); + foreach (var moduleDefId in searchQuery.ModuleDefIds) + { + modDefQuery.Add(NumericRangeQuery.NewIntRange(Constants.ModuleDefIdTag, moduleDefId, moduleDefId, true, true), Occur.SHOULD); + } + if (searchQuery.ModuleDefIds.Any()) + query.Add(modDefQuery, Occur.MUST); //Note the MUST + } + + query.Add(NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, _moduleSearchTypeId, _moduleSearchTypeId, true, true), Occur.MUST); + } + else + { + var searchTypeIdQuery = new BooleanQuery(); + foreach (var searchTypeId in searchQuery.SearchTypeIds) + { + if (searchTypeId == _moduleSearchTypeId) + { + foreach (var moduleDefId in searchQuery.ModuleDefIds) + { + searchTypeIdQuery.Add(NumericRangeQuery.NewIntRange(Constants.ModuleDefIdTag, moduleDefId, moduleDefId, true, true), Occur.SHOULD); + } + if (!searchQuery.ModuleDefIds.Any()) + searchTypeIdQuery.Add(NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, searchTypeId, searchTypeId, true, true), Occur.SHOULD); + } + else + { + searchTypeIdQuery.Add(NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, searchTypeId, searchTypeId, true, true), Occur.SHOULD); + } + } + query.Add(searchTypeIdQuery, Occur.MUST); + } + } + + private SearchResult GetSearchResultFromLuceneResult(LuceneResult luceneResult) + { + var result = new SearchResult(); + var doc = luceneResult.Document; + result.DisplayScore = luceneResult.DisplayScore; + result.Score = luceneResult.Score; + + // set culture code of result + result.CultureCode = string.Empty; + var localeField = luceneResult.Document.GetField(Constants.LocaleTag); + if (localeField != null) + { + int id; + if (int.TryParse(localeField.StringValue, out id) && id >= 0) + { + result.CultureCode = LocaleController.Instance.GetLocale(id).Code; + } + else + { + result.CultureCode = Null.NullString; + } + } + + FillTagsValues(doc, result); + result.Snippet = GetSnippet(result, luceneResult); + return result; + } + + private static void FillTagsValues(Document doc, SearchResult result) + { + foreach (var field in doc.GetFields()) + { + if (field.StringValue == null) continue; + int intField; + switch (field.Name) + { + case Constants.UniqueKeyTag: + result.UniqueKey = field.StringValue; + break; + case Constants.TitleTag: + var title = field.StringValue; + //TODO - Need better highlighting logic for Title + //result.Title = string.IsNullOrEmpty(titleSnippet) ? title : string.Format("...{0}...", titleSnippet); + result.Title = title; + break; + case Constants.BodyTag: + result.Body = field.StringValue; + break; + case Constants.DescriptionTag: + result.Description = field.StringValue; + break; + case Constants.Tag: + result.Tags = result.Tags.Concat(new string[] { field.StringValue }); + break; + case Constants.PermissionsTag: + result.Permissions = field.StringValue; + break; + case Constants.QueryStringTag: + result.QueryString = field.StringValue; + break; + case Constants.UrlTag: + result.Url = field.StringValue; + break; + case Constants.SearchTypeTag: + if(int.TryParse(field.StringValue, out intField)) result.SearchTypeId = intField; + break; + case Constants.ModuleIdTag: + if (int.TryParse(field.StringValue, out intField)) result.ModuleId = intField; + break; + case Constants.ModuleDefIdTag: + if (int.TryParse(field.StringValue, out intField)) result.ModuleDefId = intField; + break; + case Constants.PortalIdTag: + if (int.TryParse(field.StringValue, out intField)) result.PortalId = intField; + break; + case Constants.AuthorIdTag: + if (int.TryParse(field.StringValue, out intField)) result.AuthorUserId = intField; + break; + case Constants.AuthorNameTag: + result.AuthorName = field.StringValue; + break; + case Constants.TabIdTag: + if (int.TryParse(field.StringValue, out intField)) result.TabId = intField; + break; + case Constants.ModifiedTimeTag: + DateTime modifiedTimeUtc; + DateTime.TryParseExact(field.StringValue, Constants.DateTimeFormat, null, DateTimeStyles.None, out modifiedTimeUtc); + result.ModifiedTimeUtc = modifiedTimeUtc; + break; + default: + if (field.Name.StartsWith(Constants.NumericKeyPrefixTag)) + { + var key = field.Name.Substring(Constants.NumericKeyPrefixTag.Length); + if (int.TryParse(field.StringValue, out intField)) + { + if (!result.NumericKeys.ContainsKey(key)) + result.NumericKeys.Add(key, intField); + } + } + else if (field.Name.StartsWith(Constants.KeywordsPrefixTag)) + { + var key = field.Name.Substring(Constants.KeywordsPrefixTag.Length); + if (!result.Keywords.ContainsKey(key)) + result.Keywords.Add(key, field.StringValue); + } + break; + } + } + } + + private string GetSnippet(SearchResult searchResult, LuceneResult luceneResult) + { + var sb = new StringBuilder(); + + if (!string.IsNullOrEmpty(luceneResult.TitleSnippet)) sb.Append(luceneResult.TitleSnippet + "..."); + if (!string.IsNullOrEmpty(luceneResult.DescriptionSnippet)) sb.Append(luceneResult.DescriptionSnippet + "..."); + if (!string.IsNullOrEmpty(luceneResult.TagSnippet)) sb.Append(luceneResult.TagSnippet + "..."); + if (!string.IsNullOrEmpty(luceneResult.BodySnippet)) sb.Append(luceneResult.BodySnippet + "..."); + if (!string.IsNullOrEmpty(luceneResult.AuthorSnippet)) sb.Append(luceneResult.AuthorSnippet + "..."); + if (!string.IsNullOrEmpty(luceneResult.ContentSnippet)) sb.Append(luceneResult.ContentSnippet + "..."); + + var snippet = sb.ToString(); + if (string.IsNullOrEmpty(snippet)) snippet = searchResult.Title; + + return snippet; + } + + private Dictionary GetSearchResultControllers() + { + var cachArg = new CacheItemArgs(SeacrchContollersCacheKey, 120, CacheItemPriority.Default); + return CBO.GetCachedObject>(cachArg, GetSearchResultsControllersCallBack); + } + + private Dictionary GetSearchResultsControllersCallBack(CacheItemArgs cacheItem) + { + var searchTypes = SearchHelper.Instance.GetSearchTypes(); + var resultControllers = new Dictionary(); + + foreach (var searchType in searchTypes) + { + try + { + var searchControllerType = Reflection.CreateType(searchType.SearchResultClass); + var searchController = Reflection.CreateObject(searchControllerType); + + resultControllers.Add(searchType.SearchTypeId, (BaseResultController)searchController); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + + return resultControllers; + } + + private Tuple> GetSecurityTrimmedResults(SearchQuery searchQuery, LuceneQuery luceneQuery) + { + var results = new List(); + var totalHits = 0; + + //**************************************************************************** + // First Fetch and determine starting item of current page + //**************************************************************************** + if (searchQuery.PageSize > 0) + { + var luceneResults = LuceneController.Instance.Search(luceneQuery, out totalHits, HasPermissionToViewDoc); + results = luceneResults.Select(GetSearchResultFromLuceneResult).ToList(); + + //**************************************************************************** + //Adding URL Links to final trimmed results + //**************************************************************************** + foreach (var result in results) + { + if (string.IsNullOrEmpty(result.Url)) + { + var resultController = GetSearchResultControllers().Single(sc => sc.Key == result.SearchTypeId).Value; + result.Url = resultController.GetDocUrl(result); + } + } + } + + return new Tuple>(totalHits, results); + } + + private bool HasPermissionToViewDoc(Document document) + { + // others LuceneResult fields are not impotrant at this moment + var result = GetPartialSearchResult(document); + var resultController = GetSearchResultControllers().SingleOrDefault(sc => sc.Key == result.SearchTypeId).Value; + return resultController != null && resultController.HasViewPermission(result); + } + + private static SearchResult GetPartialSearchResult(Document doc) + { + var result = new SearchResult(); + var localeField = doc.GetField(Constants.LocaleTag); + + if (localeField != null) + { + int id; + result.CultureCode = int.TryParse(localeField.StringValue, out id) && id >= 0 + ? LocaleController.Instance.GetLocale(id).Code : Null.NullString; + } + + FillTagsValues(doc, result); + return result; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Controllers/TabResultController.cs b/DNN Platform/Library/Services/Search/Controllers/TabResultController.cs new file mode 100644 index 00000000000..06c168c602c --- /dev/null +++ b/DNN Platform/Library/Services/Search/Controllers/TabResultController.cs @@ -0,0 +1,79 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Controllers +{ + /// + /// Search Result Controller for Tab Indexer + /// + /// + public class TabResultController : BaseResultController + { + #region Abstract Class Implmentation + + public override bool HasViewPermission(SearchResult searchResult) + { + var tabController = new TabController(); + var viewable = false; + + if (searchResult.TabId > 0) + { + var tab = tabController.GetTab(searchResult.TabId, searchResult.PortalId, false); + if (!tab.IsDeleted && TabPermissionController.CanViewPage(tab)) + { + viewable = true; + } + } + else + { + viewable = true; + } + + return viewable; + } + + public override string GetDocUrl(SearchResult searchResult) + { + var url = Localization.Localization.GetString("SEARCH_NoLink"); + var tabController = new TabController(); + + var tab = tabController.GetTab(searchResult.TabId, searchResult.PortalId, false); + if (TabPermissionController.CanViewPage(tab)) + { + url = Globals.NavigateURL(searchResult.TabId, string.Empty, searchResult.QueryString); + } + + return url; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Entities/SearchDocument.cs b/DNN Platform/Library/Services/Search/Entities/SearchDocument.cs new file mode 100644 index 00000000000..cd9a6544c5c --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchDocument.cs @@ -0,0 +1,179 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Search.Entities +{ + /// + /// The document that will be stored in Search Index + /// + /// Each document is one discrete unit of content to be indexed and is independent from other Documents + [Serializable] + public class SearchDocument + { + /// + /// A key to uniquely identify a document in the Index + /// + public string UniqueKey { get; set; } + + /// + /// Content's Title + /// + /// + /// HTML tags are stripped from this property, but certain HTML attribute values will be retain, ie. alt and title attribute values. + /// + public string Title { get; set; } + + /// + /// Content's Description + /// + /// + /// Description should generally be no more than two sentences. This property is used by RSS Syndication. It is also used in search result when highlighted text is not found during searching. + /// HTML tags are stripped from this property, but certain HTML attribute values will be retain, ie. alt and title attribute values. + /// + public string Description { get; set; } + + /// + ///Content's Body + /// + /// + /// HTML tags are stripped from this property, but certain HTML attribute values will be retain, ie. alt and title attribute values. + /// + public string Body { get; set; } + + /// + /// Url for the indexed item. + /// + /// Usually TabId or ModuleId is enough to generate Document Url in Search Result. However, Url field is used if present in SearchResult + public string Url { get; set; } + + /// + /// Portal Id + /// + public int PortalId { get; set; } + + /// + /// Tab Id of the Content [Optional] + /// + public int TabId { get; set; } + + /// + /// Module Definition Id of the Content. + /// + /// This is needed when SearchTypeId is for a Module + public int ModuleDefId { get; set; } + + /// + /// Module Id of the Content + /// + /// This is needed when SearchTypeId is for a Module + public int ModuleId { get; set; } + + /// + /// User Id of the Author + /// + /// Author's display name is automatically found and stored. AuthorName can be found in SearchResult. + /// However, this may get out of date if Display Name is changed after Index. + public int AuthorUserId { get; set; } + + /// + /// Search Type Id, e.g. module, file or url + /// + public int SearchTypeId { get; set; } + + /// + /// Time when Content was last modified (in Utc) + /// + public DateTime ModifiedTimeUtc { get; set; } + + /// + /// Flag to indicate if Content is Active or Not. Content will be deleted from Index when IsActive = false. Default is True. + /// + public bool IsActive { get; set; } + + /// + /// QueryString that may be associated with a Search Document. + /// + /// This information will be used to creare Url for the document + public string QueryString { get; set; } + + /// + /// A string representation of roles and users who have view (or denied view) permissions + /// + public string Permissions { get; set; } + + /// + /// Additional keywords can be specified for Indexing + /// + /// This is key-value pair, e.g. "AliasName","something" + public IDictionary Keywords { get; set; } + + /// + /// Additional numeric fields can be specified for Indexing + /// + /// This is key-value pair, e.g. "ItemId","888" + public IDictionary NumericKeys { get; set; } + + /// + /// Tags can be specified as additional information + /// + public IEnumerable Tags { get; set; } + + /// + /// Culture Code associated with the content. + /// + public string CultureCode { get; set; } + + #region constructor + public SearchDocument() + { + Keywords = new Dictionary(); + NumericKeys = new Dictionary(); + Tags = new string[0]; + IsActive = true; + CultureCode = string.Empty; + } + #endregion + + public override string ToString() + { + var data = new string[] + { + "Portal ID: " + PortalId.ToString(), + "Tab ID: " + TabId.ToString(), + "Module ID: " + ModuleId.ToString(), + "Mod. Def.ID: " + ModuleDefId.ToString(), + "Url: " + Url, + "Unique Key: " + UniqueKey, + "Last Modified: " + ModifiedTimeUtc.ToString("o"), + "Culture: " + CultureCode, + }; + return string.Join(", ", data); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Entities/SearchQuery.cs b/DNN Platform/Library/Services/Search/Entities/SearchQuery.cs new file mode 100644 index 00000000000..dd890de46d6 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchQuery.cs @@ -0,0 +1,149 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Search.Entities +{ + /// + /// Criteria to search for. + /// + /// This object should be passed to SearchController to search for Content. KeyWords and PortalId must be specified + [Serializable] + public class SearchQuery + { + /// + /// A key to uniquely identify a document in the Index + /// + public string UniqueKey { get; set; } + + /// + /// Keywords to search for. + /// + public string KeyWords { get; set; } + + /// + /// A collection of Portal Ids of the Site to perform Search upon. This field must be specified or else Portal 0 will be searched by default. + /// + /// Search cannot be executed across Sites + public IEnumerable PortalIds { get; set; } + + /// + /// A collection of Search Type Ids that should be searched upon [Optional] + /// + public IEnumerable SearchTypeIds { get; set; } + + /// + /// A collection of Module Def Ids that should be searched upon [Optional]. Match is performed only when a SearchTypeId for Module Search Crawler Id + /// + public IEnumerable ModuleDefIds { get; set; } + + /// + /// Module Id to restrict Search. Value > 0 is used only. + /// + public int ModuleId { get; set; } + + /// + /// Tab Id to restrict Search. Value > 0 is used only. + /// + public int TabId { get; set; } + + /// + /// Locale to restrict Search to. This field can be left empty for single language site + /// + /// E.g. A value en-US or nl-NL can specified to restrict search to a single locale . + public string Locale { get; set; } + + /// + /// Begin Date of the time when Content was last modified (in Utc). This field is optional. + /// + public DateTime BeginModifiedTimeUtc { get; set; } + + /// + /// End Date of the time when Content was last modified (in Utc). This field is optional. + /// + public DateTime EndModifiedTimeUtc { get; set; } + + /// + /// Restrict search to specific tags. This field is optional. + /// + public IEnumerable Tags { get; set; } + + /// + /// Page Index for the result, e.g. pageIndex=1 and pageSize=10 indicates first 10 hits. Default value is 1 + /// + public int PageIndex { get; set; } + + /// + /// Page size of the search result. Default value is 10. + /// + public int PageSize { get; set; } + + /// + /// Maximum length of highlighted title field in the results + /// + public int TitleSnippetLength { get; set; } + + /// + /// Maximum length of highlighted title field in the results + /// + public int BodySnippetLength { get; set; } + + /// + /// Culture Code associated with the content. + /// + /// Culture-Neutral content is always returned even though this value is specfied + public string CultureCode { get; set; } + + /// + /// Sort option of the search result. This field is optional. + /// + public SortFields SortField { get; set; } + + /// + /// Set this to true to perform perform WildCard Search. + /// + /// This property is not respected when Keywords contain special boolean phrases "~", "*", "\"", "\'", "and", "or", "+", "-". + /// When this is enabled, an additional OR is performed, e.g. (keyword OR keyword*). It adds asterisk at then end to find any words starting with the keyword. + /// There can be performance implications with this setting turned on. + public bool WildCardSearch { get; set; } + + #region constructor + + public SearchQuery() + { + Tags = new string[0]; + PortalIds = new int[0]; + SearchTypeIds = new int[0]; + ModuleDefIds = new int[0]; + TitleSnippetLength = 60; + BodySnippetLength = 100; + PageSize = 10; + PageIndex = 1; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Entities/SearchResult.cs b/DNN Platform/Library/Services/Search/Entities/SearchResult.cs new file mode 100644 index 00000000000..7b279e63874 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchResult.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search.Entities +{ + /// + /// Search Result to be displayed to end user + /// + /// TODO: + /// Inherited "Body" property from SearchDocument may be purposefully left empty for performance purposes. + /// + [Serializable] + public class SearchResult : SearchDocument + { + /// + /// Time when Content was last modified (in friendly format) + /// + public string DisplayModifiedTime { get { return DateUtils.CalculateDateForDisplay(ModifiedTimeUtc); } } + + /// + /// Highlighted snippet from document + /// + public string Snippet { get; set; } + + /// + /// Optional: Display Name of the Author + /// + /// This may be different form current Display Name when Index was run prior to change in Display Name. + public string AuthorName { get; set; } + + /// + /// Lucene's original Score. The score of this document for the query. + /// + /// This field may not be reliable as most of the time it contains Nan. Use DisplayScore instead + public float Score { get; set; } + + /// + /// Lucene's original Score in String format, e.g. 1.45678 or 0.87642. The score of this document for the query. + /// + /// This field is more reliable than the float version of Score. + public string DisplayScore { get; set; } + + /// + /// Empty Constructor + /// + public SearchResult() + { + Tags = new string[0]; + NumericKeys = new Dictionary(); + Keywords = new Dictionary(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Entities/SearchResults.cs b/DNN Platform/Library/Services/Search/Entities/SearchResults.cs new file mode 100644 index 00000000000..5692c5e84a2 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchResults.cs @@ -0,0 +1,54 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Search.Entities +{ + /// + /// Collection storing Search Results + /// + [Serializable] + public class SearchResults + { + /// + /// Total Hits found in Lucene + /// + /// This number will generally be larger than count of Results object as Results usually holds 10 items, whereas TotalHits indicates TOTAL hits in entire Lucene for the query supplied. + public int TotalHits { get; set; } + + /// + /// Collection of Results + /// + public IList Results { get; set; } + + public SearchResults() + { + Results = new List(); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Entities/SearchStopWords.cs b/DNN Platform/Library/Services/Search/Entities/SearchStopWords.cs new file mode 100644 index 00000000000..8bf8a7e556f --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchStopWords.cs @@ -0,0 +1,17 @@ +using System; + +namespace DotNetNuke.Services.Search.Entities +{ + [Serializable] + public class SearchStopWords + { + public int StopWordsId { get; set; } + public string StopWords { get; set; } + public int CreatedByUserId { get; set; } + public int LastModifiedByUserId { get; set; } + public DateTime CreatedOnDate { get; set; } + public DateTime LastModifiedOnDate { get; set; } + public int PortalId { get; set; } + public string CultureCode { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Search/Entities/SearchType.cs b/DNN Platform/Library/Services/Search/Entities/SearchType.cs new file mode 100644 index 00000000000..361735f89e5 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SearchType.cs @@ -0,0 +1,28 @@ +using System; + +namespace DotNetNuke.Services.Search.Entities +{ + [Serializable] + public class SearchType + { + /// + /// Search Type Id + /// + public int SearchTypeId { get; set; } + + /// + /// Search Type Name + /// + public string SearchTypeName { get; set; } + + /// + /// A class implementing BaseResultController. This class will be invoked by reflection. + /// + public string SearchResultClass { get; set; } + + /// + /// Content from this SearchType will normally be not searched while performing site or module search + /// + public bool IsPrivate { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Search/Entities/SortFields.cs b/DNN Platform/Library/Services/Search/Entities/SortFields.cs new file mode 100644 index 00000000000..5d2b11f1eb0 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SortFields.cs @@ -0,0 +1,18 @@ +namespace DotNetNuke.Services.Search.Entities +{ + /// + /// Sorting criteria to be used for Querying + /// + public enum SortFields + { + /// + /// Sort by Relevance [default]. Most relevant come first. + /// + Relevance = 0, + + /// + /// Sort by DateTime Modified. Latest come first + /// + LastModified = 1 + } +} diff --git a/DNN Platform/Library/Services/Search/Entities/SynonymsGroup.cs b/DNN Platform/Library/Services/Search/Entities/SynonymsGroup.cs new file mode 100644 index 00000000000..39ea7c72fcc --- /dev/null +++ b/DNN Platform/Library/Services/Search/Entities/SynonymsGroup.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetNuke.Services.Search.Entities +{ + [Serializable] + public class SynonymsGroup + { + public int SynonymsGroupId { get; set; } + public string SynonymsTags { get; set; } + public int CreatedByUserId { get; set; } + public int LastModifiedByUserId { get; set; } + public DateTime CreatedOnDate { get; set; } + public DateTime LastModifiedOnDate { get; set; } + public int PortalId { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Search/IndexingProvider.cs b/DNN Platform/Library/Services/Search/IndexingProvider.cs new file mode 100644 index 00000000000..7be07b16115 --- /dev/null +++ b/DNN Platform/Library/Services/Search/IndexingProvider.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search +{ + public abstract class IndexingProvider + { + public static IndexingProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + public virtual IEnumerable GetSearchDocuments(int portalId, DateTime startDate) + { + return new List(); + } + + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchDocuments' instead.")] + public abstract SearchItemInfoCollection GetSearchIndexItems(int portalId); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/Constants.cs b/DNN Platform/Library/Services/Search/Internals/Constants.cs new file mode 100644 index 00000000000..d8b4beb2588 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/Constants.cs @@ -0,0 +1,110 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using Version = Lucene.Net.Util.Version; +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Constants + /// + internal static class Constants + { + internal const string UniqueKeyTag = "key"; + internal const string PortalIdTag = "portal"; + internal const string SearchTypeTag = "searchtype"; + internal const string TitleTag = "title"; + internal const string DescriptionTag = "description"; + internal const string ContentTag = "content"; + internal const string UrlTag = "url"; + internal const string BodyTag = "body"; + internal const string TabIdTag = "tab"; + internal const string TabMetaDataPrefixTag = "tabMetaData_"; + internal const string ModuleIdTag = "module"; + internal const string ModuleDefIdTag = "moduledef"; + internal const string ModuleMetaDataPrefixTag = "moduleMetaData_"; + internal const string CommentsTag = "comments"; + internal const string ViewsTag = "views"; + internal const string LikesTag = "likes"; + internal const string AuthorIdTag = "authorid"; + internal const string AuthorNameTag = "authorname"; + internal const string PermissionsTag = "perm"; + internal const string Tag = "tag"; + internal const string LocaleTag = "locale"; + internal const string ModifiedTimeTag = "time"; + internal const string QueryStringTag = "querystring"; + internal const string NumericKeyPrefixTag = "nk-"; + internal const string KeywordsPrefixTag = "kw-"; + + internal const string FolderIdTag = "folderid"; + internal const string FileIdTag = "fileid"; + internal const string FolderNameTag = "foldername"; + internal const string FileNameTag = "filename"; + + internal const string DateTimeFormat = "yyyyMMddHHmmssfff"; + internal const string ReinsdexDateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff"; + + internal static Version LuceneVersion = Version.LUCENE_30; + + //Field Boost Settings - they are scaled down by 10. + internal const int DefaultSearchTitleBoost = 50; + internal const int DefaultSearchTagBoost = 40; + internal const int DefaultSearchKeywordBoost = 35; + internal const int DefaultSearchDescriptionBoost = 20; + internal const int DefaultSearchAuthorBoost = 15; + internal const int StandardLuceneBoost = 10; //Lucene's default boost is 1.0f + + //Field Bosst Setting Names + internal const string SearchTitleBoostSetting = "Search_Title_Boost"; + internal const string SearchTagBoostSetting = "Search_Tag_Boost"; + internal const string SearchContentBoostSetting = "Search_Content_Boost"; + internal const string SearchDescriptionBoostSetting = "Search_Description_Boost"; + internal const string SearchAuthorBoostSetting = "Search_Author_Boost"; + + //If weighted sum of Likes, Comment and Weight is the number below, Document gets a boost of 1.0 + internal const int DefaultDocumentBoostScale = 1000; + + internal static string[] KeyWordSearchFields = new[] {TitleTag, Tag, DescriptionTag, BodyTag, ContentTag }; + + // search index tokenizers word lengths + internal const int MinimumMinLen = 1; + internal const int DefaultMinLen = 3; + internal const int MaximumMinLen = 10; + + internal const int MinimumMaxLen = 10; + internal const int DefaultMaxLen = 255; + internal const int MaximumMaxLen = 500; + + internal const string SearchMinLengthKey = "Search_MinKeyWordLength"; + internal const string SearchMaxLengthKey = "Search_MaxKeyWordLength"; + internal const string SearchIndexFolderKey = "Search_IndexFolder"; + internal const string SearchReaderRefreshTimeKey = "Search_ReaderRefreshTime"; + internal const string SearchReindexSettingName = "Search_ReindexRequestedOn"; + internal const string SearchLastSuccessIndexName = "Search_LastSuccessfulIndexedOn"; + internal const string SearchoptimizeFlagName = "Search_OptimizeIndex"; + + // misc. + internal const string TlsSearchInfo = "TLS_SEARCH_INFO"; + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/IInternalSearchController.cs b/DNN Platform/Library/Services/Search/Internals/IInternalSearchController.cs new file mode 100644 index 00000000000..53fa039d861 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/IInternalSearchController.cs @@ -0,0 +1,116 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Internal Search Controller Interface. + /// This is an Internal interface and should not be used outside of Core. + /// + public interface IInternalSearchController + { + /// + /// Get a List of Search Content Source that participate in Search + /// + IEnumerable GetSearchContentSourceList(int portalId); + + /// + /// Returns current search indexs general information + /// + /// + SearchStatistics GetSearchStatistics(); + + /// + /// Get Friendly Display Name for the Search Result + /// + /// SearchTypeId is used primarily to obtain this value. Multiple SearchTypeId can map to same Display Name, + /// e.g. Tab, Module, Html/Module all map to Pages. + /// For SearchTypeId=module, ModuleDefitionId is also used. Module's display name is used unless an entry is found in + /// ~/DesktopModules/Admin/SearchResults/App_LocalResources/SearchableModules.resx for the Module_[MODULENAME].txt is found. + string GetSearchDocumentTypeDisplayName(SearchResult searchResult); + + #region Core Search Indexing APIs + + /// + /// Add a Search Document to Search Index + /// + void AddSearchDocument(SearchDocument searchDocument); + + /// + /// Adds the collection of search documents to the search index + /// + /// + /// The controller auto-commits at the end of this method + /// + /// + void AddSearchDocuments(IEnumerable searchDocumentList); + + /// + /// Delete a Search Document from the Search Index. + /// REQUIRES: searchDocument to have PortalId, UniqueKey, SearchTypeId properties set. + /// + /// + void DeleteSearchDocument(SearchDocument searchDocument); + + /// + /// Delete all search documents related to a particula module + /// + /// + /// + /// + void DeleteSearchDocumentsByModule(int portalId, int moduleId, int moduleDefId); + + /// + /// Deletes all documents of a specified portal and search type (used for re-index operation) + /// + /// + /// + void DeleteAllDocuments(int portalId, int searchTypeId); + + /// + /// Commits individually added/deleted documents to the search index + /// + void Commit(); + + /// + /// Optimize the search index files by compacting and removing previously deleted search documents. + /// The call will return immediately and the operation runs on a background thread. + /// + /// + /// This is a costly operation which consumes substantial CPU and I/O resources, therefore use it + /// judiciously. If your site has a a single server that performs both indexing and searching, then + /// you should consider running the optimize operation after hours or over the weekend so that it + /// does not interfere with ongoing search activities. + /// + /// True is optimization was scheduled to run in the background, false otherwise. + bool OptimizeSearchIndex(); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/ILuceneController.cs b/DNN Platform/Library/Services/Search/Internals/ILuceneController.cs new file mode 100644 index 00000000000..9f0f3cfec92 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/ILuceneController.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using Lucene.Net.Documents; +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + internal interface ILuceneController + { + /// + /// Execute Search + /// + /// Search Parameters + /// Total Hits found in Lucene + /// List of matching Documents + IEnumerable Search(LuceneQuery luceneQuery, out int totalHits, SecurityCheckerDelegate securityChecker = null); + + /// + /// Adds Lucene Document in Lucene Index + /// + void Add(Document doc); + + /// + /// Delete a Search Document from the Search Index + /// + void Delete(Query query); + + /// + /// Commits the added search documents into the search database + /// + void Commit(); + + /// + /// Optimize the search index files by compacting and removing previously deleted search documents. + /// + /// + /// This is a costly operation which consumes substantial CPU and I/O resources, therefore use it + /// judiciously. If your site has a a single server that performs both indexing and searching, then + /// you should consider running the optimize operation after hours or over the weekend so that it + /// does not interfere with ongoing search activities. + /// This means you should expect the size of your index to roughly triple (temporarily) + /// during optimization. Once optimization completes, and once you call commit(), disk usage + /// will fall back to a lower level than the starting size. + /// + /// Whether to run optimization on background thread or wait for optimization to finish. + /// True is optimization was scheduled to run in the background or ran to completion in foreground, false otherwise (due to + /// that there were no deletions or the writer was not created yet). + bool OptimizeSearchIndex(bool doWait); + + /// + /// Returns number of total documents in the search index (including deleted ones). + /// + /// Number of total documents in the search index (including Deletions). + int MaxDocsCount(); + + /// + /// Returns number of total searchable documents in the search index. + /// + /// Number of total searchable documents in the search index. + int SearchbleDocsCount(); + + /// + /// Returns if the current search index has deletions + /// + /// Whther the search index has deletions or not + bool HasDeletions(); + + /// + /// Returns current search indexs general information + /// + /// object or null if the information can not be retrieved. + SearchStatistics GetSearchStatistics(); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/ISearchHelper.cs b/DNN Platform/Library/Services/Search/Internals/ISearchHelper.cs new file mode 100644 index 00000000000..4746259d3fd --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/ISearchHelper.cs @@ -0,0 +1,161 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Search.Entities; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Internal Search Controller Helper Interface. + /// This is an Internal interface and should not be used outside of Core. + /// + public interface ISearchHelper + { + + #region SearchType APIs + + // /// + // /// Commits the added search documents into the search database + // /// + // void Commit(); + + /// + /// Returns a list of SearchTypes defined in the system + /// + /// + IEnumerable GetSearchTypes(); + + /// + /// Gets a SearchType Item for the given name. + /// + /// + SearchType GetSearchTypeByName(string searchTypeName); + + #endregion + + #region Synonym Management APIs + /// + /// Returns a list of Synonyms for a given word. E.g. leap, hop for jump + /// + /// word for which to obtain synonyms + /// portal id + /// culture code + /// List of synonyms + /// Synonyms must be defined in system first + IEnumerable GetSynonyms(int portalId, string cultureCode, string term); + + /// + /// Returns a list of SynonymsGroup defined in the system + /// + /// + IEnumerable GetSynonymsGroups(int portalId, string cultureCode); + + /// + /// Adds a synonymsgroup to system + /// + /// synonyms tags seperated by comma, like this: dnn,dotnetnuke + /// + /// culture code + /// + int AddSynonymsGroup(string synonymsTags, int portalId, string cultureCode, out string duplicateWord); + + /// + /// Updates a sysnonymsGroup + /// + /// + /// synonyms tags seperated by comma, like this: dnn,dotnetnuke + /// + /// culture code + /// + int UpdateSynonymsGroup(int synonymsGroupId, string synonymsTags, int portalId, string cultureCode, out string duplicateWord); + + /// + /// Deletes a synonyms group + /// + /// + /// + /// culture code + void DeleteSynonymsGroup(int synonymsGroupId, int portalId, string cultureCode); + + #endregion + + #region Stop Word Management APIs + + /// + /// Gets a search stop words + /// + /// + /// + /// + SearchStopWords GetSearchStopWords(int portalId, string cultureCode); + + /// + /// Adds a search stop words + /// + /// + /// + /// + /// + int AddSearchStopWords(string stopWords, int portalId, string cultureCode); + + /// + /// Updates a search stop words + /// + /// + /// + /// + /// + /// + int UpdateSearchStopWords(int stopWordsId, string stopWords, int portalId, string cultureCode); + + /// + /// Deletes a search stop words + /// + /// + /// + /// + void DeleteSearchStopWords(int stopWordsId, int portalId, string cultureCode); + + #endregion + + #region Reindex and Compact settings + DateTime GetSearchReindexRequestTime(int portalId); + DateTime SetSearchReindexRequestTime(int portalId); + bool GetSearchCompactFlag(); + void SetSearchReindexRequestTime(bool turnOn); + bool IsReindexRequested(int portalId, DateTime startDate); + IEnumerable GetPortalsToReindex(DateTime startDate); + DateTime GetLastSuccessfulIndexingDateTime(int scheduleId); + void SetLastSuccessfulIndexingDateTime(int scheduleId, DateTime startDate); + #endregion + + #region Other Search Helper methods + Tuple GetSearchMinMaxLength(); + string RephraseSearchText(string searchPhrase, bool useWildCard); + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/InternalSearchController.cs b/DNN Platform/Library/Services/Search/Internals/InternalSearchController.cs new file mode 100644 index 00000000000..6e945fdf153 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/InternalSearchController.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Internal Search Controller. This is an Internal class and should not be used outside of Core + /// + public class InternalSearchController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new InternalSearchControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/InternalSearchControllerImpl.cs b/DNN Platform/Library/Services/Search/Internals/InternalSearchControllerImpl.cs new file mode 100644 index 00000000000..276eacdc201 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/InternalSearchControllerImpl.cs @@ -0,0 +1,548 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users.Internal; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Search.Entities; + +using Lucene.Net.Documents; +using Lucene.Net.Index; +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// ----------------------------------------------------------------------------- + /// + /// The Impl Controller class for Lucene + /// + /// ----------------------------------------------------------------------------- + internal class InternalSearchControllerImpl : IInternalSearchController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(LuceneControllerImpl)); + private const string SearchableModuleDefsKey = "{0}-{1}"; + private const string SearchableModuleDefsCacheKey = "SearchableModuleDefs"; + private const string LocalizedResxFile = "~/DesktopModules/Admin/SearchResults/App_LocalResources/SearchableModules.resx"; + + private static readonly string[] HtmlAttributesToRetain = new[] { "alt", "title" }; + private readonly int _titleBoost; + private readonly int _tagBoost; + private readonly int _contentBoost; + private readonly int _descriptionBoost; + private readonly int _authorBoost; + private readonly int _moduleSearchTypeId = SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId; + + private static readonly DataProvider DataProvider = DataProvider.Instance(); + + #region constructor + public InternalSearchControllerImpl() + { + var hostController = HostController.Instance; + _titleBoost = hostController.GetInteger(Constants.SearchTitleBoostSetting, Constants.DefaultSearchTitleBoost); + _tagBoost = hostController.GetInteger(Constants.SearchTagBoostSetting, Constants.DefaultSearchTagBoost); + _contentBoost = hostController.GetInteger(Constants.SearchContentBoostSetting, Constants.DefaultSearchKeywordBoost); + _descriptionBoost = hostController.GetInteger(Constants.SearchDescriptionBoostSetting, Constants.DefaultSearchDescriptionBoost); + _authorBoost = hostController.GetInteger(Constants.SearchAuthorBoostSetting, Constants.DefaultSearchAuthorBoost); + } + #endregion + + internal virtual object SearchContentSourceCallback(CacheItemArgs cacheItem) + { + var searchTypes = CBO.FillCollection(DataProvider.GetAllSearchTypes()); + + var results = new List(); + + foreach (var crawler in searchTypes) + { + switch (crawler.SearchTypeName) + { + case "module": // module crawler + + // get searchable module definition list + var portalId = int.Parse(cacheItem.CacheKey.Split('-')[1]); + var moduleController = new ModuleController(); + var modules = moduleController.GetSearchModules(portalId); + var modDefIds = new HashSet(); + + foreach (ModuleInfo module in modules) + { + if (!modDefIds.Contains(module.ModuleDefID)) modDefIds.Add(module.ModuleDefID); + } + + var list = modDefIds.Select(ModuleDefinitionController.GetModuleDefinitionByID).ToList(); + + foreach (var def in list) + { + var text = Localization.Localization.GetSafeJSString("Module_" + def.DefinitionName, LocalizedResxFile); + if (string.IsNullOrEmpty(text)) + { + text = def.FriendlyName; + } + var result = new SearchContentSource + { + SearchTypeId = crawler.SearchTypeId, + SearchTypeName = crawler.SearchTypeName, + IsPrivate = crawler.IsPrivate, + ModuleDefinitionId = def.ModuleDefID, + LocalizedName = text + }; + + results.Add(result); + } + + break; + + default: + + var localizedName = Localization.Localization.GetSafeJSString("Crawler_" + crawler.SearchTypeName, LocalizedResxFile); + if (string.IsNullOrEmpty(localizedName)) + { + localizedName = crawler.SearchTypeName; + } + + results.Add(new SearchContentSource + { + SearchTypeId = crawler.SearchTypeId, + SearchTypeName = crawler.SearchTypeName, + IsPrivate = crawler.IsPrivate, + ModuleDefinitionId = 0, + LocalizedName = localizedName + }); + break; + } + } + + return results; + + } + + public IEnumerable GetSearchContentSourceList(int portalId) + { + var searchableModuleDefsCacheArgs = new CacheItemArgs( + string.Format(SearchableModuleDefsKey, SearchableModuleDefsCacheKey, portalId), + 120, CacheItemPriority.Default); + + var list = CBO.GetCachedObject>( + searchableModuleDefsCacheArgs, SearchContentSourceCallback); + + return list; + } + + private object SearchDocumentTypeDisplayNameCallBack(CacheItemArgs cacheItem) + { + var data = new Dictionary(); + foreach (PortalInfo portal in new PortalController().GetPortals()) + { + var searchContentSources = GetSearchContentSourceList(portal.PortalID); + foreach (var searchContentSource in searchContentSources) + { + var key = string.Format("{0}-{1}", searchContentSource.SearchTypeId, searchContentSource.ModuleDefinitionId); + if(!data.ContainsKey(key)) + data.Add(key, searchContentSource.LocalizedName); + } + } + + return data; + } + + public string GetSearchDocumentTypeDisplayName(SearchResult searchResult) + { + //ModuleDefId will be zero for non-module + var key = string.Format("{0}-{1}", searchResult.SearchTypeId, searchResult.ModuleDefId); + var keys = CBO.GetCachedObject>( + new CacheItemArgs(key, 120, CacheItemPriority.Default), SearchDocumentTypeDisplayNameCallBack); + + return keys.ContainsKey(key) ? keys[key] : string.Empty; + } + + #region Core Search APIs + + public void AddSearchDocument(SearchDocument searchDocument) + { + AddSearchDocumentInternal(searchDocument, false); + } + + private void AddSearchDocumentInternal(SearchDocument searchDocument, bool autoCommit) + { + Requires.NotNull("SearchDocument", searchDocument); + Requires.NotNullOrEmpty("UniqueKey", searchDocument.UniqueKey); + Requires.NotNullOrEmpty("Title", searchDocument.Title); + Requires.NotNegative("SearchTypeId", searchDocument.SearchTypeId); + Requires.PropertyNotEqualTo("searchDocument", "SearchTypeId", searchDocument.SearchTypeId, 0); + Requires.PropertyNotEqualTo("searchDocument", "ModifiedTimeUtc", searchDocument.ModifiedTimeUtc.ToString(CultureInfo.InvariantCulture), DateTime.MinValue.ToString(CultureInfo.InvariantCulture)); + + if (searchDocument.SearchTypeId == _moduleSearchTypeId) + { + if(searchDocument.ModuleDefId <= 0) + throw new ArgumentException("ModuleDefId must be greater than zero when SearchTypeId is for a module"); + + if (searchDocument.ModuleId <= 0) + throw new ArgumentException("ModuleId must be greater than zero when SearchTypeId is for a module"); + } + else + { + if (searchDocument.ModuleDefId > 0) + throw new ArgumentException("ModuleDefId is needed only when SearchTypeId is for a module"); + + if (searchDocument.ModuleId > 0) + throw new ArgumentException("ModuleId is needed only when SearchTypeId is for a module"); + } + + var doc = new Document(); + var sb = new StringBuilder(); + + //TODO Set setOmitTermFreqAndPositions + //TODO Check if Numeric fields need to have Store.YES or Store.NO + //TODO - Should ModifiedTime be mandatory + //TODO - Is Locale needed for a single-language site + //TODO - Sorting + + //Field.Store.YES | Stores the value. When the value is stored, the original String in its entirety is recorded in the index + //Field.Store.NO | Doesn’t store the value. This option is often used along with Index.ANALYZED to index a large text field that doesn’t need to be retrieved + // | in its original form, such as bodies of web pages, or any other type of text document. + //Index.ANALYZED | Use the analyzer to break the field’s value into a stream of separate tokens and make each token searchable + //Index.NOT_ANALYZED | Do index the field, but don’t analyze the String value.Instead, treat the Field’s entire value as a single token and make that token searchable. + + // Generic and Additional SearchDocument Params + AddSearchDocumentParamters(doc, searchDocument, sb); + + + //Remove the existing document from Lucene + DeleteSearchDocumentInternal(searchDocument, false); + + //Add only when Document is active. The previous call would have otherwise deleted the document if it existed earlier + if (searchDocument.IsActive) + { + Thread.SetData(Thread.GetNamedDataSlot(Constants.TlsSearchInfo), searchDocument); + try + { + LuceneController.Instance.Add(doc); + } + finally + { + Thread.SetData(Thread.GetNamedDataSlot(Constants.TlsSearchInfo), null); + } + } + + if (autoCommit) + { + Commit(); + } + } + + public void AddSearchDocuments(IEnumerable searchDocuments) + { + var searchDocs = searchDocuments as IList ?? searchDocuments.ToList(); + if (searchDocs.Any()) + { + const int commitBatchSize = 1024; + var idx = 0; + var added = false; + + foreach (var searchDoc in searchDocs) + { + try + { + AddSearchDocumentInternal(searchDoc, (++idx%commitBatchSize) == 0); + added = true; + } + catch (Exception ex) + { + Logger.ErrorFormat("Search Document error: {0}{1}{2}", searchDoc, Environment.NewLine, ex); + } + } + + // check so we don't commit again + if (added && (idx % commitBatchSize) != 0) + { + Commit(); + } + } + } + + public void DeleteSearchDocument(SearchDocument searchDocument) + { + Requires.NotNullOrEmpty("UniqueKey", searchDocument.UniqueKey); + Requires.NotNegative("SearchTypeId", searchDocument.SearchTypeId); + Requires.PropertyNotEqualTo("searchDocument", "SearchTypeId", searchDocument.SearchTypeId, 0); + + DeleteSearchDocumentInternal(searchDocument, false); + } + + private void DeleteSearchDocumentInternal(SearchDocument searchDocument, bool autoCommit) + { + var query = new BooleanQuery + { + {new TermQuery(new Term(Constants.UniqueKeyTag, searchDocument.UniqueKey)), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.PortalIdTag, searchDocument.PortalId, searchDocument.PortalId, true, true), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, searchDocument.SearchTypeId, searchDocument.SearchTypeId, true, true), Occur.MUST} + }; + + //ModuleCrawler Type + if (searchDocument.SearchTypeId == _moduleSearchTypeId) + { + if (searchDocument.ModuleId > 0) + query.Add(NumericRangeQuery.NewIntRange(Constants.ModuleIdTag, searchDocument.ModuleId, searchDocument.ModuleId, true, true), Occur.MUST); + query.Add(NumericRangeQuery.NewIntRange(Constants.ModuleDefIdTag, searchDocument.ModuleDefId, searchDocument.ModuleDefId, true, true), Occur.MUST); + } + + LuceneController.Instance.Delete(query); + + if (autoCommit) + { + Commit(); + } + } + + public void DeleteSearchDocumentsByModule(int portalId, int moduleId, int moduleDefId) + { + var query = new BooleanQuery + { + {NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId, SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId, true, true), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.PortalIdTag, portalId, portalId, true, true), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.ModuleIdTag, moduleId, moduleId, true, true), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.ModuleDefIdTag, moduleDefId, moduleDefId, true, true), Occur.MUST} + }; + + LuceneController.Instance.Delete(query); + } + + public void DeleteAllDocuments(int portalId, int searchTypeId) + { + var query = new BooleanQuery + { + {NumericRangeQuery.NewIntRange(Constants.PortalIdTag, portalId, portalId, true, true), Occur.MUST}, + {NumericRangeQuery.NewIntRange(Constants.SearchTypeTag, searchTypeId, searchTypeId, true, true), Occur.MUST} + }; + + LuceneController.Instance.Delete(query); + } + + public void Commit() + { + LuceneController.Instance.Commit(); + } + + public bool OptimizeSearchIndex() + { + // run optimization in background + return LuceneController.Instance.OptimizeSearchIndex(true); + } + + public SearchStatistics GetSearchStatistics() + { + return LuceneController.Instance.GetSearchStatistics(); + } + + #endregion + + #region Private methods + + private void AddSearchDocumentParamters(Document doc, SearchDocument searchDocument, StringBuilder sb) + { + //mandatory fields + doc.Add(new Field(Constants.UniqueKeyTag, StripTagsNoAttributes(searchDocument.UniqueKey, true), Field.Store.YES, Field.Index.NOT_ANALYZED)); + doc.Add(new NumericField(Constants.PortalIdTag, Field.Store.YES, true).SetIntValue(searchDocument.PortalId)); + doc.Add(new NumericField(Constants.SearchTypeTag, Field.Store.YES, true).SetIntValue(searchDocument.SearchTypeId)); + doc.Add(!string.IsNullOrEmpty(searchDocument.CultureCode) + ? new NumericField(Constants.LocaleTag, Field.Store.YES, true).SetIntValue(Localization.Localization.GetCultureLanguageID(searchDocument.CultureCode)) + : new NumericField(Constants.LocaleTag, Field.Store.YES, true).SetIntValue(-1)); + + if (!string.IsNullOrEmpty(searchDocument.Title)) + { + var field = new Field(Constants.TitleTag, StripTagsRetainAttributes(searchDocument.Title, HtmlAttributesToRetain, false, true), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); + if (_titleBoost >0 && _titleBoost != Constants.StandardLuceneBoost) field.Boost = _titleBoost / 10f; + doc.Add(field); + } + + if (!string.IsNullOrEmpty(searchDocument.Description)) + { + var field = new Field(Constants.DescriptionTag, StripTagsRetainAttributes(searchDocument.Description, HtmlAttributesToRetain, false, true), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); + if (_descriptionBoost > 0 && _descriptionBoost != Constants.StandardLuceneBoost) field.Boost = _descriptionBoost / 10f; + doc.Add(field); + } + + if (!string.IsNullOrEmpty(searchDocument.Body)) + { + doc.Add(new Field(Constants.BodyTag, StripTagsRetainAttributes(searchDocument.Body, HtmlAttributesToRetain, false, true), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); + } + + if (!string.IsNullOrEmpty(searchDocument.Url)) + { + doc.Add(new Field(Constants.UrlTag, StripTagsNoAttributes(searchDocument.Url, true), Field.Store.YES, Field.Index.NOT_ANALYZED)); + } + + if (!string.IsNullOrEmpty(searchDocument.QueryString)) + { + doc.Add(new Field(Constants.QueryStringTag, searchDocument.QueryString, Field.Store.YES, Field.Index.NOT_ANALYZED)); + } + + foreach (var kvp in searchDocument.Keywords) + { + doc.Add(new Field(StripTagsNoAttributes(Constants.KeywordsPrefixTag + kvp.Key, true), StripTagsNoAttributes(kvp.Value, true), Field.Store.YES, Field.Index.NOT_ANALYZED)); + sb.Append(StripTagsNoAttributes(kvp.Value, true)).Append(" "); + } + + foreach (var kvp in searchDocument.NumericKeys) + { + doc.Add(new NumericField(StripTagsNoAttributes(Constants.NumericKeyPrefixTag + kvp.Key, true), Field.Store.YES, true).SetIntValue(kvp.Value)); + } + + foreach (var tag in searchDocument.Tags) + { + var field = new Field(Constants.Tag, StripTagsNoAttributes(tag, true), Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); + if (_tagBoost > 0 && _tagBoost != Constants.StandardLuceneBoost) field.Boost = _tagBoost / 10f; + doc.Add(field); + } + + AddIntField(doc, searchDocument.TabId, Constants.TabIdTag); + AddIntField(doc, searchDocument.ModuleDefId, Constants.ModuleDefIdTag); + AddIntField(doc, searchDocument.ModuleId, Constants.ModuleIdTag); + AddIntField(doc, searchDocument.AuthorUserId, Constants.AuthorIdTag); + + if (searchDocument.AuthorUserId > 0) + { + var user = TestableUserController.Instance.GetUserById(searchDocument.PortalId, searchDocument.AuthorUserId); + if (user != null && !string.IsNullOrEmpty(user.DisplayName)) + { + var field = new Field(Constants.AuthorNameTag, user.DisplayName, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); + if (_authorBoost > 0 && _authorBoost != Constants.StandardLuceneBoost) field.Boost = _authorBoost / 10f; + doc.Add(field); + } + } + + if (!string.IsNullOrEmpty(searchDocument.Permissions)) + { + doc.Add(new Field(Constants.PermissionsTag, StripTagsNoAttributes(searchDocument.Permissions, true), Field.Store.YES, Field.Index.NOT_ANALYZED)); + } + + doc.Add(new NumericField(Constants.ModifiedTimeTag, Field.Store.YES, true).SetLongValue(long.Parse(searchDocument.ModifiedTimeUtc.ToString(Constants.DateTimeFormat)))); + + if (sb.Length > 0) + { + var field = new Field(Constants.ContentTag, StripTagsNoAttributes(sb.ToString(), true), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); + doc.Add(field); + if (_contentBoost > 0 && _contentBoost != Constants.StandardLuceneBoost) field.Boost = _contentBoost/10f; + } + + } + + /// + /// Add Field to Doc when supplied fieldValue > 0 + /// + private void AddIntField(Document doc, int fieldValue, string fieldTag) + { + if (fieldValue > 0) + doc.Add(new NumericField(fieldTag, Field.Store.YES, true).SetIntValue(fieldValue)); + } + + private static string StripTagsNoAttributes(string html, bool retainSpace) + { + var strippedString = !String.IsNullOrEmpty(html) ? HtmlUtils.StripTags(html, retainSpace) : html; + + // Encode and Strip again + strippedString = !String.IsNullOrEmpty(strippedString) ? HtmlUtils.StripTags(html, retainSpace) : html; + + return strippedString; + } + + private const string HtmlTagsWithAttrs = "<[A-Za-z_:][\\w:.-]*(\\s+(?\\w+\\s*?=\\s*?[\"'].*?[\"']))+\\s*/?>"; + private static readonly Regex HtmlTagsRegex = new Regex(HtmlTagsWithAttrs, RegexOptions.IgnoreCase | RegexOptions.Compiled); + + private const string AttrText = "[\"'](?.*?)[\"']"; + private static readonly Regex AttrTextRegex = new Regex(AttrText, RegexOptions.Compiled); + + private static string StripTagsRetainAttributes(string html, IEnumerable attributes, bool decoded, bool retainSpace) + { + var attributesList = attributes as IList ?? attributes.ToList(); + var attributeStr = string.Join("|", attributesList); + var strippedString = html; + var emptySpace = retainSpace ? " " : ""; + + if (!String.IsNullOrEmpty(strippedString)) + { + // Remove all opening HTML Tags with no attributes + strippedString = Regex.Replace(strippedString, @"<\w*\s*>", emptySpace, RegexOptions.IgnoreCase); + // Remove all closing HTML Tags + strippedString = Regex.Replace(strippedString, @"", emptySpace, RegexOptions.IgnoreCase); + } + + if (!String.IsNullOrEmpty(strippedString)) + { + var list = new List(); + + foreach (var match in HtmlTagsRegex.Matches(strippedString).Cast()) + { + var captures = match.Groups["attr"].Captures; + foreach (var capture in captures.Cast()) + { + var val = capture.Value.Trim(); + var pos = val.IndexOf('='); + if (pos > 0) + { + var attr = val.Substring(0, pos).Trim(); + if (attributesList.Contains(attr)) + { + var text = AttrTextRegex.Match(val).Groups["text"].Value.Trim(); + if (text.Length > 0 && !list.Contains(text)) + { + list.Add(text); + } + } + } + } + + if (list.Count > 0) + { + strippedString = strippedString.Replace(match.ToString(), string.Join(" ", list)); + list.Clear(); + } + } + } + + // If not decoded, decode and strip again. Becareful with recursive + if (!decoded) strippedString = StripTagsRetainAttributes(HttpUtility.HtmlDecode(strippedString), attributesList, true, retainSpace); + + return strippedString; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/LuceneController.cs b/DNN Platform/Library/Services/Search/Internals/LuceneController.cs new file mode 100644 index 00000000000..ceffeb4280f --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/LuceneController.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Low-level APIs to manage Lucene Layer. This is an Internal class and should not be used outside of Core + /// + internal class LuceneController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new LuceneControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/LuceneControllerImpl.cs b/DNN Platform/Library/Services/Search/Internals/LuceneControllerImpl.cs new file mode 100644 index 00000000000..0f0a72037b7 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/LuceneControllerImpl.cs @@ -0,0 +1,514 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Search.Entities; + +using Lucene.Net.Documents; +using Lucene.Net.Index; +using Lucene.Net.Search; +using Lucene.Net.Search.Vectorhighlight; +using Lucene.Net.Store; +using DotNetNuke.Instrumentation; +using System.Web; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// ----------------------------------------------------------------------------- + /// + /// The Impl Controller class for Lucene + /// + /// ----------------------------------------------------------------------------- + internal class LuceneControllerImpl : ILuceneController, IDisposable + { + #region Constants + private const string DefaultSearchFolder = @"App_Data\Search"; + private const string WriteLockFile = "write.lock"; + internal const int DefaultRereadTimeSpan = 30; // in seconds + private const int DISPOSED = 1; + private const int UNDISPOSED = 0; + #endregion + + #region Private Properties + + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(LuceneControllerImpl)); + + internal string IndexFolder { get; private set; } + + private IndexWriter _writer; + private IndexReader _idxReader; + private CachedReader _reader; + private FastVectorHighlighter _fastHighlighter; + private readonly object _writerLock = new object(); + private readonly double _readerTimeSpan; // in seconds + private readonly List _oldReaders = new List(); + private int _isDisposed = UNDISPOSED; + + private const string HighlightPreTag = "[b]"; + private const string HighlightPostTag = "[/b]"; + + private const string HtmlPreTag = ""; + private const string HtmlPostTag = ""; + + #region constructor + public LuceneControllerImpl() + { + var hostController = HostController.Instance; + + var folder = hostController.GetString(Constants.SearchIndexFolderKey, DefaultSearchFolder); + if (string.IsNullOrEmpty(folder)) folder = DefaultSearchFolder; + IndexFolder = Path.Combine(Globals.ApplicationMapPath, folder); + _readerTimeSpan = hostController.GetDouble(Constants.SearchReaderRefreshTimeKey, DefaultRereadTimeSpan); + } + + private void CheckDisposed() + { + if (Thread.VolatileRead(ref _isDisposed) == DISPOSED) + throw new ObjectDisposedException("LuceneController is disposed and cannot be used anymore"); + } + #endregion + + private IndexWriter Writer + { + get + { + if (_writer == null) + { + lock (_writerLock) + { + if (_writer == null) + { + var lockFile = Path.Combine(IndexFolder, WriteLockFile); + if (File.Exists(lockFile)) + { + try + { + // if we successd in deleting the file, move on and create a new writer; otherwise, + // the writer is locked by another instance (e.g., another server in a webfarm). + File.Delete(lockFile); + } + catch (IOException e) + { +#pragma warning disable 0618 + throw new SearchException( + "Unable to create Lucene writer (lock file is in use). Please recycle AppPool in IIS to release lock.", + e, new SearchItemInfo()); +#pragma warning restore 0618 + } + } + + CheckDisposed(); + var writer = new IndexWriter(FSDirectory.Open(IndexFolder), + new SynonymAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); + _idxReader = writer.GetReader(); + Thread.MemoryBarrier(); + _writer = writer; + } + } + } + return _writer; + } + } + + // made internal to be used in unit tests only; otherwise could be made private + internal IndexSearcher GetSearcher() + { + if (_reader == null || MustRereadIndex) + { + CheckValidIndexFolder(); + UpdateLastAccessTimes(); + InstantiateReader(); + } + + return _reader.GetSearcher(); + } + + private void InstantiateReader() + { + IndexSearcher searcher; + if (_idxReader != null) + { + //use the Reopen() method for better near-realtime when the _writer ins't null + var newReader = _idxReader.Reopen(); + if (_idxReader != newReader) + { + //_idxReader.Dispose(); -- will get disposed upon disposing the searcher + Interlocked.Exchange(ref _idxReader, newReader); + } + + searcher = new IndexSearcher(_idxReader); + } + else + { + // Note: disposing the IndexSearcher instance obtained from the next + // statement will not close the underlying reader on dispose. + searcher = new IndexSearcher(FSDirectory.Open(IndexFolder)); + } + + var reader = new CachedReader(searcher); + var cutoffTime = DateTime.Now - TimeSpan.FromSeconds(_readerTimeSpan*10); + lock (((ICollection) _oldReaders).SyncRoot) + { + CheckDisposed(); + _oldReaders.RemoveAll(r => r.LastUsed <= cutoffTime); + _oldReaders.Add(reader); + Interlocked.Exchange(ref _reader, reader); + } + } + + private DateTime _lastReadTimeUtc; + private DateTime _lastDirModifyTimeUtc; + + private bool MustRereadIndex + { + get + { + return (DateTime.UtcNow - _lastReadTimeUtc).TotalSeconds >= _readerTimeSpan && + System.IO.Directory.Exists(IndexFolder) && + System.IO.Directory.GetLastWriteTimeUtc(IndexFolder) != _lastDirModifyTimeUtc; + } + } + + private void UpdateLastAccessTimes() + { + _lastReadTimeUtc = DateTime.UtcNow; + if (System.IO.Directory.Exists(IndexFolder)) + { + _lastDirModifyTimeUtc = System.IO.Directory.GetLastWriteTimeUtc(IndexFolder); + } + } + + private void RescheduleAccessTimes() + { + // forces re-opening the reader within 30 seconds from now (used mainly by commit) + var now = DateTime.UtcNow; + if (_readerTimeSpan > DefaultRereadTimeSpan && (now - _lastReadTimeUtc).TotalSeconds > DefaultRereadTimeSpan) + { + _lastReadTimeUtc = now - TimeSpan.FromSeconds(_readerTimeSpan - DefaultRereadTimeSpan); + } + } + + private void CheckValidIndexFolder() + { + if (!System.IO.Directory.Exists(IndexFolder) || System.IO.Directory.GetFiles(IndexFolder, "*.*").Length == 0) + { + throw new SearchIndexEmptyException("Search indexing directory is either empty or does not exist"); + } + } + + private FastVectorHighlighter FastHighlighter + { + get + { + if (_fastHighlighter == null) + { + FragListBuilder fragListBuilder = new SimpleFragListBuilder(); + FragmentsBuilder fragmentBuilder = new ScoreOrderFragmentsBuilder( + new[] { HighlightPreTag }, new[] { HighlightPostTag }); + _fastHighlighter = new FastVectorHighlighter(true, true, fragListBuilder, fragmentBuilder); + } + return _fastHighlighter; + } + } + + #endregion + + public IEnumerable Search( + LuceneQuery luceneQuery, out int totalHits, SecurityCheckerDelegate securityChecker = null) + { + Requires.NotNull("LuceneQuery", luceneQuery); + Requires.NotNull("LuceneQuery.Query", luceneQuery.Query); + Requires.PropertyNotEqualTo("LuceneQuery", "PageSize", luceneQuery.PageSize, 0); + Requires.PropertyNotEqualTo("LuceneQuery", "PageIndex", luceneQuery.PageIndex, 0); + + //TODO - Explore simple highlighter as it does not give partial words + var highlighter = FastHighlighter; + var fieldQuery = highlighter.GetFieldQuery(luceneQuery.Query); + + var maxResults = luceneQuery.PageIndex*luceneQuery.PageSize; + var minResults = maxResults - luceneQuery.PageSize + 1; + + var searcher = GetSearcher(); + var topDocs = new SearchSecurityTrimmer(searcher, securityChecker, luceneQuery); + searcher.Search(luceneQuery.Query, null, topDocs); + totalHits = topDocs.TotalHits; + + if (Logger.IsDebugEnabled) + { + var sb = GetSearcResultExplanation(luceneQuery, topDocs.ScoreDocs, searcher); + Logger.Debug(sb); + } + + //Page doesn't exist + if (totalHits < minResults) + return new List(); + + return topDocs.ScoreDocs.Select(match => + new LuceneResult + { + Document = searcher.Doc(match.Doc), + Score = match.Score, + DisplayScore = GetDisplayScoreFromMatch(match.ToString()), + TitleSnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.TitleTag, luceneQuery.TitleSnippetLength), + BodySnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.BodyTag, luceneQuery.BodySnippetLength), + DescriptionSnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.DescriptionTag, luceneQuery.TitleSnippetLength), + TagSnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.Tag, luceneQuery.TitleSnippetLength), + AuthorSnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.AuthorNameTag, luceneQuery.TitleSnippetLength), + ContentSnippet = GetHighlightedText(highlighter, fieldQuery, searcher, match, Constants.ContentTag, luceneQuery.TitleSnippetLength) + }).ToList(); + } + + private string GetHighlightedText(FastVectorHighlighter highlighter, FieldQuery fieldQuery, IndexSearcher searcher, ScoreDoc match, string tag, int length) + { + var s = highlighter.GetBestFragment(fieldQuery, searcher.IndexReader, match.Doc, tag, length); + if (!string.IsNullOrEmpty(s)) + { + s = HttpUtility.HtmlEncode(s).Replace(HighlightPreTag, HtmlPreTag).Replace(HighlightPostTag, HtmlPostTag); + } + return s; + } + + private static StringBuilder GetSearcResultExplanation(LuceneQuery luceneQuery, IEnumerable scoreDocs, IndexSearcher searcher) + { + var sb = new StringBuilder(); + sb.AppendLine("Query: " + luceneQuery.Query.ToString()); + foreach (var match in scoreDocs) + { + var explanation = searcher.Explain(luceneQuery.Query, match.Doc); + sb.AppendLine("-------------------"); + var doc = searcher.Doc(match.Doc); + sb.AppendLine(doc.Get(Constants.TitleTag)); + sb.AppendLine(explanation.ToString()); + } + return sb; + } + + /// + /// Extract the Score portion of the match.ToString() + /// + private string GetDisplayScoreFromMatch(string match) + { + var displayScore = string.Empty; + if (!string.IsNullOrEmpty(match)) + { + var beginPos = match.IndexOf('['); + var endPos = match.LastIndexOf(']'); + if (beginPos > 0 && endPos > 0 && endPos > beginPos) displayScore = match.Substring(beginPos + 1, endPos - beginPos - 1); + } + + return displayScore; + } + + public void Add(Document doc) + { + Requires.NotNull("searchDocument", doc); + if (doc.GetFields().Count > 0) + { + try + { + Writer.AddDocument(doc); + } + catch (OutOfMemoryException) + { + lock (_writerLock) + { + // as suggested by Lucene's doc + DisposeWriter(); + Writer.AddDocument(doc); + } + } + } + } + + public void Delete(Query query) + { + Requires.NotNull("luceneQuery", query); + Writer.DeleteDocuments(query); + } + + public void Commit() + { + if (_writer != null) + { + lock (_writerLock) + { + if (_writer != null) + { + CheckDisposed(); + _writer.Commit(); + RescheduleAccessTimes(); + } + } + } + } + + public bool OptimizeSearchIndex(bool doWait) + { + var writer = _writer; + if (writer != null && writer.HasDeletions()) + { + if (doWait) + { + Logger.Debug("Compacting Search Index - started"); + } + + CheckDisposed(); + //optimize down to "> 1 segments" for better performance than down to 1 + _writer.Optimize(4, doWait); + + if (doWait) + { + Commit(); + Logger.Debug("Compacting Search Index - finished"); + } + + return true; + } + + return false; + } + + public bool HasDeletions() + { + CheckDisposed(); + var searcher = GetSearcher(); + return searcher.IndexReader.HasDeletions; + } + + public int MaxDocsCount() + { + CheckDisposed(); + var searcher = GetSearcher(); + return searcher.IndexReader.MaxDoc; + } + + public int SearchbleDocsCount() + { + CheckDisposed(); + var searcher = GetSearcher(); + return searcher.IndexReader.NumDocs(); + } + + // works on the computer (in a web-farm) that runs under the scheduler + public SearchStatistics GetSearchStatistics() + { + CheckDisposed(); + var searcher = GetSearcher(); + + var files = System.IO.Directory.GetFiles(IndexFolder, "*.*"); + var size = files.Select(name => new FileInfo(name)).Select(fInfo => fInfo.Length).Sum(); + + return new SearchStatistics + { + //Hack: seems that NumDocs/MaxDoc are buggy and return incorrect/swapped values + TotalActiveDocuments = searcher.IndexReader.NumDocs(), + TotalDeletedDocuments = searcher.IndexReader.NumDeletedDocs, + IndexLocation = IndexFolder, + LastModifiedOn = System.IO.Directory.GetLastWriteTimeUtc(IndexFolder), + IndexDbSize = size + }; + } + + public void Dispose() + { + var status = Interlocked.CompareExchange(ref _isDisposed, DISPOSED, UNDISPOSED); + if (status == UNDISPOSED) + { + DisposeWriter(); + DisposeReaders(); + } + } + + private void DisposeWriter() + { + if (_writer != null) + { + lock (_writerLock) + { + if (_writer != null) + { + _idxReader.Dispose(); + _idxReader = null; + + _writer.Commit(); + _writer.Dispose(); + _writer = null; + } + } + } + } + + private void DisposeReaders() + { + lock (((ICollection)_oldReaders).SyncRoot) + { + foreach (var rdr in _oldReaders) + { + rdr.Dispose(); + } + _oldReaders.Clear(); + _reader = null; + } + } + + class CachedReader : IDisposable + { + public DateTime LastUsed { get; private set; } + private readonly IndexSearcher _searcher; + + public CachedReader(IndexSearcher searcher) + { + _searcher = searcher; + UpdateLastUsed(); + } + + public IndexSearcher GetSearcher() + { + UpdateLastUsed(); + return _searcher; + } + + private void UpdateLastUsed() + { + LastUsed = DateTime.Now; + } + + public void Dispose() + { + _searcher.Dispose(); + _searcher.IndexReader.Dispose(); + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/LuceneQuery.cs b/DNN Platform/Library/Services/Search/Internals/LuceneQuery.cs new file mode 100644 index 00000000000..082555a75c7 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/LuceneQuery.cs @@ -0,0 +1,82 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Search.Entities; + +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Lucene Specific Query Object to be passed into Lucene for Search + /// + internal class LuceneQuery + { + /// + /// Lucene's original Query Object + /// + public Query Query { get; set; } + + /// + /// Lucene's original Sort Object. Default is by Relevance + /// + public Sort Sort { get; set; } + + /// + /// Page Index for the result, e.g. pageIndex=1 and pageSize=10 indicates first 10 hits. Default value is 1 + /// + public int PageIndex { get; set; } + + /// + /// Page size of the search result. Default value is 10. + /// + public int PageSize { get; set; } + + /// + /// Maximum length of highlighted title field in the results + /// + public int TitleSnippetLength { get; set; } + + /// + /// Maximum length of highlighted title field in the results + /// + public int BodySnippetLength { get; set; } + + #region constructor + + public LuceneQuery() + { + PageIndex = 1; + TitleSnippetLength = 60; + BodySnippetLength = 100; + PageSize = 10; + Sort = Sort.RELEVANCE; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/LuceneResult.cs b/DNN Platform/Library/Services/Search/Internals/LuceneResult.cs new file mode 100644 index 00000000000..47e39bbbb77 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/LuceneResult.cs @@ -0,0 +1,87 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Services.Search.Entities; + +using Lucene.Net.Documents; +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Lucene Specific Query Result + /// + internal class LuceneResult + { + /// + /// Lucene's original Document Object + /// + public Document Document { get; set; } + + /// + /// Lucene's original Score. The score of this document for the query. + /// + /// This field may not be reliable as most of the time it contains Nan. Use DisplayScore instead + public float Score { get; set; } + + /// + /// Lucene's original Score in String format, e.g. 1.45678 or 0.87642. The score of this document for the query. + /// + /// This field is more reliable than the float version of Score. + public string DisplayScore { get; set; } + + /// + /// Highlighted Title Snippet. This may be empty for synonym based search + /// + public string TitleSnippet { get; set; } + + /// + /// Highlighted Body Snippet. This may be empty for synonym based search + /// + public string BodySnippet { get; set; } + + /// + /// Highlighted Description Snippet. This may be empty for synonym based search + /// + public string DescriptionSnippet { get; set; } + + /// + /// Highlighted Tag Snippet. This may be empty for synonym based search + /// + public string TagSnippet { get; set; } + + /// + /// Highlighted Author Snippet. This may be empty for synonym based search + /// + public string AuthorSnippet { get; set; } + + /// + /// Highlighted Content Snippet. This may be empty for synonym based search + /// + public string ContentSnippet { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/SearchContentSource.cs b/DNN Platform/Library/Services/Search/Internals/SearchContentSource.cs new file mode 100644 index 00000000000..76e84382839 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchContentSource.cs @@ -0,0 +1,13 @@ +using System; + +using DotNetNuke.Services.Search.Entities; + +namespace DotNetNuke.Services.Search.Internals +{ + public class SearchContentSource: SearchType + { + public string LocalizedName { get; set; } + + public int ModuleDefinitionId { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/SearchHelper.cs b/DNN Platform/Library/Services/Search/Internals/SearchHelper.cs new file mode 100644 index 00000000000..4a56ad58008 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchHelper.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// Internal Search Controller. This is an Internal class and should not be used outside of Core + /// + public class SearchHelper : ServiceLocator + { + protected override Func GetFactory() + { + return () => new SearchHelperImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/SearchHelperImpl.cs b/DNN Platform/Library/Services/Search/Internals/SearchHelperImpl.cs new file mode 100644 index 00000000000..11244102a8f --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchHelperImpl.cs @@ -0,0 +1,623 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.Caching; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Entities.Controllers; +using System.IO; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + internal class SearchHelperImpl : ISearchHelper + { + private const string SearchTypesCacheKey = "SearchTypes"; + private const string SynonymTermsCacheKey = "SynonymTerms"; + private const string SynonymGroupsCacheKey = "SynonymsGroups"; + private const string CacheKeyFormat = "{0}_{1}_{2}"; + private const string LastIndexKeyFormat = "{0}_{1}"; + private const string SearchStopWordsCacheKey = "SearchStopWords"; + private const string ResourceFileRelativePathWithoutExt = "/DesktopModules/Admin/SearchAdmin/App_LocalResources/SearchAdmin.ascx"; + private readonly IList EmptySynonums = new List(0); + + #region SearchType APIs + + public IEnumerable GetSearchTypes() + { + var cachArg = new CacheItemArgs(SearchTypesCacheKey, 120, CacheItemPriority.Default); + return CBO.GetCachedObject>(cachArg, GetSearchTypesCallBack); + } + + public SearchType GetSearchTypeByName(string searchTypeName) + { + return GetSearchTypes().Single(t => t.SearchTypeName == searchTypeName); + } + + #endregion + + #region Synonym Management APIs + + private IDictionary> GetSynonymTerms(int portalId, string cultureCode) + { + var cacheKey = string.Format("{0}_{1}_{2}", SynonymTermsCacheKey, portalId, cultureCode); + var cachArg = new CacheItemArgs(cacheKey, 120, CacheItemPriority.Default); + return CBO.GetCachedObject>>(cachArg, SynonymTermsCallBack); + } + + public IEnumerable GetSynonyms(int portalId, string cultureCode, string term) + { + var terms = GetSynonymTerms(portalId, cultureCode); + IList synonyms; + if (terms == null || !terms.TryGetValue((term ?? string.Empty).ToLower(), out synonyms)) + { + synonyms = EmptySynonums; + } + return synonyms; + } + + public IEnumerable GetSynonymsGroups(int portalId, string cultureCode) + { + var cacheKey = string.Format(CacheKeyFormat, SynonymGroupsCacheKey, portalId, cultureCode); + var cachArg = new CacheItemArgs(cacheKey, 120, CacheItemPriority.Default); + return CBO.GetCachedObject>(cachArg, GetSynonymsGroupsCallBack); + } + + public int AddSynonymsGroup(string synonymsTags, int portalId, string cultureCode, out string duplicateWord) + { + duplicateWord = null; + if (string.IsNullOrEmpty(synonymsTags)) return 0; + if (portalId < 0) return 0; + + var userId = PortalSettings.Current.UserId; + var list = GetSynonymsGroups(portalId, cultureCode); + var tags = synonymsTags.ToLowerInvariant().Split(','); + + if (!tags.Any()) return 0; + + foreach (var group in list) + { + var groupTags = group.SynonymsTags.ToLowerInvariant().Split(','); + duplicateWord = tags.FirstOrDefault(groupTags.Contains); + if (!string.IsNullOrEmpty(duplicateWord)) return 0; + } + + var newId = DataProvider.Instance().AddSynonymsGroup(synonymsTags, userId, portalId, cultureCode); + var cacheKey = string.Format(CacheKeyFormat, SynonymGroupsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + + cacheKey = string.Format(CacheKeyFormat, SynonymTermsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + + return newId; + } + + public int UpdateSynonymsGroup(int synonymsGroupId, string synonymsTags, int portalId, string cultureCode, out string duplicateWord) + { + duplicateWord = null; + if (synonymsGroupId <= 0) return 0; + if (string.IsNullOrEmpty(synonymsTags)) return 0; + + var userId = PortalSettings.Current.UserId; + var list = GetSynonymsGroups(portalId, cultureCode); + var tags = synonymsTags.ToLowerInvariant().Split(','); + + if (!tags.Any()) return 0; + + foreach (var group in list) + { + if (group.SynonymsGroupId != synonymsGroupId) + { + var groupTags = group.SynonymsTags.ToLowerInvariant().Split(','); + duplicateWord = tags.FirstOrDefault(groupTags.Contains); + if (!string.IsNullOrEmpty(duplicateWord)) return 0; + } + } + + DataProvider.Instance().UpdateSynonymsGroup(synonymsGroupId, synonymsTags, userId); + var cacheKey = string.Format(CacheKeyFormat, SynonymGroupsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + + cacheKey = string.Format(CacheKeyFormat, SynonymTermsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + return synonymsGroupId; + } + + public void DeleteSynonymsGroup(int synonymsGroupId, int portalId, string cultureCode) + { + if (synonymsGroupId <= 0) return; + + DataProvider.Instance().DeleteSynonymsGroup(synonymsGroupId); + var cacheKey = string.Format(CacheKeyFormat, SynonymGroupsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + + cacheKey = string.Format(CacheKeyFormat, SynonymTermsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + } + + public SearchStopWords GetSearchStopWords(int portalId, string cultureCode) + { + var cacheKey = string.Format(CacheKeyFormat, SearchStopWordsCacheKey, portalId, cultureCode); + var cachArg = new CacheItemArgs(cacheKey, 120, CacheItemPriority.Default); + var list = CBO.GetCachedObject>(cachArg, GetSearchStopWordsCallBack); + return list == null ? null : list.FirstOrDefault(); + } + + public int AddSearchStopWords(string stopWords, int portalId, string cultureCode) + { + if (string.IsNullOrEmpty(stopWords)) return 0; + if (portalId < 0) return 0; + if (string.IsNullOrEmpty(cultureCode)) return 0; + + var tags = stopWords.ToLowerInvariant().Split(','); + if (!tags.Any()) return 0; + + var userId = PortalSettings.Current.UserId; + var newId = DataProvider.Instance().AddSearchStopWords(stopWords, userId, portalId, cultureCode); + var cacheKey = string.Format(CacheKeyFormat, SearchStopWordsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + return newId; + } + + public int UpdateSearchStopWords(int stopWordsId, string stopWords, int portalId, string cultureCode) + { + if (string.IsNullOrEmpty(stopWords)) return 0; + if (portalId < 0) return 0; + if (stopWordsId <= 0) return 0; + if (string.IsNullOrEmpty(cultureCode)) return 0; + + var tags = stopWords.ToLowerInvariant().Split(','); + if (!tags.Any()) return 0; + + var userId = PortalSettings.Current.UserId; + DataProvider.Instance().UpdateSearchStopWords(stopWordsId, stopWords, userId); + var cacheKey = string.Format(CacheKeyFormat, SearchStopWordsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + return stopWordsId; + } + + public void DeleteSearchStopWords(int stopWordsId, int portalId, string cultureCode) + { + if (stopWordsId <= 0) return; + + DataProvider.Instance().DeleteSearchStopWords(stopWordsId); + var cacheKey = string.Format(CacheKeyFormat, SearchStopWordsCacheKey, portalId, cultureCode); + DataCache.ClearCache(cacheKey); + } + + #endregion + + #region Reindex and Compact settings management API + + public DateTime GetSearchReindexRequestTime(int portalId) + { + var requestedOn = SqlDateTime.MinValue.Value; + string reindexRequest; + + if (portalId < 0) + { + // host level setting + reindexRequest = HostController.Instance.GetString(Constants.SearchReindexSettingName, Null.NullString); + } + else + { + // portal level setting + reindexRequest = PortalController.GetPortalSetting(Constants.SearchReindexSettingName, portalId, Null.NullString); + } + + if (reindexRequest != Null.NullString) + { + DateTime.TryParseExact(reindexRequest, Constants.ReinsdexDateTimeFormat, null, DateTimeStyles.None, out requestedOn); + } + + return requestedOn; + } + + public DateTime SetSearchReindexRequestTime(int portalId) + { + var now = DateTime.Now; + var text = now.ToString(Constants.ReinsdexDateTimeFormat); + + if (portalId < 0) + { + // host level setting + HostController.Instance.Update(Constants.SearchReindexSettingName, text); + } + else + { + // portal level setting + PortalController.UpdatePortalSetting(portalId, Constants.SearchReindexSettingName, text, true, string.Empty); + } + + return now; + } + + public bool GetSearchCompactFlag() + { + return "1" == HostController.Instance.GetString(Constants.SearchoptimizeFlagName, Null.NullString); + } + + public void SetSearchReindexRequestTime(bool turnOn) + { + HostController.Instance.Update(Constants.SearchoptimizeFlagName, turnOn ? "1" : "0"); + } + + /// + /// Determines whether there was a request to re-index the site since a specific date/time + /// + public bool IsReindexRequested(int portalId, DateTime startDate) + { + var reindexDateTime = GetSearchReindexRequestTime(portalId); + return reindexDateTime > startDate; + } + + /// + /// Returns a collection of portal ID's to reindex if it was requested since last indexing + /// + /// + /// + public IEnumerable GetPortalsToReindex(DateTime startDate) + { + var portals2Reindex = new PortalController().GetPortals().Cast() + .Where(portal => IsReindexRequested(portal.PortalID, startDate)) + .Select(portal => portal.PortalID); + + if (IsReindexRequested(-1, startDate)) + { + // Include Host Level + portals2Reindex = portals2Reindex.Concat(new[] { -1 }); + } + + return portals2Reindex.ToArray(); + } + + public DateTime GetLastSuccessfulIndexingDateTime(int scheduleId) + { + var name = string.Format(LastIndexKeyFormat, Constants.SearchLastSuccessIndexName, scheduleId); + var lastSuccessfulDateTime = SqlDateTime.MinValue.Value; + var lastValue = HostController.Instance.GetString(name, Null.NullString); + if (lastValue != Null.NullString) + { + DateTime.TryParseExact(lastValue, Constants.ReinsdexDateTimeFormat, null, DateTimeStyles.None, out lastSuccessfulDateTime); + } + + return lastSuccessfulDateTime; + } + + public void SetLastSuccessfulIndexingDateTime(int scheduleId, DateTime startDate) + { + var name = string.Format(LastIndexKeyFormat, Constants.SearchLastSuccessIndexName, scheduleId); + HostController.Instance.Update(name, startDate.ToString(Constants.ReinsdexDateTimeFormat)); + } + + #endregion + + #region Other Search Helper methods + + public Tuple GetSearchMinMaxLength() + { + var hostController = HostController.Instance; + var minWordLength = hostController.GetInteger(Constants.SearchMinLengthKey, Constants.DefaultMinLen); + var maxWordLength = hostController.GetInteger(Constants.SearchMaxLengthKey, Constants.DefaultMaxLen); + + if (minWordLength < Constants.MinimumMinLen) minWordLength = Constants.MinimumMinLen; + if (maxWordLength < Constants.MinimumMaxLen) maxWordLength = Constants.MinimumMaxLen; + + if (minWordLength > Constants.MaximumMinLen) minWordLength = Constants.MaximumMinLen; + if (maxWordLength > Constants.MaximumMaxLen) maxWordLength = Constants.MaximumMaxLen; + + if (minWordLength > maxWordLength) + { + throw new InvalidDataException( + string.Format("Search Analyzer: min word length ({0}) is greater than max wrod length ({1}) value", minWordLength, maxWordLength)); + } + + return new Tuple(minWordLength, maxWordLength); + } + + /// + /// Processes and re-phrases the search text by looking into exact-match and wildcard option + /// + /// + /// + /// cleaned and pre-processed search phrase + public string RephraseSearchText(string searchPhrase, bool useWildCard) + { + searchPhrase = CleanSearchPhrase(searchPhrase); + + if (!useWildCard && !searchPhrase.Contains("\"")) + { + return searchPhrase; + } + + // we have a quotation marks and/or wildcard search, adjust accordingly + var chars = searchPhrase.ToArray(); + var insideQuote = false; + var newPhraseBulder = new StringBuilder(); + var currentWord = new StringBuilder(); + + foreach (var c in chars) + { + currentWord.Append(c); + switch (c) + { + case '"': + insideQuote = !insideQuote; + if (!insideQuote) + { + newPhraseBulder.Append(currentWord.ToString() + " "); + currentWord.Clear(); + } + break; + case ' ': + if (!insideQuote && useWildCard) + { + // end of a word; we need to append a wild card to search when needed + newPhraseBulder.Append(FixLastWord(currentWord.ToString().Trim()) + " "); + currentWord.Clear(); + } + break; + } + } + + // in case the a double quote was not closed + if (insideQuote) + { + currentWord.Append('"'); + newPhraseBulder.Append(currentWord.ToString()); + } + else if (useWildCard) + { + newPhraseBulder.Append(FixLastWord(currentWord.ToString().Trim())); + } + else + { + newPhraseBulder.Append(currentWord.ToString()); + } + + return newPhraseBulder.ToString().Trim().Replace(" ", " "); + } + + #endregion + + #region private methods + + private string FixLastWord(string lastWord) + { + if (string.IsNullOrEmpty(lastWord)) + return string.Empty; + + if (lastWord.IndexOfAny(new[] {'~', '*'}) < 0) + { + var beginIsGroup = false; + var endIsGroup = false; + var wordStartPos = 0; + var wordEndPos = lastWord.Length; + + var c1 = lastWord[0]; + var c2 = lastWord[wordEndPos - 1]; + + if (c1 == '(' || c1 == '{' || c1 == '[') + { + wordStartPos++; + beginIsGroup = true; + } + + if (c2 == ')' || c2 == '}' || c2 == ']') + { + wordEndPos--; + endIsGroup = true; + } + + // pos points to next character after space + var wordLen = wordEndPos - wordStartPos; + lastWord = lastWord.Substring(wordStartPos, wordLen); + + // reserved words used for logical operations are case sensitive + if (lastWord.Length > 0 && lastWord != "AND" && lastWord != "OR") + { + lastWord = (beginIsGroup && endIsGroup) + ? string.Format("{0} OR {0}*", lastWord) + : string.Format("({0} OR {0}*)", lastWord); + } + + if (beginIsGroup) lastWord = c1 + lastWord; + if (endIsGroup) lastWord += c2; + } + return lastWord; + } + + private string CleanSearchPhrase(string searchPhrase) + { + var chars = searchPhrase.ToCharArray(); + var hasExactMatch = false; + int pos; + + // replace all forms of double quotes or whitespace with the normal ones + for (pos = 0; pos < chars.Length; pos++) + { + var c = chars[pos]; + switch (c) + { + case '\u02BA': // 'ʺ' Modifier Letter Double Prime + case '\u02EE': // 'ˮ' Modifier Letter Double Apostrophe + case '\u00AB': // [LEFT-POINTING DOUBLE ANGLE QUOTATION MARK] + case '\u00BB': // [RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK] + case '\u201C': // [LEFT DOUBLE QUOTATION MARK] + case '\u201D': // [RIGHT DOUBLE QUOTATION MARK] + case '\u201E': // [DOUBLE LOW-9 QUOTATION MARK] + case '\u2033': // [DOUBLE PRIME] + case '\u2036': // [REVERSED DOUBLE PRIME] + case '\u275D': // [HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT] + case '\u275E': // [HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT] + case '\u276E': // [HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT] + case '\u276F': // [HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT] + case '\uFF02': // [FULLWIDTH QUOTATION MARK] + chars[pos] = '"'; // Quotation Mark + hasExactMatch = true; + break; + case '\u0009': // HT, Horizontal Tab + case '\u000A': // LF, Line feed + case '\u000B': // VT, Vertical Tab + case '\u000C': // FF, Form feed + case '\u000D': // CR, Carriage return + case '\u00A0': // NBSP, No-break space + chars[pos] = ' '; // space + break; + } + } + + // remove double apaces + var cleaned = new string(chars).Replace(" ", " "); + + if (hasExactMatch) + { + // remove empty double quotes + cleaned = cleaned.Replace("\"\"", "").Replace("\" \"", ""); + } + + return cleaned; + } + + private object SynonymTermsCallBack(CacheItemArgs cacheItem) + { + var parts = cacheItem.CacheKey.Split('_'); + var allTerms = new Dictionary>(); + var portalId = int.Parse(parts[1]); + var cultureCode = parts[2]; + var groups = GetSynonymsGroups(portalId, cultureCode); + if (groups == null) return allTerms; + + foreach (var synonymsGroup in groups) + { + var terms = new Dictionary>(); + var groupTags = synonymsGroup.SynonymsTags.ToLowerInvariant().Split(','); + //add the first key first + foreach (var tag in groupTags) + { + if (!terms.ContainsKey(tag)) + terms.Add(tag, new List()); + } + + //add synonyms + foreach (var term in terms) + { + foreach (var syn in terms) + { + if (term.Key != syn.Key) + term.Value.Add(syn.Key); + } + } + + foreach (var term in terms) + { + allTerms.Add(term.Key, term.Value); + } + } + + return allTerms; + } + + private object GetSearchTypesCallBack(CacheItemArgs cacheItem) + { + return CBO.FillCollection(DataProvider.Instance().GetAllSearchTypes()); + } + + private object GetSearchStopWordsCallBack(CacheItemArgs cacheItem) + { + var splittedKeys = cacheItem.CacheKey.Split('_'); + var portalId = int.Parse(splittedKeys[1]); + var cultureCode = splittedKeys[2]; + + EnsurePortalDefaultsAreSet(portalId); + + return CBO.FillCollection(DataProvider.Instance().GetSearchStopWords(portalId, cultureCode)); + } + + private void EnsurePortalDefaultsAreSet(int portalId) + { + const string setting = "SearchAdminInitialization"; + + //check portal settings first + if (PortalController.GetPortalSetting(setting, portalId, "false") != "false") return; + + //Portal may not be present, especially during installation + if (new PortalController().GetPortal(portalId) == null) return; + + foreach (var locale in LocaleController.Instance.GetLocales(portalId).Values) + { + var resourceFile = GetResourceFile(locale.Code); + + var currentStopWords = CBO.FillCollection(DataProvider.Instance().GetSearchStopWords(portalId, locale.Code)); + if (currentStopWords == null || currentStopWords.Count == 0) + { + //Add Default StopWord + var defaultStopWords = Localization.Localization.GetString("DefaultStopwordGroup", resourceFile); + if (!string.IsNullOrEmpty(defaultStopWords)) DataProvider.Instance().AddSearchStopWords(defaultStopWords, 1, portalId, locale.Code); + } + + var currentSynonymGroups = CBO.FillCollection(DataProvider.Instance().GetAllSynonymsGroups(portalId, locale.Code)); + if (currentSynonymGroups == null || currentSynonymGroups.Count == 0) + { + //Add Default Synonym + var defaultSynonymsGroup = Localization.Localization.GetString("DefaultSynonymGroup", resourceFile); + if (!string.IsNullOrEmpty(defaultSynonymsGroup)) DataProvider.Instance().AddSynonymsGroup(defaultSynonymsGroup, 1, portalId, locale.Code); + } + } + //Update Portal Settings + PortalController.UpdatePortalSetting(portalId, setting, "true", true); + } + + private string GetResourceFile(string cultureCode) + { + var cultureRelativePath = "~" + ResourceFileRelativePathWithoutExt + "." + cultureCode + ".resx"; + const string regularRelativePath = "~" + ResourceFileRelativePathWithoutExt + ".resx"; + return File.Exists(Path.Combine(Globals.ApplicationMapPath, ResourceFileRelativePathWithoutExt + "." + cultureCode + ".resx")) ? cultureRelativePath : regularRelativePath; + } + + private object GetSynonymsGroupsCallBack(CacheItemArgs cacheItem) + { + var portalId = int.Parse(cacheItem.CacheKey.Split('_')[1]); + var cultureCode = cacheItem.CacheKey.Split('_')[2]; + + EnsurePortalDefaultsAreSet(portalId); + + return CBO.FillCollection(DataProvider.Instance().GetAllSynonymsGroups(portalId, cultureCode)); + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/SearchQueryAnalyzer.cs b/DNN Platform/Library/Services/Search/Internals/SearchQueryAnalyzer.cs new file mode 100644 index 00000000000..8ad5a81c3a4 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchQueryAnalyzer.cs @@ -0,0 +1,70 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; + +using DotNetNuke.Entities.Controllers; + +using Lucene.Net.Analysis; +using Lucene.Net.Analysis.Standard; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// This is responsible for the filters chain that analyzes search documents/queries + /// + internal class SearchQueryAnalyzer : Analyzer + { + private readonly bool _useStemmingFilter; + + public SearchQueryAnalyzer(bool useStemmingFilter) + { + _useStemmingFilter = useStemmingFilter; + } + + public override TokenStream TokenStream(string fieldName, TextReader reader) + { + var wordLengthMinMax = SearchHelper.Instance.GetSearchMinMaxLength(); + + //Note: the order of filtering is important for both operation and performane, so we try to make it work faster + // Also, note that filters are applied from the innermost outwards. + var filter = + new ASCIIFoldingFilter( // accents filter + new LowerCaseFilter( + new LengthFilter( + new StandardFilter( + new StandardTokenizer(Constants.LuceneVersion, reader) + ) + , wordLengthMinMax.Item1, wordLengthMinMax.Item2) + ) + ); + + if (!_useStemmingFilter) + return filter; + + return new PorterStemFilter(filter); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/SearchSecurityTrimmer.cs b/DNN Platform/Library/Services/Search/Internals/SearchSecurityTrimmer.cs new file mode 100644 index 00000000000..741feb06a88 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchSecurityTrimmer.cs @@ -0,0 +1,139 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; + +using Lucene.Net.Documents; +using Lucene.Net.Index; +using Lucene.Net.Search; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + internal delegate bool SecurityCheckerDelegate(Document luceneResult); + + internal class SearchSecurityTrimmer : Collector + { + private readonly SecurityCheckerDelegate _securityChecker; + private readonly IndexSearcher _searcher; + + private Scorer _scorer; + private int _docBase, _totalHits; + private readonly LuceneQuery _query; + private readonly List _hitDocs; + private List _scoreDocs; + + public SearchSecurityTrimmer(IndexSearcher searcher, SecurityCheckerDelegate securityChecker, LuceneQuery luceneQuery) + { + _securityChecker = securityChecker; + _searcher = searcher; + _query = luceneQuery; + _hitDocs = new List(16); + } + + public override bool AcceptsDocsOutOfOrder { get { return false; } } + + public override void SetNextReader(IndexReader reader, int docBase) + { + _docBase = docBase; + } + + public override void SetScorer(Scorer scorer) + { + _scorer = scorer; + } + + public override void Collect(int doc) + { + _hitDocs.Add(new ScoreDoc(doc + _docBase, _scorer.Score())); + } + + public int TotalHits + { + get + { + if (_scoreDocs == null) PrepareScoreDocs(); + return _totalHits; + } + } + + public List ScoreDocs + { + get + { + if (_scoreDocs == null) PrepareScoreDocs(); + return _scoreDocs; + } + } + + private void PrepareScoreDocs() + { + int skippedSoFar; + var collectedSoFar = skippedSoFar = 0; + var pageSize = _query.PageSize; + var toSkip = _query.PageIndex <= 1 ? 0 : ((_query.PageIndex - 1) * pageSize); + _scoreDocs = new List(pageSize); + IEnumerable tempDocs; + + _totalHits = _hitDocs.Count; + + if (ReferenceEquals(Sort.RELEVANCE, _query.Sort)) + { + tempDocs = _hitDocs.OrderByDescending(d => d.Score).ThenBy(d => d.Doc); + } + else + { + //HACK: order by document date descending based on date's "StringValue" as below + // and we don't take into consideration all of the Sort fields; only the first + tempDocs = _hitDocs.Select(d => new { SDoc = d, Document = _searcher.Doc(d.Doc) }) + .OrderByDescending(rec => rec.Document.GetField(Constants.ModifiedTimeTag).StringValue) + .ThenBy(rec => rec.Document.Boost) + .Select(rec => rec.SDoc); + } + + foreach (var scoreDoc in tempDocs) + { + if (_securityChecker == null || _securityChecker(_searcher.Doc(scoreDoc.Doc))) + { + if (skippedSoFar < toSkip) + { + skippedSoFar++; + continue; + } + + _scoreDocs.Add(scoreDoc); + if (++collectedSoFar == pageSize) + { + break; + } + } + else + { + _totalHits--; + } + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/Internals/SearchStatistics.cs b/DNN Platform/Library/Services/Search/Internals/SearchStatistics.cs new file mode 100644 index 00000000000..83fc718b812 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SearchStatistics.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DotNetNuke.Services.Search.Internals +{ + public class SearchStatistics + { + public int TotalActiveDocuments { get; set; } + public int TotalDeletedDocuments { get; set; } + public string IndexLocation { get; set; } + public DateTime LastModifiedOn { get; set; } + public long IndexDbSize { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/SynonymAnalyzer.cs b/DNN Platform/Library/Services/Search/Internals/SynonymAnalyzer.cs new file mode 100644 index 00000000000..e31c3d90143 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SynonymAnalyzer.cs @@ -0,0 +1,107 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Search.Entities; +using Lucene.Net.Analysis; +using Lucene.Net.Analysis.Standard; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// This is responsible for the filters chain that analyzes search documents/queries + /// + internal class SynonymAnalyzer : Analyzer + { + private static readonly PortalController PortalController = new PortalController(); + + public override TokenStream TokenStream(string fieldName, TextReader reader) + { + var stops = GetStopWords(); + var wordLengthMinMax = SearchHelper.Instance.GetSearchMinMaxLength(); + + //Note: the order of filtering is important for both operation and performane, so we try to make it work faster + // Also, note that filters are applied from the innermost outwards. + return + new PorterStemFilter( // stemming filter + new ASCIIFoldingFilter( // accents filter + new SynonymFilter( + new StopFilter(true, + new LowerCaseFilter( + new LengthFilter( + new StandardFilter( + new StandardTokenizer(Constants.LuceneVersion, reader) + ) + , wordLengthMinMax.Item1, wordLengthMinMax.Item2) + ) + , stops) + ) + ) + ) + ; + } + + private static ISet GetStopWords() + { + int portalId; + string cultureCode; + + var searchDoc = Thread.GetData(Thread.GetNamedDataSlot(Constants.TlsSearchInfo)) as SearchDocument; + if (searchDoc == null) + { + portalId = 0; // default + cultureCode = Thread.CurrentThread.CurrentCulture.Name; + } + else + { + portalId = searchDoc.PortalId; + cultureCode = searchDoc.CultureCode; + if (string.IsNullOrEmpty(cultureCode)) + { + var portalInfo = PortalController.GetPortal(portalId); + if (portalInfo != null) + cultureCode = portalInfo.DefaultLanguage; + } + } + + var stops = StopAnalyzer.ENGLISH_STOP_WORDS_SET; + var searchStopWords = SearchHelper.Instance.GetSearchStopWords(portalId, cultureCode); + + if (searchStopWords != null && !string.IsNullOrEmpty(searchStopWords.StopWords)) + { + //TODO Use cache from InternalSearchController + var strArray = searchStopWords.StopWords.Split(','); + var set = new CharArraySet(strArray.Length, false); + set.AddAll(strArray); + stops = CharArraySet.UnmodifiableSet(set); + } + + return stops; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/Internals/SynonymFilter.cs b/DNN Platform/Library/Services/Search/Internals/SynonymFilter.cs new file mode 100644 index 00000000000..22ca6f6adf1 --- /dev/null +++ b/DNN Platform/Library/Services/Search/Internals/SynonymFilter.cs @@ -0,0 +1,111 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Search.Entities; + +using Lucene.Net.Analysis; +using Lucene.Net.Analysis.Tokenattributes; + +#endregion + +namespace DotNetNuke.Services.Search.Internals +{ + /// + /// SynonymFilter + /// + /// Implementation is inspired by sample code in Manning Lucene In Action 2nd Edition, pg. 133 + internal sealed class SynonymFilter : TokenFilter + { + private readonly Stack _synonymStack = new Stack(); + private State _current; + private readonly TermAttribute _termAtt; + private readonly PositionIncrementAttribute _posIncrAtt; + private static readonly PortalController PortalController = new PortalController(); + + public SynonymFilter(TokenStream input) : base(input) + { + _termAtt = (TermAttribute) AddAttribute(); + _posIncrAtt = (PositionIncrementAttribute)AddAttribute(); + } + + public override bool IncrementToken() + { + //Pop buffered synonyms + if (_synonymStack.Count > 0) + { + var syn = _synonymStack.Pop(); + RestoreState(_current); + _termAtt.SetTermBuffer(syn); + + //set position increment to 0 + _posIncrAtt.PositionIncrement = 0; + return true; + } + + //read next token + if (!input.IncrementToken()) + return false; + + //push synonyms onto stack + if (AddAliasesToStack()) + { + _current = CaptureState(); //save current token + } + + return true; + } + + private bool AddAliasesToStack() + { + var portalId = 0; //default + string cultureCode; + var searchDoc = Thread.GetData(Thread.GetNamedDataSlot(Constants.TlsSearchInfo)) as SearchDocument; + if (searchDoc != null) + { + portalId = searchDoc.PortalId; + cultureCode = searchDoc.CultureCode; + if (string.IsNullOrEmpty(cultureCode)) + { + var portalInfo = PortalController.GetPortal(portalId); + if (portalInfo != null) + cultureCode = portalInfo.DefaultLanguage; + } + } + else + { + cultureCode = Thread.CurrentThread.CurrentCulture.Name; + } + var synonyms = SearchHelper.Instance.GetSynonyms(portalId, cultureCode, _termAtt.Term); + if (synonyms.Count() == 0) return false; + foreach (var synonym in synonyms) + { + _synonymStack.Push(synonym); + } + return true; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/ModuleIndexer.cs b/DNN Platform/Library/Services/Search/ModuleIndexer.cs new file mode 100644 index 00000000000..628e1be958d --- /dev/null +++ b/DNN Platform/Library/Services/Search/ModuleIndexer.cs @@ -0,0 +1,395 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.Index + /// Class: ModuleIndexer + /// ----------------------------------------------------------------------------- + /// + /// The ModuleIndexer is an implementation of the abstract IndexingProvider + /// class + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// [vnguyen] 04/16/2013 updated with methods for an Updated Search + /// + /// ----------------------------------------------------------------------------- + public class ModuleIndexer : IndexingProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModuleIndexer)); + private static readonly int ModuleSearchTypeId = SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId; + + /// ----------------------------------------------------------------------------- + /// + /// Returns the collection of SearchDocuments for the portal. + /// This replaces "GetSearchIndexItems" as a newer implementation of search. + /// + /// + /// + /// + /// + /// [vnguyen] 04/16/2013 created + /// + /// ----------------------------------------------------------------------------- + public override IEnumerable GetSearchDocuments(int portalId, DateTime startDate) + { + var searchDocuments = new List(); + var searchModuleCollection = GetSearchModules(portalId); + + foreach (var module in searchModuleCollection) + { + try + { + //Some modules update LastContentModifiedOnDate (e.g. Html module) when their content changes. + //We won't be calling into such modules if LastContentModifiedOnDate is prior to startDate + //LastContentModifiedOnDate remains minvalue for modules that don't update this property + if (module.LastContentModifiedOnDate != DateTime.MinValue && module.LastContentModifiedOnDate < startDate) + { + continue; + } + + var controller = Reflection.CreateObject(module.DesktopModule.BusinessControllerClass, module.DesktopModule.BusinessControllerClass); + var contentInfo = new SearchContentModuleInfo {ModSearchBaseControllerType= (ModuleSearchBase) controller, ModInfo = module}; + var searchItems = contentInfo.ModSearchBaseControllerType.GetModifiedSearchDocuments(module, startDate); + + if (searchItems != null) + { + //Add Module MetaData + foreach (var searchItem in searchItems) + { + searchItem.ModuleDefId = module.ModuleDefID; + searchItem.ModuleId = module.ModuleID; + if (string.IsNullOrEmpty(searchItem.CultureCode)) searchItem.CultureCode = module.CultureCode; + } + + Logger.Trace("ModuleIndexer: " + searchItems.Count + " search documents found for module [" + module.DesktopModule.ModuleName + " mid:" + module.ModuleID + "]"); + + searchDocuments.AddRange(searchItems); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + + return searchDocuments; + } + + /// ----------------------------------------------------------------------------- + /// + /// Returns a collection of SearchDocuments containing module metadata (title, header, footer...) of Searchable Modules. + /// + /// + /// + /// + /// + /// [vnguyen] 05/17/2013 created + /// + /// ----------------------------------------------------------------------------- + public List GetModuleMetaData(int portalId, DateTime startDate) + { + var searchDocuments = new List(); + var searchModuleCollection = GetSearchModules(portalId); + foreach (ModuleInfo module in searchModuleCollection) + { + try + { + if (module.LastModifiedOnDate > startDate && module.LastModifiedOnDate < DateTime.Now) + { + var searchDoc = new SearchDocument + { + SearchTypeId = ModuleSearchTypeId, + UniqueKey = Constants.ModuleMetaDataPrefixTag + module.ModuleID, + ModuleDefId = module.ModuleDefID, + ModuleId = module.ModuleID, + Title = module.ModuleTitle, + PortalId = portalId, + CultureCode = module.CultureCode, + ModifiedTimeUtc = module.LastModifiedOnDate, + Body = module.Header + " " + module.Footer + }; + + if (module.Terms != null && module.Terms.Count > 0) + { + searchDoc.Tags = module.Terms.Select(t => t.Name); + } + + Logger.Trace("ModuleIndexer: Search document for metaData found for module [" + module.DesktopModule.ModuleName + " mid:" + module.ModuleID + "]"); + + searchDocuments.Add(searchDoc); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + + return searchDocuments; + } + + /// ----------------------------------------------------------------------------- + /// + /// Converts a SearchItemInfo into a SearchDocument. + /// + /// SearchItemInfo object was used in the old version of search. + /// + /// + /// + /// + /// [vnguyen] 05/16/2013 created + /// + /// ----------------------------------------------------------------------------- + #pragma warning disable 0618 + public SearchDocument ConvertSearchItemInfoToSearchDocument(SearchItemInfo searchItem) + { + var moduleController = new ModuleController(); + var module = moduleController.GetModule(searchItem.ModuleId); + + var searchDoc = new SearchDocument + { + // Assigns as a Search key the SearchItems' GUID, if not it creates a dummy guid. + UniqueKey = (searchItem.SearchKey.Trim() != string.Empty) ? searchItem.SearchKey : Guid.NewGuid().ToString(), + QueryString = searchItem.GUID, + Title = searchItem.Title, + Body = searchItem.Content, + Description = searchItem.Description, + ModifiedTimeUtc = searchItem.PubDate, + AuthorUserId = searchItem.Author, + TabId = searchItem.TabId, + PortalId = module.PortalID, + SearchTypeId = ModuleSearchTypeId, + CultureCode = module.CultureCode, + //Add Module MetaData + ModuleDefId = module.ModuleDefID, + ModuleId = module.ModuleID + }; + + return searchDoc; + } + #pragma warning restore 0618 + + /// ----------------------------------------------------------------------------- + /// + /// Gets a list of modules that are listed as "Searchable" from the module definition and check if they + /// implement ModuleSearchBase -- which is a newer implementation of search that replaces ISearchable + /// + /// + /// + /// + /// [vnguyen] 04/16/2013 created + /// + /// ----------------------------------------------------------------------------- + protected IEnumerable GetSearchModules(int portalId) + { + var tabController = new TabController(); + var moduleController = new ModuleController(); + var businessControllers = new Hashtable(); + var searchModuleIds = new HashSet(); + var searchModules = new List(); + //Only get modules that are set to be Indexed. + var modules = moduleController.GetSearchModules(portalId).Cast().Where(m => m.TabModuleSettings["AllowIndex"] == null || bool.Parse(m.TabModuleSettings["AllowIndex"].ToString())); + + foreach (var module in modules.Where(module => !searchModuleIds.Contains(module.ModuleID))) + { + try + { + var tab = tabController.GetTab(module.TabID, portalId, false); + //Only index modules on tabs that are set to be Indexed. + if(tab.TabSettings["AllowIndex"] == null || (tab.TabSettings["AllowIndex"]!=null && bool.Parse(tab.TabSettings["AllowIndex"].ToString()))) + { + //Check if the business controller is in the Hashtable + var controller = businessControllers[module.DesktopModule.BusinessControllerClass]; + if (!String.IsNullOrEmpty(module.DesktopModule.BusinessControllerClass)) + { + //If nothing create a new instance + if (controller == null) + { + //Add to hashtable + controller = Reflection.CreateObject(module.DesktopModule.BusinessControllerClass, module.DesktopModule.BusinessControllerClass); + businessControllers.Add(module.DesktopModule.BusinessControllerClass, controller); + } + //Check if module inherits from ModuleSearchBase + if (controller is ModuleSearchBase) searchModules.Add(module); + } + } + } + catch (Exception ex) + { + Logger.Error(ex); + ThrowLogError(module, ex); + } + finally + { + searchModuleIds.Add(module.ModuleID); + } + } + return searchModules; + } + + /// ----------------------------------------------------------------------------- + /// + /// LEGACY: Depricated in DNN 7.1. Use 'GetSearchDocuments' instead. + /// Used for Legacy Search (ISearchable) + /// + /// GetSearchIndexItems gets the SearchInfo Items for the Portal + /// + /// + /// + /// The Id of the Portal + /// + /// [cnurse] 11/15/2004 documented + /// [vnguyen] 09/07/2010 Modified: Included logic to add TabId to searchItems + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchDocuments' instead.")] + public override SearchItemInfoCollection GetSearchIndexItems(int portalId) + { + var searchItems = new SearchItemInfoCollection(); + var searchCollection = GetModuleList(portalId); + foreach (SearchContentModuleInfo scModInfo in searchCollection) + { + try + { + var myCollection = scModInfo.ModControllerType.GetSearchItems(scModInfo.ModInfo); + if (myCollection != null) + { + foreach (SearchItemInfo searchItem in myCollection) + { + searchItem.TabId = scModInfo.ModInfo.TabID; + } + + Logger.Trace("ModuleIndexer: " + myCollection.Count + " search documents found for module [" + scModInfo.ModInfo.DesktopModule.ModuleName + " mid:" + scModInfo.ModInfo.ModuleID + "]"); + + searchItems.AddRange(myCollection); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + } + return searchItems; + } + + /// ----------------------------------------------------------------------------- + /// + /// LEGACY: Depricated in DNN 7.1. Use 'GetSearchModules' instead. + /// Used for Legacy Search (ISearchable) + /// + /// GetModuleList gets a collection of SearchContentModuleInfo Items for the Portal + /// + /// + /// Parses the Modules of the Portal, determining whetehr they are searchable. + /// + /// The Id of the Portal + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchModules' instead.")] + protected SearchContentModuleInfoCollection GetModuleList(int portalId) + { + var results = new SearchContentModuleInfoCollection(); + var objModules = new ModuleController(); + var arrModules = objModules.GetSearchModules(portalId); + var businessControllers = new Hashtable(); + var htModules = new Hashtable(); + + foreach (var module in arrModules.Cast().Where(module => !htModules.ContainsKey(module.ModuleID))) + { + try + { + //Check if the business controller is in the Hashtable + var controller = businessControllers[module.DesktopModule.BusinessControllerClass]; + if (!String.IsNullOrEmpty(module.DesktopModule.BusinessControllerClass)) + { + //If nothing create a new instance + if (controller == null) + { + //Add to hashtable + controller = Reflection.CreateObject(module.DesktopModule.BusinessControllerClass, module.DesktopModule.BusinessControllerClass); + businessControllers.Add(module.DesktopModule.BusinessControllerClass, controller); + } + //Double-Check that module supports ISearchable + + //Check if module inherits from ModuleSearchBase + if (controller is ISearchable && !(controller is ModuleSearchBase)) + { + var contentInfo = new SearchContentModuleInfo {ModControllerType = (ISearchable) controller, ModInfo = module}; + results.Add(contentInfo); + } + } + } + catch (Exception ex) + { + Logger.Error(ex); + ThrowLogError(module, ex); + } + finally + { + htModules.Add(module.ModuleID, module.ModuleID); + } + } + return results; + } + + private static void ThrowLogError(ModuleInfo module, Exception ex) + { + try + { + var message = string.Format("Error Creating BusinessControllerClass '{0}' of module({1}) id=({2}) in tab({3}) and portal({4}) ", + module.DesktopModule.BusinessControllerClass, + module.DesktopModule.ModuleName, + module.ModuleID, + module.TabID, + module.PortalID); + throw new Exception(message, ex); + } + catch (Exception ex1) + { + Exceptions.Exceptions.LogException(ex1); + } + } + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/SearchConfig.cs b/DNN Platform/Library/Services/Search/SearchConfig.cs new file mode 100644 index 00000000000..00fb1d55180 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchConfig.cs @@ -0,0 +1,200 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// + /// The SearchConfig class provides a configuration class for Search + /// + /// + /// [cnurse] 07/10/2007 Created + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + [Serializable] + public class SearchConfig + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SearchConfig)); + #region "Private Members" + + private readonly bool _SearchIncludeCommon; + private readonly bool _SearchIncludeNumeric; + private readonly int _SearchMaxWordlLength; + private readonly int _SearchMinWordlLength; + + #endregion + + #region "Constructor(s)" + + public SearchConfig(int portalID) : this(PortalController.GetPortalSettingsDictionary(portalID)) + { + } + + public SearchConfig(Dictionary settings) + { + _SearchIncludeCommon = GetSettingAsBoolean("SearchIncludeCommon", settings, Host.SearchIncludeCommon); + _SearchIncludeNumeric = GetSettingAsBoolean("SearchIncludeNumeric", settings, Host.SearchIncludeNumeric); + _SearchMaxWordlLength = GetSettingAsInteger("MaxSearchWordLength", settings, Host.SearchMaxWordlLength); + _SearchMinWordlLength = GetSettingAsInteger("MinSearchWordLength", settings, Host.SearchMinWordlLength); + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Common Words in the Search Index + /// + /// Defaults to False + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool SearchIncludeCommon + { + get + { + return _SearchIncludeCommon; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether to inlcude Numbers in the Search Index + /// + /// Defaults to False + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public bool SearchIncludeNumeric + { + get + { + return _SearchIncludeNumeric; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the maximum Search Word length to index + /// + /// Defaults to 25 + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int SearchMaxWordlLength + { + get + { + return _SearchMaxWordlLength; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the maximum Search Word length to index + /// + /// Defaults to 3 + /// + /// [cnurse] 03/10/2008 Created + /// + /// ----------------------------------------------------------------------------- + public int SearchMinWordlLength + { + get + { + return _SearchMinWordlLength; + } + } + + #endregion + + #region "Private Methods" + + + private bool GetSettingAsBoolean(string key, Dictionary settings, bool defaultValue) + { + bool retValue = Null.NullBoolean; + try + { + string setting = Null.NullString; + settings.TryGetValue(key, out setting); + if (string.IsNullOrEmpty(setting)) + { + retValue = defaultValue; + } + else + { + retValue = (setting.ToUpperInvariant().StartsWith("Y") || setting.ToUpperInvariant() == "TRUE"); + } + } + catch (Exception exc) + { + //we just want to trap the error as we may not be installed so there will be no Settings + Logger.Error(exc); + + } + return retValue; + } + + private int GetSettingAsInteger(string key, Dictionary settings, int defaultValue) + { + int retValue = Null.NullInteger; + try + { + string setting = Null.NullString; + settings.TryGetValue(key, out setting); + if (string.IsNullOrEmpty(setting)) + { + retValue = defaultValue; + } + else + { + retValue = Convert.ToInt32(setting); + } + } + catch (Exception exc) + { + //we just want to trap the error as we may not be installed so there will be no Settings + Logger.Error(exc); + + } + return retValue; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/SearchContentModuleInfo.cs b/DNN Platform/Library/Services/Search/SearchContentModuleInfo.cs new file mode 100644 index 00000000000..82bc49a9d69 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchContentModuleInfo.cs @@ -0,0 +1,92 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.Index + /// Class: SearchContentModuleInfo + /// ----------------------------------------------------------------------------- + /// + /// The SearchContentModuleInfo class represents an extendension (by containment) + /// of ModuleInfo to add a parametere that determines whether a module is Searchable + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + public class SearchContentModuleInfo + { +#pragma warning disable 0618 + protected ISearchable MModControllerType; +#pragma warning restore 0618 + protected ModuleSearchBase SearchBaseControllerType; + protected ModuleInfo MModInfo; + +#pragma warning disable 0618 + public ISearchable ModControllerType + { + get + { + return MModControllerType; + } + set + { + MModControllerType = value; + } + } +#pragma warning restore 0618 + + public ModuleSearchBase ModSearchBaseControllerType + { + get + { + return SearchBaseControllerType; + } + set + { + SearchBaseControllerType = value; + } + } + + public ModuleInfo ModInfo + { + get + { + return MModInfo; + } + set + { + MModInfo = value; + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchContentModuleInfoCollection.cs b/DNN Platform/Library/Services/Search/SearchContentModuleInfoCollection.cs new file mode 100644 index 00000000000..026d89f9829 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchContentModuleInfoCollection.cs @@ -0,0 +1,196 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.Index + /// Class: SearchContentModuleInfoCollection + /// ----------------------------------------------------------------------------- + /// + /// Represents a collection of SearchContentModuleInfo objects. + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + #pragma warning disable 0618 + public class SearchContentModuleInfoCollection : CollectionBase + { + #region "Constructors" + + /// + /// Initializes a new instance of the SearchContentModuleInfoCollection class. + /// + public SearchContentModuleInfoCollection() + { + } + + /// + /// Initializes a new instance of the SearchContentModuleInfoCollection class containing the elements of the specified source collection. + /// + /// A SearchContentModuleInfoCollection with which to initialize the collection. + public SearchContentModuleInfoCollection(SearchContentModuleInfoCollection value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchContentModuleInfoCollection class containing the specified array of SearchContentModuleInfo objects. + /// + /// An array of SearchContentModuleInfo objects with which to initialize the collection. + public SearchContentModuleInfoCollection(SearchContentModuleInfo[] value) + { + AddRange(value); + } + + #endregion + + #region "Properties" + + /// + /// Gets the SearchContentModuleInfoCollection at the specified index in the collection. + /// + /// In VB.Net, this property is the indexer for the SearchContentModuleInfoCollection class. + /// + /// + public SearchContentModuleInfo this[int index] + { + get + { + return (SearchContentModuleInfo) List[index]; + } + set + { + List[index] = value; + } + } + + #endregion + + #region "Public Methods" + + /// + /// Add an element of the specified SearchContentModuleInfo to the end of the collection. + /// + /// An object of type SearchContentModuleInfo to add to the collection. + public int Add(SearchContentModuleInfo value) + { + return List.Add(value); + } + + /// + /// Gets the index in the collection of the specified SearchContentModuleInfoCollection, if it exists in the collection. + /// + /// The SearchContentModuleInfoCollection to locate in the collection. + /// The index in the collection of the specified object, if found; otherwise, -1. + public int IndexOf(SearchContentModuleInfo value) + { + return List.IndexOf(value); + } + + /// + /// Add an element of the specified SearchContentModuleInfo to the collection at the designated index. + /// + /// An Integer to indicate the location to add the object to the collection. + /// An object of type SearchContentModuleInfo to add to the collection. + public void Insert(int index, SearchContentModuleInfo value) + { + List.Insert(index, value); + } + + /// + /// Remove the specified object of type SearchContentModuleInfo from the collection. + /// + /// An object of type SearchContentModuleInfo to remove to the collection. + public void Remove(SearchContentModuleInfo value) + { + List.Remove(value); + } + + /// + /// Gets a value indicating whether the collection contains the specified SearchContentModuleInfoCollection. + /// + /// The SearchContentModuleInfoCollection to search for in the collection. + /// true if the collection contains the specified object; otherwise, false. + public bool Contains(SearchContentModuleInfo value) + { + //If value is not of type SearchContentModuleInfo, this will return false. + return List.Contains(value); + } + + /// + /// Copies the elements of the specified SearchContentModuleInfo array to the end of the collection. + /// + /// An array of type SearchContentModuleInfo containing the objects to add to the collection. + public void AddRange(SearchContentModuleInfo[] value) + { + for (int i = 0; i <= value.Length - 1; i++) + { + Add(value[i]); + } + } + + /// + /// Adds the contents of another SearchContentModuleInfoCollection to the end of the collection. + /// + /// A SearchContentModuleInfoCollection containing the objects to add to the collection. + public void AddRange(SearchContentModuleInfoCollection value) + { + for (int i = 0; i <= value.Count - 1; i++) + { + Add((SearchContentModuleInfo) value.List[i]); + } + } + + /// + /// Copies the collection objects to a one-dimensional Array instance beginning at the specified index. + /// + /// The one-dimensional Array that is the destination of the values copied from the collection. + /// The index of the array at which to begin inserting. + public void CopyTo(SearchContentModuleInfo[] array, int index) + { + List.CopyTo(array, index); + } + + /// + /// Creates a one-dimensional Array instance containing the collection items. + /// + /// Array of type SearchContentModuleInfo + public SearchContentModuleInfo[] ToArray() + { + var arr = new SearchContentModuleInfo[Count]; + CopyTo(arr, 0); + return arr; + } + + #endregion + } + #pragma warning restore 0618 +} diff --git a/DNN Platform/Library/Services/Search/SearchCriteria.cs b/DNN Platform/Library/Services/Search/SearchCriteria.cs new file mode 100644 index 00000000000..2e30d600a0a --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchCriteria.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.DataStore + /// Class: SearchCriteria + /// ----------------------------------------------------------------------------- + /// + /// The SearchCriteria represents a search criterion + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + public class SearchCriteria + { + public string Criteria { get; set; } + + public bool MustExclude { get; set; } + + public bool MustInclude { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchCriteriaCollection.cs b/DNN Platform/Library/Services/Search/SearchCriteriaCollection.cs new file mode 100644 index 00000000000..d6397d6595e --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchCriteriaCollection.cs @@ -0,0 +1,242 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.DataStore + /// Class: SearchCriteria + /// ----------------------------------------------------------------------------- + /// + /// Represents a collection of SearchCriteria objects. + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + public class SearchCriteriaCollection : CollectionBase + { + #region Constructors + + /// + /// Initializes a new instance of the SearchCriteriaCollection class. + /// + + public SearchCriteriaCollection() + { + } + + /// + /// Initializes a new instance of the SearchCriteriaCollection class containing the elements of the specified source collection. + /// + /// A SearchCriteriaCollection with which to initialize the collection. + public SearchCriteriaCollection(SearchCriteriaCollection value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchCriteriaCollection class containing the specified array of SearchCriteria objects. + /// + /// An array of SearchCriteria objects with which to initialize the collection. + public SearchCriteriaCollection(SearchCriteria[] value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchCriteriaCollection class containing the elements of the specified source collection. + /// + /// A criteria string with which to initialize the collection + public SearchCriteriaCollection(string value) + { + //split search criteria into words + string[] words = value.Split(' '); + //Add all criteria without modifiers + foreach (string word in words) + { + var criterion = new SearchCriteria(); + if ((!word.StartsWith("+")) && (!word.StartsWith("-"))) + { + criterion.MustInclude = false; + criterion.MustExclude = false; + criterion.Criteria = word; + Add(criterion); + } + } + //Add all mandatory criteria + foreach (string word in words) + { + var criterion = new SearchCriteria(); + if (word.StartsWith("+")) + { + criterion.MustInclude = true; + criterion.MustExclude = false; + criterion.Criteria = word.Remove(0, 1); + Add(criterion); + } + } + //Add all excluded criteria + foreach (string word in words) + { + var criterion = new SearchCriteria(); + if (word.StartsWith("-")) + { + criterion.MustInclude = false; + criterion.MustExclude = true; + criterion.Criteria = word.Remove(0, 1); + Add(criterion); + } + } + } + + #endregion + + #region Properties + + /// + /// Gets the SearchCriteriaCollection at the specified index in the collection. + /// + /// In VB.Net, this property is the indexer for the SearchCriteriaCollection class. + /// + /// + public SearchCriteria this[int index] + { + get + { + return (SearchCriteria) List[index]; + } + set + { + List[index] = value; + } + } + + #endregion + + #region Public Methods + + /// + /// Add an element of the specified SearchCriteria to the end of the collection. + /// + /// An object of type SearchCriteria to add to the collection. + public int Add(SearchCriteria value) + { + return List.Add(value); + } + + /// + /// Gets the index in the collection of the specified SearchCriteriaCollection, if it exists in the collection. + /// + /// The SearchCriteriaCollection to locate in the collection. + /// The index in the collection of the specified object, if found; otherwise, -1. + public int IndexOf(SearchCriteria value) + { + return List.IndexOf(value); + } + + /// + /// Add an element of the specified SearchCriteria to the collection at the designated index. + /// + /// An Integer to indicate the location to add the object to the collection. + /// An object of type SearchCriteria to add to the collection. + public void Insert(int index, SearchCriteria value) + { + List.Insert(index, value); + } + + /// + /// Remove the specified object of type SearchCriteria from the collection. + /// + /// An object of type SearchCriteria to remove to the collection. + public void Remove(SearchCriteria value) + { + List.Remove(value); + } + + /// + /// Gets a value indicating whether the collection contains the specified SearchCriteriaCollection. + /// + /// The SearchCriteriaCollection to search for in the collection. + /// true if the collection contains the specified object; otherwise, false. + public bool Contains(SearchCriteria value) + { + return List.Contains(value); + } + + /// + /// Copies the elements of the specified SearchCriteria array to the end of the collection. + /// + /// An array of type SearchCriteria containing the objects to add to the collection. + public void AddRange(SearchCriteria[] value) + { + for (int i = 0; i <= value.Length - 1; i++) + { + Add(value[i]); + } + } + + /// + /// Adds the contents of another SearchCriteriaCollection to the end of the collection. + /// + /// A SearchCriteriaCollection containing the objects to add to the collection. + public void AddRange(SearchCriteriaCollection value) + { + for (int i = 0; i <= value.Count - 1; i++) + { + Add((SearchCriteria) value.List[i]); + } + } + + /// + /// Copies the collection objects to a one-dimensional Array instance beginning at the specified index. + /// + /// The one-dimensional Array that is the destination of the values copied from the collection. + /// The index of the array at which to begin inserting. + public void CopyTo(SearchCriteria[] array, int index) + { + List.CopyTo(array, index); + } + + /// + /// Creates a one-dimensional Array instance containing the collection items. + /// + /// Array of type SearchCriteria + public SearchCriteria[] ToArray() + { + var arr = new SearchCriteria[Count]; + CopyTo(arr, 0); + return arr; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/SearchDataStore.cs b/DNN Platform/Library/Services/Search/SearchDataStore.cs new file mode 100644 index 00000000000..aae3e5eeff1 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchDataStore.cs @@ -0,0 +1,327 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.DataStore + /// Class: SearchDataStore + /// ----------------------------------------------------------------------------- + /// + /// The SearchDataStore is an implementation of the abstract SearchDataStoreProvider + /// class + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + public class SearchDataStore : SearchDataStoreProvider + { + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// GetCommonWords gets a list of the Common Words for the locale + /// + /// + /// + /// The locale string + /// A hashtable of common words + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + private Hashtable GetCommonWords(string locale) + { + string strCacheKey = "CommonWords" + locale; + var objWords = (Hashtable) DataCache.GetCache(strCacheKey); + if (objWords == null) + { + objWords = new Hashtable(); + IDataReader drWords = DataProvider.Instance().GetSearchCommonWordsByLocale(locale); + try + { + while (drWords.Read()) + { + objWords.Add(drWords["CommonWord"].ToString(), drWords["CommonWord"].ToString()); + } + } + finally + { + drWords.Close(); + drWords.Dispose(); + } + DataCache.SetCache(strCacheKey, objWords); + } + return objWords; + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// GetSearchItems gets a collection of Search Items for a Module/Tab/Portal + /// + /// + /// + /// A Id of the Portal + /// A Id of the Tab + /// A Id of the Module + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + public override SearchResultsInfoCollection GetSearchItems(int portalId, int tabId, int moduleId) + { + return SearchDataStoreController.GetSearchResults(portalId, tabId, moduleId); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSearchResults gets the search results for a passed in criteria string + /// + /// + /// + /// A Id of the Portal + /// The criteria string + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + public override SearchResultsInfoCollection GetSearchResults(int portalId, string criteria) + { + bool hasExcluded = Null.NullBoolean; + bool hasMandatory = Null.NullBoolean; + + var objPortalController = new PortalController(); + PortalInfo objPortal = objPortalController.GetPortal(portalId); + + //Get the Settings for this Portal + var portalSettings = new PortalSettings(objPortal); + + //We will assume that the content is in the locale of the Portal + Hashtable commonWords = GetCommonWords(portalSettings.DefaultLanguage); + + //clean criteria + criteria = criteria.ToLower(); + + //split search criteria into words + var searchWords = new SearchCriteriaCollection(criteria); + + var searchResults = new Dictionary(); + + //dicResults is a Dictionary(Of SearchItemID, Dictionary(Of TabID, SearchResultsInfo) + var dicResults = new Dictionary>(); + + //iterate through search criteria words + foreach (SearchCriteria criterion in searchWords) + { + if (commonWords.ContainsKey(criterion.Criteria) == false || portalSettings.SearchIncludeCommon) + { + if (!searchResults.ContainsKey(criterion.Criteria)) + { + searchResults.Add(criterion.Criteria, SearchDataStoreController.GetSearchResults(portalId, criterion.Criteria)); + } + if (searchResults.ContainsKey(criterion.Criteria)) + { + foreach (SearchResultsInfo result in searchResults[criterion.Criteria]) + { + //Add results to dicResults + if (!criterion.MustExclude) + { + if (dicResults.ContainsKey(result.SearchItemID)) + { + //The Dictionary exists for this SearchItemID already so look in the TabId keyed Sub-Dictionary + Dictionary dic = dicResults[result.SearchItemID]; + if (dic.ContainsKey(result.TabId)) + { + //The sub-Dictionary contains the item already so update the relevance + SearchResultsInfo searchResult = dic[result.TabId]; + searchResult.Relevance += result.Relevance; + } + else + { + //Add Entry to Sub-Dictionary + dic.Add(result.TabId, result); + } + } + else + { + //Create new TabId keyed Dictionary + var dic = new Dictionary(); + dic.Add(result.TabId, result); + + //Add new Dictionary to SearchResults + dicResults.Add(result.SearchItemID, dic); + } + } + } + } + } + } + foreach (SearchCriteria criterion in searchWords) + { + var mandatoryResults = new Dictionary(); + var excludedResults = new Dictionary(); + if (searchResults.ContainsKey(criterion.Criteria)) + { + foreach (SearchResultsInfo result in searchResults[criterion.Criteria]) + { + if (criterion.MustInclude) + { + //Add to mandatory results lookup + mandatoryResults[result.SearchItemID] = true; + hasMandatory = true; + } + else if (criterion.MustExclude) + { + //Add to exclude results lookup + excludedResults[result.SearchItemID] = true; + hasExcluded = true; + } + } + } + foreach (KeyValuePair> kvpResults in dicResults) + { + //The key of this collection is the SearchItemID, Check if the value of this collection should be processed + if (hasMandatory && (!mandatoryResults.ContainsKey(kvpResults.Key))) + { + //1. If mandatoryResults exist then only process if in mandatoryResults Collection + foreach (SearchResultsInfo result in kvpResults.Value.Values) + { + result.Delete = true; + } + } + else if (hasExcluded && (excludedResults.ContainsKey(kvpResults.Key))) + { + //2. Do not process results in the excludedResults Collection + foreach (SearchResultsInfo result in kvpResults.Value.Values) + { + result.Delete = true; + } + } + } + } + + //Process results against permissions and mandatory and excluded results + var results = new SearchResultsInfoCollection(); + var objTabController = new TabController(); + foreach (KeyValuePair> kvpResults in dicResults) + { + foreach (SearchResultsInfo result in kvpResults.Value.Values) + { + if (!result.Delete) + { + //Check If authorised to View Tab + TabInfo objTab = objTabController.GetTab(result.TabId, portalId, false); + if (TabPermissionController.CanViewPage(objTab)) + { + //Check If authorised to View Module + ModuleInfo objModule = new ModuleController().GetModule(result.ModuleId, result.TabId, false); + if (ModulePermissionController.CanViewModule(objModule)) + { + results.Add(result); + } + } + } + } + } + + //Return Search Results Collection + return results; + } + + /// ----------------------------------------------------------------------------- + /// + /// StoreSearchItems adds the Search Item to the Data Store + /// + /// + /// + /// A Collection of SearchItems + /// + /// [cnurse] 11/15/2004 documented + /// [vnguyen] 09/07/2010 Modified: Added a date comparison for LastModifiedDate on the Tab + /// [vnguyen] 16/04/2013 Modified: Now uses Lucene indexing + /// [galatrash] 23/05/2013 Modified: moved indexing methods into the internal namespace. + /// + /// ----------------------------------------------------------------------------- + public override void StoreSearchItems(SearchItemInfoCollection searchItems) + { + var moduleController = new ModuleController(); + var indexer = new ModuleIndexer(); + + var modulesDic = new Dictionary(); + foreach (SearchItemInfo item in searchItems) + { + if (!modulesDic.ContainsKey(item.ModuleId)) + { + var module = moduleController.GetModule(item.ModuleId); + modulesDic.Add(item.ModuleId, module.CultureCode); + + //Remove all indexed items for this module + InternalSearchController.Instance.DeleteSearchDocumentsByModule(module.PortalID, module.ModuleID, module.ModuleDefID); + } + } + + //Process the SearchItems by Module to reduce Database hits + foreach (var kvp in modulesDic) + { + //Get the Module's SearchItems + var moduleSearchItems = searchItems.ModuleItems(kvp.Key); + + //Convert SearchItemInfo objects to SearchDocument objects + var searchDocuments = (from SearchItemInfo item in moduleSearchItems select indexer.ConvertSearchItemInfoToSearchDocument(item)).ToList(); + + //Index + InternalSearchController.Instance.AddSearchDocuments(searchDocuments); + } + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Search/SearchDataStoreController.cs b/DNN Platform/Library/Services/Search/SearchDataStoreController.cs new file mode 100644 index 00000000000..669d4a2d4f0 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchDataStoreController.cs @@ -0,0 +1,159 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.DataStore + /// Class: SearchDataStoreController + /// ----------------------------------------------------------------------------- + /// + /// The SearchDataStoreController is the Business Controller class for SearchDataStore + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + public class SearchDataStoreController + { + public static int AddSearchItem(SearchItemInfo item) + { + return DataProvider.Instance().AddSearchItem(item.Title, item.Description, item.Author, item.PubDate, item.ModuleId, item.SearchKey, item.GUID, item.ImageFileId); + } + + public static void DeleteSearchItem(int SearchItemId) + { + DataProvider.Instance().DeleteSearchItem(SearchItemId); + } + + public static void DeleteSearchItemWords(int SearchItemId) + { + DataProvider.Instance().DeleteSearchItemWords(SearchItemId); + } + + public static SearchItemInfo GetSearchItem(int ModuleId, string SearchKey) + { + return (SearchItemInfo) CBO.FillObject(DataProvider.Instance().GetSearchItem(ModuleId, SearchKey), typeof (SearchItemInfo)); + } + + public static Dictionary GetSearchItems(int ModuleId) + { + return CBO.FillDictionary("SearchKey", DataProvider.Instance().GetSearchItems(Null.NullInteger, Null.NullInteger, ModuleId)); + } + + public static ArrayList GetSearchItems(int PortalId, int TabId, int ModuleId) + { + return CBO.FillCollection(DataProvider.Instance().GetSearchItems(PortalId, TabId, ModuleId), typeof (SearchItemInfo)); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSearchResults gets the search results for a single word + /// + /// + /// + /// A Id of the Portal + /// The word + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + public static SearchResultsInfoCollection GetSearchResults(int PortalID, string Word) + { + return new SearchResultsInfoCollection(CBO.FillCollection(DataProvider.Instance().GetSearchResults(PortalID, Word), typeof (SearchResultsInfo))); + } + + public static SearchResultsInfoCollection GetSearchResults(int PortalId, int TabId, int ModuleId) + { + return new SearchResultsInfoCollection(CBO.FillCollection(DataProvider.Instance().GetSearchResults(PortalId, TabId, ModuleId), typeof (SearchResultsInfo))); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSearchSettings gets the search settings for a single module + /// + /// + /// + /// The Id of the Module + /// + /// [cnurse] 11/15/2004 created + /// + /// ----------------------------------------------------------------------------- + public static Dictionary GetSearchSettings(int ModuleId) + { + var dicSearchSettings = new Dictionary(); + IDataReader dr = null; + try + { + dr = DataProvider.Instance().GetSearchSettings(ModuleId); + while (dr.Read()) + { + if (!dr.IsDBNull(1)) + { + dicSearchSettings[dr.GetString(0)] = dr.GetString(1); + } + else + { + dicSearchSettings[dr.GetString(0)] = ""; + } + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return dicSearchSettings; + } + + public static void UpdateSearchItem(SearchItemInfo item) + { + DataProvider.Instance().UpdateSearchItem(item.SearchItemId, + item.Title, + item.Description, + item.Author, + item.PubDate, + item.ModuleId, + item.SearchKey, + item.GUID, + item.HitCount, + item.ImageFileId); + } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchDataStoreProvider.cs b/DNN Platform/Library/Services/Search/SearchDataStoreProvider.cs new file mode 100644 index 00000000000..d70aaf443a7 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchDataStoreProvider.cs @@ -0,0 +1,58 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search +{ + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + public abstract class SearchDataStoreProvider + { + #region "Shared/Static Methods" + + //return the provider + public static SearchDataStoreProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region "Abstract Methods" + + public abstract void StoreSearchItems(SearchItemInfoCollection searchItems); + + public abstract SearchResultsInfoCollection GetSearchResults(int portalId, string criteria); + + public abstract SearchResultsInfoCollection GetSearchItems(int portalId, int tabId, int moduleId); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Search/SearchEngine.cs b/DNN Platform/Library/Services/Search/SearchEngine.cs new file mode 100644 index 00000000000..4eef1e338eb --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchEngine.cs @@ -0,0 +1,349 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using System.Linq; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; +using DotNetNuke.Services.Scheduling; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchEngine + /// ----------------------------------------------------------------------------- + /// + /// The SearchEngine manages the Indexing of the Portal content + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// [vnguyen] 04/16/2013 updated with methods for an Updated Search + /// + /// ----------------------------------------------------------------------------- + public class SearchEngine + { + #region Properties + + public int IndexedSearchDocumentCount { get; private set; } + + public Dictionary Results { get; private set; } + + #endregion + + #region internal + /// ----------------------------------------------------------------------------- + /// + /// Indexes content within the given time farame + /// + /// + /// + /// [vnguyen] 04/17/2013 created + /// + /// ----------------------------------------------------------------------------- + internal void IndexContent(DateTime startDate) + { + var tabIndexer = new TabIndexer(); + var moduleIndexer = new ModuleIndexer(); + IndexedSearchDocumentCount = 0; + Results = new Dictionary(); + + //Index TAB META-DATA + var searchDocs = GetSearchDocuments(tabIndexer, startDate); + var searchDocuments = searchDocs as IList ?? searchDocs.ToList(); + StoreSearchDocuments(searchDocuments); + IndexedSearchDocumentCount += searchDocuments.Count(); + Results.Add("Tabs", searchDocuments.Count()); + + //Index MODULE META-DATA from modules that inherit from SearchModuleBase + searchDocs = GetModuleMetaData(startDate); + searchDocuments = searchDocs as IList ?? searchDocs.ToList(); + StoreSearchDocuments(searchDocuments); + IndexedSearchDocumentCount += searchDocuments.Count(); + Results.Add("Modules (Metadata)", searchDocuments.Count()); + + //Index MODULE CONTENT from modules that inherit from SearchModuleBase + searchDocs = GetSearchDocuments(moduleIndexer, startDate); + searchDocuments = searchDocs as IList ?? searchDocs.ToList(); + StoreSearchDocuments(searchDocuments); + IndexedSearchDocumentCount += searchDocuments.Count(); + + #pragma warning disable 0618 + //Index all Defunct ISearchable module content + var searchItems = GetContent(moduleIndexer); + SearchDataStoreProvider.Instance().StoreSearchItems(searchItems); + #pragma warning restore 0618 + IndexedSearchDocumentCount += searchItems.Count; + + //Both SearchModuleBase and ISearchable module content count + Results.Add("Modules (Content)", searchDocuments.Count() + searchItems.Count); + } + + internal bool CompactSearchIndexIfNeeded(ScheduleHistoryItem scheduleItem) + { + var shelper = SearchHelper.Instance; + if (shelper.GetSearchCompactFlag()) + { + shelper.SetSearchReindexRequestTime(false); + var stopWatch = System.Diagnostics.Stopwatch.StartNew(); + if (InternalSearchController.Instance.OptimizeSearchIndex()) + { + stopWatch.Stop(); + scheduleItem.AddLogNote(string.Format("
    Compacted Index, total time {0}", stopWatch.Elapsed)); + } + } + return false; + } + + /// + /// Deletes all old documents when re-index was requested, so we start a fresh search + /// + /// + internal void DeleteOldDocsBeforeReindex(DateTime startDate) + { + var portal2Reindex = SearchHelper.Instance.GetPortalsToReindex(startDate); + var controller = InternalSearchController.Instance; + + foreach (var portalId in portal2Reindex) + { + controller.DeleteAllDocuments(portalId, SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId); + controller.DeleteAllDocuments(portalId, SearchHelper.Instance.GetSearchTypeByName("tab").SearchTypeId); + } + } + + #endregion + + #region Private + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the Search Documents for the given timeframe. + /// + /// + /// + /// + /// + /// [vnguyen] 04/17/2013 created + /// + /// ----------------------------------------------------------------------------- + private IEnumerable GetSearchDocuments(IndexingProvider indexer, DateTime startDate) + { + var searchDocs = new List(); + var portalController = new PortalController(); + var portals = portalController.GetPortals(); + DateTime indexSince; + + foreach (var portal in portals.Cast()) + { + indexSince = FixedIndexingStartDate(portal.PortalID, startDate); + searchDocs.AddRange(indexer.GetSearchDocuments(portal.PortalID, indexSince)); + } + + // Include Host Level Items + indexSince = FixedIndexingStartDate(-1, startDate); + searchDocs.AddRange(indexer.GetSearchDocuments(-1, indexSince)); + + return searchDocs; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the Search Documents within the timeframe for the given portal + /// + /// + /// + /// + /// + /// + /// [vnguyen] 04/17/2013 created + /// + /// ----------------------------------------------------------------------------- + private IEnumerable GetSearchDocuments(int portalId, IndexingProvider indexer, DateTime startDate) + { + var searchDocs = new List(); + var indexSince = FixedIndexingStartDate(portalId, startDate); + searchDocs.AddRange(indexer.GetSearchDocuments(portalId, indexSince)); + return searchDocs; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the Searchable Module MetaData SearchDocuments within the timeframe for all portals + /// + /// + /// + /// + /// [vnguyen] 04/17/2013 created + /// + /// ----------------------------------------------------------------------------- + private IEnumerable GetModuleMetaData(DateTime startDate) + { + var searchDocs = new List(); + var portalController = new PortalController(); + var portals = portalController.GetPortals(); + var indexer = new ModuleIndexer(); + DateTime indexSince; + + foreach (var portal in portals.Cast()) + { + indexSince = FixedIndexingStartDate(portal.PortalID, startDate); + searchDocs.AddRange(indexer.GetModuleMetaData(portal.PortalID, indexSince)); + } + + // Include Host Level Items + indexSince = FixedIndexingStartDate(-1, startDate); + searchDocs.AddRange(indexer.GetSearchDocuments(-1, indexSince)); + + return searchDocs; + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets all the Searchable Module MetaData SearchDocuments within the timeframe for the given portal + /// + /// + /// + /// + /// + /// [vnguyen] 04/17/2013 created + /// + /// ----------------------------------------------------------------------------- + private static IEnumerable GetModuleMetaData(int portalId, DateTime startDate) + { + var searchDocs = new List(); + var indexer = new ModuleIndexer(); + var indexSince = FixedIndexingStartDate(portalId, startDate); + + searchDocs.AddRange(indexer.GetModuleMetaData(portalId, indexSince)); + + return searchDocs; + } + + /// ----------------------------------------------------------------------------- + /// + /// Ensures all SearchDocuments have a SearchTypeId + /// + /// + /// ----------------------------------------------------------------------------- + private static void StoreSearchDocuments(IEnumerable searchDocs) + { + var defaultSearchTypeId = SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId; + + var searchDocumentList = searchDocs as IList ?? searchDocs.ToList(); + foreach (var searchDocument in searchDocumentList.Where(searchDocument => searchDocument.SearchTypeId <= 0)) + { + searchDocument.SearchTypeId = defaultSearchTypeId; + } + + InternalSearchController.Instance.AddSearchDocuments(searchDocumentList); + } + + /// ----------------------------------------------------------------------------- + /// + /// Adjusts the re-index date/time to account for the portal reindex value + /// + /// + /// + /// + /// + /// [galatrash] 06/04/2013 created + /// + /// ----------------------------------------------------------------------------- + private static DateTime FixedIndexingStartDate(int portalId, DateTime startDate) + { + if (startDate != SqlDateTime.MinValue.Value && + SearchHelper.Instance.IsReindexRequested(portalId, startDate)) + { + return SqlDateTime.MinValue.Value; + } + return startDate; + } + + #endregion + + #region Obsolete Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// LEGACY: Depricated in DNN 7.1. Use 'GetSearchDocuments' instead. + /// Used for Legacy Search (ISearchable) + /// + /// GetContent gets all the content and passes it to the Indexer + /// + /// + /// + /// The Index Provider that will index the content of the portal + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchDocuments' instead.")] + protected SearchItemInfoCollection GetContent(IndexingProvider indexer) + { + var searchItems = new SearchItemInfoCollection(); + var objPortals = new PortalController(); + var arrPortals = objPortals.GetPortals(); + int intPortal; + for (intPortal = 0; intPortal <= arrPortals.Count - 1; intPortal++) + { + var objPortal = (PortalInfo) arrPortals[intPortal]; + searchItems.AddRange(indexer.GetSearchIndexItems(objPortal.PortalID)); + } + return searchItems; + } + + /// ----------------------------------------------------------------------------- + /// + /// LEGACY: Depricated in DNN 7.1. Use 'GetSearchDocuments' instead. + /// Used for Legacy Search (ISearchable) + /// + /// GetContent gets the Portal's content and passes it to the Indexer + /// + /// + /// + /// The Id of the Portal + /// The Index Provider that will index the content of the portal + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchDocuments' instead.")] + protected SearchItemInfoCollection GetContent(int portalId, IndexingProvider indexer) + { + var searchItems = new SearchItemInfoCollection(); + searchItems.AddRange(indexer.GetSearchIndexItems(portalId)); + return searchItems; + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Search/SearchEngineScheduler.cs b/DNN Platform/Library/Services/Search/SearchEngineScheduler.cs new file mode 100644 index 00000000000..4cd4ff2fae6 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchEngineScheduler.cs @@ -0,0 +1,104 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data.SqlTypes; +using System.Linq; + +using DotNetNuke.Common; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Scheduling; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchEngineScheduler + /// ----------------------------------------------------------------------------- + /// + /// The SearchEngineScheduler implements a SchedulerClient for the Indexing of + /// portal content. + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + public class SearchEngineScheduler : SchedulerClient + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(Globals)); + + public SearchEngineScheduler(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + /// ----------------------------------------------------------------------------- + /// + /// DoWork runs the scheduled item + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// [vqnguyen] 05/28/2013 updated + /// + /// ----------------------------------------------------------------------------- + public override void DoWork() + { + try + { + var searchEngine = new SearchEngine(); + var lastSuccessFulDateTime = SearchHelper.Instance.GetLastSuccessfulIndexingDateTime(ScheduleHistoryItem.ScheduleID); + Logger.Trace("Search: Site Crawler - Starting. Content change start time " + lastSuccessFulDateTime.ToString("g")); + ScheduleHistoryItem.AddLogNote(string.Format("Starting. Content change start time {0:g}", lastSuccessFulDateTime)); + + searchEngine.DeleteOldDocsBeforeReindex(lastSuccessFulDateTime); + searchEngine.IndexContent(lastSuccessFulDateTime); + foreach (var result in searchEngine.Results) + { + ScheduleHistoryItem.AddLogNote("
       " + result.Key + " Indexed: " + result.Value); + } + ScheduleHistoryItem.AddLogNote("
    Total Items Indexed: " + searchEngine.IndexedSearchDocumentCount + ""); + + searchEngine.CompactSearchIndexIfNeeded(ScheduleHistoryItem); + ScheduleHistoryItem.Succeeded = true; + ScheduleHistoryItem.AddLogNote("
    Indexing Successful"); + SearchHelper.Instance.SetLastSuccessfulIndexingDateTime(ScheduleHistoryItem.ScheduleID, ScheduleHistoryItem.StartDate); + + Logger.Trace("Search: Site Crawler - Indexing Successful"); + } + catch (Exception ex) + { + ScheduleHistoryItem.Succeeded = false; + ScheduleHistoryItem.AddLogNote("
    EXCEPTION: " + ex.Message); + Errored(ref ex); + Exceptions.Exceptions.LogException(ex); + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchItemInfo.cs b/DNN Platform/Library/Services/Search/SearchItemInfo.cs new file mode 100644 index 00000000000..cc748a24eb1 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchItemInfo.cs @@ -0,0 +1,256 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchItemInfo + /// ----------------------------------------------------------------------------- + /// + /// The SearchItemInfo represents a Search Item + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// [vnguyen] 09/07/2010 Modified: added TabId property + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + [Serializable] + public class SearchItemInfo + { + private int _Author; + private string _Content; + private string _Description; + private string _GUID; + private int _HitCount; + private int _ImageFileId; + private int _ModuleId; + private DateTime _PubDate; + private int _SearchItemId; + private string _SearchKey; + private int _TabId; + private string _Title; + + public SearchItemInfo() + { + } + + public SearchItemInfo(string Title, string Description, int Author, DateTime PubDate, int ModuleID, string SearchKey, string Content) + : this(Title, Description, Author, PubDate, ModuleID, SearchKey, Content, "", Null.NullInteger) + { + } + + public SearchItemInfo(string Title, string Description, int Author, DateTime PubDate, int ModuleID, string SearchKey, string Content, string Guid) + : this(Title, Description, Author, PubDate, ModuleID, SearchKey, Content, Guid, Null.NullInteger) + { + } + + public SearchItemInfo(string Title, string Description, int Author, DateTime PubDate, int ModuleID, string SearchKey, string Content, int Image) + : this(Title, Description, Author, PubDate, ModuleID, SearchKey, Content, "", Image) + { + } + + public SearchItemInfo(string Title, string Description, int Author, DateTime PubDate, int ModuleID, string SearchKey, string Content, string Guid, int Image) + { + _Title = Title; + _Description = Description; + _Author = Author; + _PubDate = PubDate; + _ModuleId = ModuleID; + _SearchKey = SearchKey; + _Content = Content; + _GUID = Guid; + _ImageFileId = Image; + _HitCount = 0; + } + + public SearchItemInfo(string Title, string Description, int Author, DateTime PubDate, int ModuleID, string SearchKey, string Content, string Guid, int Image, int TabID) + { + _Title = Title; + _Description = Description; + _Author = Author; + _PubDate = PubDate; + _ModuleId = ModuleID; + _SearchKey = SearchKey; + _Content = Content; + _GUID = Guid; + _ImageFileId = Image; + _HitCount = 0; + _TabId = TabID; + } + + + public int SearchItemId + { + get + { + return _SearchItemId; + } + set + { + _SearchItemId = value; + } + } + + public string Title + { + get + { + return _Title; + } + set + { + _Title = value; + } + } + + public string Description + { + get + { + return _Description; + } + set + { + _Description = value; + } + } + + public int Author + { + get + { + return _Author; + } + set + { + _Author = value; + } + } + + public DateTime PubDate + { + get + { + return _PubDate; + } + set + { + _PubDate = value; + } + } + + public int ModuleId + { + get + { + return _ModuleId; + } + set + { + _ModuleId = value; + } + } + + public string SearchKey + { + get + { + return _SearchKey; + } + set + { + _SearchKey = value; + } + } + + public string Content + { + get + { + return _Content; + } + set + { + _Content = value; + } + } + + public string GUID + { + get + { + return _GUID; + } + set + { + _GUID = value; + } + } + + public int ImageFileId + { + get + { + return _ImageFileId; + } + set + { + _ImageFileId = value; + } + } + + public int HitCount + { + get + { + return _HitCount; + } + set + { + _HitCount = value; + } + } + + public int TabId + { + get + { + return _TabId; + } + set + { + _TabId = value; + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchItemInfoCollection.cs b/DNN Platform/Library/Services/Search/SearchItemInfoCollection.cs new file mode 100644 index 00000000000..43f08941a8e --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchItemInfoCollection.cs @@ -0,0 +1,234 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchItemInfoCollection + /// ----------------------------------------------------------------------------- + /// + /// Represents a collection of SearchItemInfo objects. + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + [Serializable] + public class SearchItemInfoCollection : CollectionBase + { + #region "Constructors" + + /// + /// Initializes a new instance of the SearchItemInfoCollection class. + /// + public SearchItemInfoCollection() + { + } + + /// + /// Initializes a new instance of the SearchItemInfoCollection class containing the elements of the specified source collection. + /// + /// A SearchItemInfoCollection with which to initialize the collection. + public SearchItemInfoCollection(SearchItemInfoCollection value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchItemInfoCollection class containing the specified array of SearchItemInfo objects. + /// + /// An array of SearchItemInfo objects with which to initialize the collection. + public SearchItemInfoCollection(SearchItemInfo[] value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchItemInfoCollectionSearchItemInfoCollection class containing the specified array of SearchItemInfo objects. + /// + /// An arraylist of SearchItemInfo objects with which to initialize the collection. + public SearchItemInfoCollection(ArrayList value) + { + AddRange(value); + } + + #endregion + + #region "Properties" + + /// + /// Gets the SearchItemInfoCollection at the specified index in the collection. + /// + /// In VB.Net, this property is the indexer for the SearchItemInfoCollection class. + /// + /// + public SearchItemInfo this[int index] + { + get + { + return (SearchItemInfo) List[index]; + } + set + { + List[index] = value; + } + } + + #endregion + + #region "Public Methods" + + /// + /// Add an element of the specified SearchItemInfo to the end of the collection. + /// + /// An object of type SearchItemInfo to add to the collection. + public int Add(SearchItemInfo value) + { + return List.Add(value); + } + + /// + /// Gets the index in the collection of the specified SearchItemInfoCollection, if it exists in the collection. + /// + /// The SearchItemInfoCollection to locate in the collection. + /// The index in the collection of the specified object, if found; otherwise, -1. + public int IndexOf(SearchItemInfo value) + { + return List.IndexOf(value); + } + + /// + /// Add an element of the specified SearchItemInfo to the collection at the designated index. + /// + /// An Integer to indicate the location to add the object to the collection. + /// An object of type SearchItemInfo to add to the collection. + public void Insert(int index, SearchItemInfo value) + { + List.Insert(index, value); + } + + /// + /// Remove the specified object of type SearchItemInfo from the collection. + /// + /// An object of type SearchItemInfo to remove to the collection. + public void Remove(SearchItemInfo value) + { + List.Remove(value); + } + + /// + /// Gets a value indicating whether the collection contains the specified SearchItemInfoCollection. + /// + /// The SearchItemInfoCollection to search for in the collection. + /// true if the collection contains the specified object; otherwise, false. + public bool Contains(SearchItemInfo value) + { + return List.Contains(value); + } + + /// + /// Copies the elements of the specified SearchItemInfo array to the end of the collection. + /// + /// An array of type SearchItemInfo containing the objects to add to the collection. + public void AddRange(SearchItemInfo[] value) + { + for (int i = 0; i <= value.Length - 1; i++) + { + Add(value[i]); + } + } + + /// + /// Copies the elements of the specified arraylist to the end of the collection. + /// + /// An arraylist of type SearchItemInfo containing the objects to add to the collection. + public void AddRange(ArrayList value) + { + foreach (object obj in value) + { + if (obj is SearchItemInfo) + { + Add((SearchItemInfo) obj); + } + } + } + + /// + /// Adds the contents of another SearchItemInfoCollection to the end of the collection. + /// + /// A SearchItemInfoCollection containing the objects to add to the collection. + public void AddRange(SearchItemInfoCollection value) + { + for (int i = 0; i <= value.Count - 1; i++) + { + Add((SearchItemInfo) value.List[i]); + } + } + + /// + /// Copies the collection objects to a one-dimensional Array instance beginning at the specified index. + /// + /// The one-dimensional Array that is the destination of the values copied from the collection. + /// The index of the array at which to begin inserting. + public void CopyTo(SearchItemInfo[] array, int index) + { + List.CopyTo(array, index); + } + + /// + /// Creates a one-dimensional Array instance containing the collection items. + /// + /// Array of type SearchItemInfo + public SearchItemInfo[] ToArray() + { + var arr = new SearchItemInfo[Count]; + CopyTo(arr, 0); + + return arr; + } + + public SearchItemInfoCollection ModuleItems(int ModuleId) + { + var retValue = new SearchItemInfoCollection(); + foreach (SearchItemInfo info in this) + { + if (info.ModuleId == ModuleId) + { + retValue.Add(info); + } + } + return retValue; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/SearchResultsInfo.cs b/DNN Platform/Library/Services/Search/SearchResultsInfo.cs new file mode 100644 index 00000000000..5fb0bd0da6e --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchResultsInfo.cs @@ -0,0 +1,243 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchResultsInfo + /// ----------------------------------------------------------------------------- + /// + /// The SearchResultsInfo represents a Search Result Item + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + [Serializable] + public class SearchResultsInfo + { + private string m_Author; + private string m_AuthorName; + private bool m_Delete; + private string m_Description; + private string m_Guid; + private int m_Image; + private int m_ModuleId; + private int m_Occurrences; + private int m_PortalId; + private DateTime m_PubDate; + private int m_Relevance; + private int m_SearchItemID; + private string m_SearchKey; + private int m_TabId; + private string m_Title; + + public int SearchItemID + { + get + { + return m_SearchItemID; + } + set + { + m_SearchItemID = value; + } + } + + public string Title + { + get + { + return m_Title; + } + set + { + m_Title = value; + } + } + + public string Description + { + get + { + return m_Description; + } + set + { + m_Description = value; + } + } + + public string Author + { + get + { + return m_Author; + } + set + { + m_Author = value; + } + } + + public DateTime PubDate + { + get + { + return m_PubDate; + } + set + { + m_PubDate = value; + } + } + + public string Guid + { + get + { + return m_Guid; + } + set + { + m_Guid = value; + } + } + + public int Image + { + get + { + return m_Image; + } + set + { + m_Image = value; + } + } + + public int TabId + { + get + { + return m_TabId; + } + set + { + m_TabId = value; + } + } + + public string SearchKey + { + get + { + return m_SearchKey; + } + set + { + m_SearchKey = value; + } + } + + public int Occurrences + { + get + { + return m_Occurrences; + } + set + { + m_Occurrences = value; + } + } + + public int Relevance + { + get + { + return m_Relevance; + } + set + { + m_Relevance = value; + } + } + + public int ModuleId + { + get + { + return m_ModuleId; + } + set + { + m_ModuleId = value; + } + } + + public bool Delete + { + get + { + return m_Delete; + } + set + { + m_Delete = value; + } + } + + public string AuthorName + { + get + { + return m_AuthorName; + } + set + { + m_AuthorName = value; + } + } + + public int PortalId + { + get + { + return m_PortalId; + } + set + { + m_PortalId = value; + } + } + } +} diff --git a/DNN Platform/Library/Services/Search/SearchResultsInfoCollection.cs b/DNN Platform/Library/Services/Search/SearchResultsInfoCollection.cs new file mode 100644 index 00000000000..d5f11a82720 --- /dev/null +++ b/DNN Platform/Library/Services/Search/SearchResultsInfoCollection.cs @@ -0,0 +1,220 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke + /// Class: SearchResultsInfoCollection + /// ----------------------------------------------------------------------------- + /// + /// Represents a collection of SearchResultsInfo objects. + /// + /// + /// + /// + /// [cnurse] 11/15/2004 documented + /// + /// ----------------------------------------------------------------------------- + [Obsolete("Deprecated in DNN 7.1. No longer used in the Search infrastructure.")] + [Serializable] + public class SearchResultsInfoCollection : CollectionBase + { + #region "Constructors" + + /// + /// Initializes a new instance of the SearchResultsInfoCollection class. + /// + public SearchResultsInfoCollection() + { + } + + /// + /// Initializes a new instance of the SearchResultsInfoCollection class containing the elements of the specified source collection. + /// + /// A SearchResultsInfoCollection with which to initialize the collection. + public SearchResultsInfoCollection(SearchResultsInfoCollection value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchResultsInfoCollection class containing the specified array of SearchResultsInfo objects. + /// + /// An array of SearchResultsInfo objects with which to initialize the collection. + public SearchResultsInfoCollection(SearchResultsInfo[] value) + { + AddRange(value); + } + + /// + /// Initializes a new instance of the SearchResultsInfoCollection class containing the specified array of SearchResultsInfo objects. + /// + /// An array of SearchResultsInfo objects with which to initialize the collection. + public SearchResultsInfoCollection(ArrayList value) + { + AddRange(value); + } + + #endregion + + #region "Properties" + + /// + /// Gets the SearchResultsInfoCollection at the specified index in the collection. + /// + /// In VB.Net, this property is the indexer for the SearchResultsInfoCollection class. + /// + /// + public SearchResultsInfo this[int index] + { + get + { + return (SearchResultsInfo) List[index]; + } + set + { + List[index] = value; + } + } + + #endregion + + #region "Public Methods" + + /// + /// Add an element of the specified SearchResultsInfo to the end of the collection. + /// + /// An object of type SearchResultsInfo to add to the collection. + public int Add(SearchResultsInfo value) + { + return List.Add(value); + } + + /// + /// Gets the index in the collection of the specified SearchResultsInfoCollection, if it exists in the collection. + /// + /// The SearchResultsInfoCollection to locate in the collection. + /// The index in the collection of the specified object, if found; otherwise, -1. + public int IndexOf(SearchResultsInfo value) + { + return List.IndexOf(value); + } + + /// + /// Add an element of the specified SearchResultsInfo to the collection at the designated index. + /// + /// An Integer to indicate the location to add the object to the collection. + /// An object of type SearchResultsInfo to add to the collection. + public void Insert(int index, SearchResultsInfo value) + { + List.Insert(index, value); + } + + /// + /// Remove the specified object of type SearchResultsInfo from the collection. + /// + /// An object of type SearchResultsInfo to remove to the collection. + public void Remove(SearchResultsInfo value) + { + List.Remove(value); + } + + /// + /// Gets a value indicating whether the collection contains the specified SearchResultsInfoCollection. + /// + /// The SearchResultsInfoCollection to search for in the collection. + /// true if the collection contains the specified object; otherwise, false. + public bool Contains(SearchResultsInfo value) + { + return List.Contains(value); + } + + /// + /// Copies the elements of the specified SearchResultsInfo array to the end of the collection. + /// + /// An array of type SearchResultsInfo containing the objects to add to the collection. + public void AddRange(SearchResultsInfo[] value) + { + for (int i = 0; i <= value.Length - 1; i++) + { + Add(value[i]); + } + } + + /// + /// Copies the elements of the specified arraylist to the end of the collection. + /// + /// An arraylist of type SearchResultsInfo containing the objects to add to the collection. + public void AddRange(ArrayList value) + { + foreach (object obj in value) + { + if (obj is SearchResultsInfo) + { + Add((SearchResultsInfo) obj); + } + } + } + + /// + /// Adds the contents of another SearchResultsInfoCollection to the end of the collection. + /// + /// A SearchResultsInfoCollection containing the objects to add to the collection. + public void AddRange(SearchResultsInfoCollection value) + { + for (int i = 0; i <= value.Count - 1; i++) + { + Add((SearchResultsInfo) value.List[i]); + } + } + + /// + /// Copies the collection objects to a one-dimensional Array instance beginning at the specified index. + /// + /// The one-dimensional Array that is the destination of the values copied from the collection. + /// The index of the array at which to begin inserting. + public void CopyTo(SearchResultsInfo[] array, int index) + { + List.CopyTo(array, index); + } + + /// + /// Creates a one-dimensional Array instance containing the collection items. + /// + /// Array of type SearchResultsInfo + public SearchResultsInfo[] ToArray() + { + var arr = new SearchResultsInfo[Count]; + CopyTo(arr, 0); + return arr; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Search/TabIndexer.cs b/DNN Platform/Library/Services/Search/TabIndexer.cs new file mode 100644 index 00000000000..3ba0060dfcb --- /dev/null +++ b/DNN Platform/Library/Services/Search/TabIndexer.cs @@ -0,0 +1,119 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Collections.Generic; + +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Search +{ + /// ----------------------------------------------------------------------------- + /// Namespace: DotNetNuke.Services.Search + /// Project: DotNetNuke.Search.Index + /// Class: TabIndexer + /// ----------------------------------------------------------------------------- + /// + /// The TabIndexer is an implementation of the abstract IndexingProvider + /// class + /// + /// + /// + /// + /// [vnguyen] 05/27/2013 + /// + /// ----------------------------------------------------------------------------- + public class TabIndexer : IndexingProvider + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(TabIndexer)); + private static readonly int TabSearchTypeId = SearchHelper.Instance.GetSearchTypeByName("tab").SearchTypeId; + + /// ----------------------------------------------------------------------------- + /// + /// Returns the collection of SearchDocuments populated with Tab MetaData for the given portal. + /// + /// + /// + /// + /// + /// [vnguyen] 04/16/2013 created + /// + /// ----------------------------------------------------------------------------- + public override IEnumerable GetSearchDocuments(int portalId, DateTime startDate) + { + var searchDocuments = new List(); + var tabController = new TabController(); + var tabs = tabController.GetTabsByPortal(portalId).AsList().Where(t => ((t.TabSettings["AllowIndex"] == null) || + (t.TabSettings["AllowIndex"] != null && t.TabSettings["AllowIndex"].ToString().ToLower() != "false")) && + t.LastModifiedOnDate > startDate); + try + { + foreach (var tab in tabs) + { + var searchDoc = new SearchDocument + { + SearchTypeId = TabSearchTypeId, + UniqueKey = Constants.TabMetaDataPrefixTag + tab.TabID, + TabId = tab.TabID, + PortalId = tab.PortalID, + CultureCode = tab.CultureCode, + ModifiedTimeUtc = tab.LastModifiedOnDate, + Body = tab.PageHeadText, + Description = tab.Description + }; + searchDoc.Keywords.Add("keywords", tab.KeyWords); + + //Using TabName for searchDoc.Title due to higher prevalence and relavency || TabTitle will be stored as a keyword + searchDoc.Title = tab.TabName; + searchDoc.Keywords.Add("title", tab.Title); + + if (tab.Terms != null && tab.Terms.Count > 0) + { + searchDoc.Tags = tab.Terms.Select(t => t.Name); + } + + Logger.Trace("TabIndexer: Search document for metaData added for page [" + tab.Title + " tid:" + tab.TabID + "]"); + + searchDocuments.Add(searchDoc); + } + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + + return searchDocuments; + } + + [Obsolete("Legacy Search (ISearchable) -- Depricated in DNN 7.1. Use 'GetSearchDocuments' instead.")] + public override SearchItemInfoCollection GetSearchIndexItems(int portalId) + { + return null; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Sitemap/CoreSitemapProvider.cs b/DNN Platform/Library/Services/Sitemap/CoreSitemapProvider.cs new file mode 100644 index 00000000000..8d0f30f6b23 --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/CoreSitemapProvider.cs @@ -0,0 +1,203 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.Services.Sitemap +{ + public class CoreSitemapProvider : SitemapProvider + { + private bool includeHiddenPages; + private float minPagePriority; + + private PortalSettings ps; + private bool useLevelBasedPagePriority; + + /// + /// Includes page urls on the sitemap + /// + /// + /// Pages that are included: + /// - are not deleted + /// - are not disabled + /// - are normal pages (not links,...) + /// - are visible (based on date and permissions) + /// + public override List GetUrls(int portalId, PortalSettings ps, string version) + { + var objTabs = new TabController(); + SitemapUrl pageUrl = null; + var urls = new List(); + + useLevelBasedPagePriority = bool.Parse(PortalController.GetPortalSetting("SitemapLevelMode", portalId, "False")); + minPagePriority = float.Parse(PortalController.GetPortalSetting("SitemapMinPriority", portalId, "0.1"), CultureInfo.InvariantCulture); + includeHiddenPages = bool.Parse(PortalController.GetPortalSetting("SitemapIncludeHidden", portalId, "True")); + + this.ps = ps; + + foreach (TabInfo objTab in objTabs.GetTabsByPortal(portalId).Values) + { + if (!objTab.IsDeleted && !objTab.DisableLink && objTab.TabType == TabType.Normal && (Null.IsNull(objTab.StartDate) || objTab.StartDate < DateTime.Now) && + (Null.IsNull(objTab.EndDate) || objTab.EndDate > DateTime.Now) && IsTabPublic(objTab.TabPermissions)) + { + if (includeHiddenPages || objTab.IsVisible) + { + pageUrl = GetPageUrl(objTab, (ps.ContentLocalizationEnabled) ? objTab.CultureCode : null); + urls.Add(pageUrl); + } + } + } + + + return urls; + } + + /// + /// Return the sitemap url node for the page + /// + /// The page being indexed + /// Culture code to use in the URL + /// A SitemapUrl object for the current page + /// + /// + private SitemapUrl GetPageUrl(TabInfo objTab, string language) + { + var pageUrl = new SitemapUrl(); + pageUrl.Url = Globals.NavigateURL(objTab.TabID, objTab.IsSuperTab, ps, "", language); + + if (pageUrl.Url.ToLower().IndexOf(ps.PortalAlias.HTTPAlias.ToLower()) == -1) + { + // code to fix a bug in dnn5.1.2 for navigateurl + if ((HttpContext.Current != null)) + { + pageUrl.Url = Globals.AddHTTP(HttpContext.Current.Request.Url.Host + pageUrl.Url); + } + else + { + // try to use the portalalias + pageUrl.Url = Globals.AddHTTP(ps.PortalAlias.HTTPAlias.ToLower()) + pageUrl.Url; + } + } + pageUrl.Priority = GetPriority(objTab); + pageUrl.LastModified = objTab.LastModifiedOnDate; + var modCtrl = new ModuleController(); + foreach (ModuleInfo m in modCtrl.GetTabModules(objTab.TabID).Values) + { + if (m.LastModifiedOnDate > objTab.LastModifiedOnDate) + { + pageUrl.LastModified = m.LastModifiedOnDate; + } + } + pageUrl.ChangeFrequency = SitemapChangeFrequency.Daily; + + return pageUrl; + } + + /// + /// When page level priority is used, the priority for each page will be computed from + /// the hierarchy level of the page. + /// Top level pages will have a value of 1, second level 0.9, third level 0.8, ... + /// + /// The page being indexed + /// The priority assigned to the page + /// + /// + protected float GetPriority(TabInfo objTab) + { + float priority = objTab.SiteMapPriority; + + if (useLevelBasedPagePriority) + { + if (objTab.Level >= 9) + { + priority = 0.1F; + } + else + { + priority = Convert.ToSingle(1 - (objTab.Level*0.1)); + } + + if (priority < minPagePriority) + { + priority = minPagePriority; + } + } + + return priority; + } + + #region "Security Check" + + public virtual bool IsTabPublic(TabPermissionCollection objTabPermissions) + { + string roles = objTabPermissions.ToString("VIEW"); + bool hasPublicRole = false; + + + if ((roles != null)) + { + // permissions strings are encoded with Deny permissions at the beginning and Grant permissions at the end for optimal performance + foreach (string role in roles.Split(new[] {';'})) + { + if (!string.IsNullOrEmpty(role)) + { + // Deny permission + if (role.StartsWith("!")) + { + string denyRole = role.Replace("!", ""); + if ((denyRole == Globals.glbRoleUnauthUserName || denyRole == Globals.glbRoleAllUsersName)) + { + hasPublicRole = false; + break; + } + // Grant permission + } + else + { + if ((role == Globals.glbRoleUnauthUserName || role == Globals.glbRoleAllUsersName)) + { + hasPublicRole = true; + break; + } + } + } + } + } + + return hasPublicRole; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Sitemap/SitemapBuilder.cs b/DNN Platform/Library/Services/Sitemap/SitemapBuilder.cs new file mode 100644 index 00000000000..3c7693539c6 --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/SitemapBuilder.cs @@ -0,0 +1,414 @@ +#region Copyright +// +// DotNetNuke� - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; + +#endregion + +namespace DotNetNuke.Services.Sitemap +{ + public class SitemapBuilder + { + private const int SITEMAP_MAXURLS = 50000; + + private const string SITEMAP_VERSION = "0.9"; + private readonly PortalSettings PortalSettings; + + private XmlWriter writer; + + /// + /// Creates an instance of the sitemap builder class + /// + /// Current PortalSettings for the portal being processed + /// + /// + public SitemapBuilder(PortalSettings ps) + { + PortalSettings = ps; + + LoadProviders(); + } + + #region "Sitemap Building" + + /// + /// Builds the complete portal sitemap + /// + /// + /// + public void BuildSiteMap(TextWriter output) + { + int cacheDays = Int32.Parse(PortalController.GetPortalSetting("SitemapCacheDays", PortalSettings.PortalId, "1")); + bool cached = cacheDays > 0; + if (cached && CacheIsValid()) + { + WriteSitemapFileToOutput("sitemap.xml", output); + return; + } + + var allUrls = new List(); + + // excluded urls by priority + float excludePriority = 0; + excludePriority = float.Parse(PortalController.GetPortalSetting("SitemapExcludePriority", PortalSettings.PortalId, "0"), NumberFormatInfo.InvariantInfo); + + // get all urls + bool isProviderEnabled = false; + bool isProviderPriorityOverrided = false; + float providerPriorityValue = 0; + + + foreach (SitemapProvider _provider in Providers) + { + isProviderEnabled = bool.Parse(PortalController.GetPortalSetting(_provider.Name + "Enabled", PortalSettings.PortalId, "True")); + + if (isProviderEnabled) + { + // check if we should override the priorities + isProviderPriorityOverrided = bool.Parse(PortalController.GetPortalSetting(_provider.Name + "Override", PortalSettings.PortalId, "False")); + // stored as an integer (pr * 100) to prevent from translating errors with the decimal point + providerPriorityValue = float.Parse(PortalController.GetPortalSetting(_provider.Name + "Value", PortalSettings.PortalId, "50"))/100; + + // Get all urls from provider + List urls = _provider.GetUrls(PortalSettings.PortalId, PortalSettings, SITEMAP_VERSION); + foreach (SitemapUrl url in urls) + { + if (isProviderPriorityOverrided) + { + url.Priority = providerPriorityValue; + } + if (url.Priority >= excludePriority) + { + allUrls.Add(url); + } + } + } + } + + if (allUrls.Count > SITEMAP_MAXURLS) + { + // create a sitemap index file + + // enabled cache if it's not already + if (!cached) + { + cached = true; + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "SitemapCacheDays", "1"); + } + + // create all the files + int index = 0; + int numFiles = (allUrls.Count/SITEMAP_MAXURLS) + 1; + int elementsInFile = allUrls.Count/numFiles; + + for (index = 1; index <= numFiles; index++) + { + int lowerIndex = elementsInFile*(index - 1); + int elements = 0; + if (index == numFiles) + { + // last file + elements = allUrls.Count - (elementsInFile*(numFiles - 1)); + } + else + { + elements = elementsInFile; + } + + WriteSitemap(cached, output, index, allUrls.GetRange(lowerIndex, elements)); + } + + // create the sitemap index + WriteSitemapIndex(output, index - 1); + } + else + { + // create a regular sitemap file + WriteSitemap(cached, output, 0, allUrls); + } + + + if (cached) + { + WriteSitemapFileToOutput("sitemap.xml", output); + } + } + + /// + /// Returns the sitemap file that is part of a sitemapindex. + /// + /// Index of the sitemap to return + /// The output stream + /// + /// The file should already exist since when using sitemapindexes the files are all cached to disk + /// + public void GetSitemapIndexFile(string index, TextWriter output) + { + WriteSitemapFileToOutput("sitemap_" + index + ".xml", output); + } + + /// + /// Generates a sitemap file + /// + /// Wheter the generated file should be cached or not + /// The output stream + /// For sitemapindex files the number of the file being generated, 0 otherwise + /// The list of urls to be included in the file + /// + /// If the output should be cached it will generate a file under the portal directory (portals\[portalid]\sitemaps\) with + /// the result of the generation. If the file is part of a sitemap, index will be appended to the + /// filename cached on disk ("sitemap_1.xml") + /// + private void WriteSitemap(bool cached, TextWriter output, int index, List allUrls) + { + // sitemap Output: can be a file is cache is enabled + TextWriter sitemapOutput = output; + if (cached) + { + if (!Directory.Exists(PortalSettings.HomeDirectoryMapPath + "Sitemap")) + { + Directory.CreateDirectory(PortalSettings.HomeDirectoryMapPath + "Sitemap"); + } + string cachedFile = "sitemap.xml"; + if (index > 0) + { + cachedFile = "sitemap_" + index + ".xml"; + } + sitemapOutput = new StreamWriter(PortalSettings.HomeDirectoryMapPath + "Sitemap\\" + cachedFile, false, Encoding.UTF8); + } + + // Initialize writer + var settings = new XmlWriterSettings(); + settings.Indent = true; + settings.Encoding = Encoding.UTF8; + settings.OmitXmlDeclaration = false; + + writer = XmlWriter.Create(sitemapOutput, settings); + + // build header + writer.WriteStartElement("urlset", "http://www.sitemaps.org/schemas/sitemap/" + SITEMAP_VERSION); + writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); + var schemaLocation = "http://www.sitemaps.org/schemas/sitemap/" + SITEMAP_VERSION; + writer.WriteAttributeString("xsi", "schemaLocation", null, string.Format("{0} {0}/sitemap.xsd", schemaLocation)); + + // write urls to output + foreach (SitemapUrl url in allUrls) + { + AddURL(url); + } + + writer.WriteEndElement(); + writer.Close(); + + if (cached) + { + sitemapOutput.Flush(); + sitemapOutput.Close(); + } + } + + /// + /// Generates a sitemapindex file + /// + /// The output stream + /// Number of files that are included in the sitemap index + private void WriteSitemapIndex(TextWriter output, int totalFiles) + { + TextWriter sitemapOutput = null; + sitemapOutput = new StreamWriter(PortalSettings.HomeDirectoryMapPath + "Sitemap\\sitemap.xml", false, Encoding.UTF8); + + // Initialize writer + var settings = new XmlWriterSettings(); + settings.Indent = true; + settings.Encoding = Encoding.UTF8; + settings.OmitXmlDeclaration = false; + + writer = XmlWriter.Create(sitemapOutput, settings); + + // build header + writer.WriteStartElement("sitemapindex", "http://www.sitemaps.org/schemas/sitemap/" + SITEMAP_VERSION); + + // write urls to output + for (int index = 1; index <= totalFiles; index++) + { + string url = null; + + url = "~/Sitemap.aspx?i=" + index; + if (IsChildPortal(PortalSettings, HttpContext.Current)) + { + url += "&portalid=" + PortalSettings.PortalId; + } + + writer.WriteStartElement("sitemap"); + writer.WriteElementString("loc", Globals.AddHTTP(HttpContext.Current.Request.Url.Host + Globals.ResolveUrl(url))); + writer.WriteElementString("lastmod", DateTime.Now.ToString("yyyy-MM-dd")); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + writer.Close(); + + sitemapOutput.Flush(); + sitemapOutput.Close(); + } + + #endregion + + #region "Helper methods" + + /// + /// Adds a new url to the sitemap + /// + /// The url to be included in the sitemap + /// + /// + private void AddURL(SitemapUrl sitemapUrl) + { + writer.WriteStartElement("url"); + writer.WriteElementString("loc", sitemapUrl.Url); + writer.WriteElementString("lastmod", sitemapUrl.LastModified.ToString("yyyy-MM-dd")); + writer.WriteElementString("changefreq", sitemapUrl.ChangeFrequency.ToString().ToLower()); + writer.WriteElementString("priority", sitemapUrl.Priority.ToString("F01", CultureInfo.InvariantCulture)); + writer.WriteEndElement(); + } + + /// + /// Is sitemap is cached, verifies is the cached file exists and is still valid + /// + /// True is the cached file exists and is still valid, false otherwise + private bool CacheIsValid() + { + int cacheDays = int.Parse(PortalController.GetPortalSetting("SitemapCacheDays", PortalSettings.PortalId, "1")); + bool isValid = true; + + if (!File.Exists(PortalSettings.HomeDirectoryMapPath + "Sitemap\\sitemap.xml")) + { + isValid = false; + } + if (isValid) + { + DateTime lastmod = File.GetLastWriteTime(PortalSettings.HomeDirectoryMapPath + "/Sitemap/sitemap.xml"); + if (lastmod.AddDays(cacheDays) < DateTime.Now) + { + isValid = false; + } + } + + return isValid; + } + + /// + /// When the sitemap is cached, reads the sitemap file and writes to the output stream + /// + /// File name + /// The output stream + private void WriteSitemapFileToOutput(string file, TextWriter output) + { + if (File.Exists(PortalSettings.HomeDirectoryMapPath + "Sitemap\\" + file)) + { + // write the cached file to output + var reader = new StreamReader(PortalSettings.HomeDirectoryMapPath + "/Sitemap/" + file, Encoding.UTF8); + output.Write(reader.ReadToEnd()); + + reader.Close(); + } + } + + + private bool IsChildPortal(PortalSettings ps, HttpContext context) + { + bool isChild = false; + string portalName = null; + var arr = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(ps.PortalId).ToList(); + string serverPath = Globals.GetAbsoluteServerPath(context.Request); + + if (arr.Count > 0) + { + var portalAlias = (PortalAliasInfo) arr[0]; + portalName = Globals.GetPortalDomainName(ps.PortalAlias.HTTPAlias, null, true); + if (portalAlias.HTTPAlias.IndexOf("/") > -1) + { + portalName = PortalController.GetPortalFolder(portalAlias.HTTPAlias); + } + if (!string.IsNullOrEmpty(portalName) && Directory.Exists(serverPath + portalName)) + { + isChild = true; + } + } + return isChild; + } + + #endregion + + #region "Provider configuration and setup" + + private static List _providers; + + private static readonly object _lock = new object(); + + public List Providers + { + get + { + return _providers; + } + } + + + private static void LoadProviders() + { + // Avoid claiming lock if providers are already loaded + if (_providers == null) + { + lock (_lock) + { + _providers = new List(); + + + foreach (KeyValuePair comp in ComponentFactory.GetComponents()) + { + comp.Value.Name = comp.Key; + comp.Value.Description = comp.Value.Description; + _providers.Add(comp.Value); + } + + + //'ProvidersHelper.InstantiateProviders(section.Providers, _providers, GetType(SiteMapProvider)) + } + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Sitemap/SitemapChangeFrequency.cs b/DNN Platform/Library/Services/Sitemap/SitemapChangeFrequency.cs new file mode 100644 index 00000000000..1ac5529cc1d --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/SitemapChangeFrequency.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.Services.Sitemap +{ + public enum SitemapChangeFrequency + { + Always, + Hourly, + Daily, + Weekly, + Monthly, + Yearly, + Never + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Sitemap/SitemapHandler.cs b/DNN Platform/Library/Services/Sitemap/SitemapHandler.cs new file mode 100644 index 00000000000..f86d1ec90c7 --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/SitemapHandler.cs @@ -0,0 +1,75 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Text; +using System.Web; + +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.Sitemap +{ + public class SitemapHandler : IHttpHandler + { + #region IHttpHandler Members + + public bool IsReusable + { + get + { + return true; + } + } + + public void ProcessRequest(HttpContext context) + { + try + { + HttpResponse Response = context.Response; + PortalSettings ps = PortalController.GetCurrentPortalSettings(); + + Response.ContentType = "text/xml"; + Response.ContentEncoding = Encoding.UTF8; + + var builder = new SitemapBuilder(ps); + + if ((context.Request.QueryString["i"] != null)) + { + // This is a request for one of the files that build the sitemapindex + builder.GetSitemapIndexFile(context.Request.QueryString["i"], Response.Output); + } + else + { + builder.BuildSiteMap(Response.Output); + } + } + catch (Exception exc) + { + Exceptions.Exceptions.LogException(exc); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Sitemap/SitemapProvider.cs b/DNN Platform/Library/Services/Sitemap/SitemapProvider.cs new file mode 100644 index 00000000000..d8cd2a3c043 --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/SitemapProvider.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections.Generic; +using System.Globalization; + +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.Sitemap +{ + public abstract class SitemapProvider + { + public string Name { get; set; } + + public string Description { get; set; } + + + public bool Enabled + { + get + { + return bool.Parse(PortalController.GetPortalSetting(Name + "Enabled", PortalController.GetCurrentPortalSettings().PortalId, "True")); + } + set + { + PortalController.UpdatePortalSetting(PortalController.GetCurrentPortalSettings().PortalId, Name + "Enabled", value.ToString()); + } + } + + + public bool OverridePriority + { + get + { + return bool.Parse(PortalController.GetPortalSetting(Name + "Override", PortalController.GetCurrentPortalSettings().PortalId, "False")); + } + set + { + PortalController.UpdatePortalSetting(PortalController.GetCurrentPortalSettings().PortalId, Name + "Override", value.ToString()); + } + } + + public float Priority + { + get + { + float value = 0; + if ((OverridePriority)) + { + // stored as an integer (pr * 100) to prevent from translating errors with the decimal point + value = float.Parse(PortalController.GetPortalSetting(Name + "Value", PortalController.GetCurrentPortalSettings().PortalId, "0.5"), NumberFormatInfo.InvariantInfo); + } + return value; + } + + set + { + PortalController.UpdatePortalSetting(PortalController.GetCurrentPortalSettings().PortalId, Name + "Value", value.ToString(NumberFormatInfo.InvariantInfo)); + } + } + + + public abstract List GetUrls(int portalId, PortalSettings ps, string version); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Sitemap/SitemapUrl.cs b/DNN Platform/Library/Services/Sitemap/SitemapUrl.cs new file mode 100644 index 00000000000..20ba9366fe6 --- /dev/null +++ b/DNN Platform/Library/Services/Sitemap/SitemapUrl.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Sitemap +{ + public class SitemapUrl + { + public string Url { get; set; } + + + public DateTime LastModified { get; set; } + + + public SitemapChangeFrequency ChangeFrequency { get; set; } + + + public float Priority { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Messaging/Data/DataService.cs b/DNN Platform/Library/Services/Social/Messaging/Data/DataService.cs new file mode 100644 index 00000000000..57cc616aae1 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Data/DataService.cs @@ -0,0 +1,299 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Social.Messaging.Internal.Views; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Data +{ + internal class DataService : ComponentBase, IDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + + #region Messages CRUD + + public int SaveMessage(Message message, int portalId, int createUpdateUserId) + { + //need to fix groupmail + return _provider.ExecuteScalar("CoreMessaging_SaveMessage", message.MessageID, portalId ,message.To, message.From, message.Subject, message.Body, message.ConversationId, message.ReplyAllAllowed, message.SenderUserID, createUpdateUserId); + } + + public IDataReader GetMessage(int messageId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessage", messageId); + } + + public IDataReader GetLastSentMessage(int userId, int portalId) + { + return _provider.ExecuteReader("CoreMessaging_GetLastSentMessage", userId, portalId); + } + + public IDataReader GetMessagesBySender(int messageId, int portalId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessagesBySender", messageId, portalId); + } + + public void DeleteMessage(int messageId) + { + _provider.ExecuteNonQuery("CoreMessaging_DeleteMessage", messageId); + } + + public int CreateMessageReply(int conversationId, int portalId,string body, int senderUserId, string from, int createUpdateUserId) + { + return _provider.ExecuteScalar("CoreMessaging_CreateMessageReply", conversationId, portalId,body, senderUserId, from, createUpdateUserId); + } + + public IDataReader GetInBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus, MessageSentStatus sentStatus) + { + object read = null; + object archived = null; + object sent = null; + + switch (readStatus) + { + case MessageReadStatus.Read: + read = true; + break; + case MessageReadStatus.UnRead: + read = false; + break; + } + + switch (archivedStatus) + { + case MessageArchivedStatus.Archived: + archived = true; + break; + case MessageArchivedStatus.UnArchived: + archived = false; + break; + } + + switch (sentStatus) + { + case MessageSentStatus.Received: + sent = false; + break; + case MessageSentStatus.Sent: + sent = true; + break; + } + + return _provider.ExecuteReader("CoreMessaging_GetMessageConversations", userId, portalId , afterMessageId, numberOfRecords, sortColumn, sortAscending, read, archived, sent); + } + + public IDataReader GetSentBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending) + { + return _provider.ExecuteReader("CoreMessaging_GetSentBox", userId, portalId, afterMessageId, numberOfRecords, sortColumn, sortAscending); + } + + public IDataReader GetArchiveBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending) + { + return _provider.ExecuteReader("CoreMessaging_GetArchiveBox", userId, portalId, afterMessageId, numberOfRecords, sortColumn, sortAscending); + } + + public IDataReader GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool @sortAscending, ref int totalRecords) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageThread", conversationId, userId, afterMessageId, numberOfRecords, sortColumn, sortAscending); + } + + public void UpdateMessageReadStatus(int conversationId, int userId, bool read) + { + _provider.ExecuteNonQuery("CoreMessaging_UpdateMessageReadStatus", conversationId, userId, read); + } + + public void UpdateMessageArchivedStatus(int conversationId, int userId, bool archived) + { + _provider.ExecuteNonQuery("CoreMessaging_UpdateMessageArchivedStatus", conversationId, userId, archived); + } + + public int CountNewThreads(int userId, int portalId) + { + return _provider.ExecuteScalar("CoreMessaging_CountNewThreads", userId, portalId); + } + + public int CountTotalConversations(int userId, int portalId) + { + return _provider.ExecuteScalar("CoreMessaging_CountTotalConversations", userId, portalId); + } + + public int CountMessagesByConversation(int conversationId) + { + return _provider.ExecuteScalar("CoreMessaging_CountMessagesByConversation", conversationId); + } + + public int CountArchivedMessagesByConversation(int conversationId) + { + return _provider.ExecuteScalar("CoreMessaging_CountArchivedMessagesByConversation", conversationId); + } + + public int CountSentMessages(int userId, int portalId) + { + return _provider.ExecuteScalar("CoreMessaging_CountSentMessages", userId, portalId); + } + + public int CountArchivedMessages(int userId, int portalId) + { + return _provider.ExecuteScalar("CoreMessaging_CountArchivedMessages", userId, portalId); + } + + #endregion + + #region Message_Recipients CRUD + + public int SaveMessageRecipient(MessageRecipient messageRecipient, int createUpdateUserId) + { + return _provider.ExecuteScalar("CoreMessaging_SaveMessageRecipient", messageRecipient.RecipientID, messageRecipient.MessageID, messageRecipient.UserID, messageRecipient.Read, messageRecipient.Archived, createUpdateUserId); + } + + public void CreateMessageRecipientsForRole(int messageId, string roleIds, int createUpdateUserId) + { + _provider.ExecuteNonQuery("CoreMessaging_CreateMessageRecipientsForRole", messageId, roleIds, createUpdateUserId); + } + + public IDataReader GetMessageRecipient(int messageRecipientId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageRecipient", messageRecipientId); + } + + public IDataReader GetMessageRecipientsByUser(int userId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageRecipientsByUser", userId); + } + + public IDataReader GetMessageRecipientsByMessage(int messageId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageRecipientsByMessage", messageId); + } + + public IDataReader GetMessageRecipientByMessageAndUser(int messageId, int userId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageRecipientsByMessageAndUser", messageId, userId); + } + + public void DeleteMessageRecipient(int messageRecipientId) + { + _provider.ExecuteNonQuery("CoreMessaging_DeleteMessageRecipient", messageRecipientId); + } + + public void DeleteMessageRecipientByMessageAndUser(int messageId, int userId) + { + _provider.ExecuteNonQuery("CoreMessaging_DeleteMessageRecipientByMessageAndUser", messageId, userId); + } + + #endregion + + #region Message_Attachments CRUD + + public int SaveMessageAttachment(MessageAttachment messageAttachment, int createUpdateUserId) + { + return _provider.ExecuteScalar("CoreMessaging_SaveMessageAttachment", messageAttachment.MessageAttachmentID, messageAttachment.MessageID, messageAttachment.FileID, createUpdateUserId); + } + + public IDataReader GetMessageAttachment(int messageAttachmentId) + { + return _provider.ExecuteReader("CoreMessaging_GetMessageAttachment", messageAttachmentId); + } + + public IList GetMessageAttachmentsByMessage(int messageId) + { + var attachments = new List(); + var dr = _provider.ExecuteReader("CoreMessaging_GetMessageAttachmentsByMessage", messageId); + + try + { + while (dr.Read()) + { + var fileId = Convert.ToInt32(dr["FileID"]); + var file = FileManager.Instance.GetFile(fileId); + + if (file == null) continue; + + var attachment = new MessageFileView + { + Name = file.FileName, + Size = file.Size.ToString(CultureInfo.InvariantCulture), + Url = FileManager.Instance.GetUrl(file) + }; + + attachments.Add(attachment); + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + return attachments; + } + + public void DeleteMessageAttachment(int messageAttachmentId) + { + _provider.ExecuteNonQuery("CoreMessaging_DeleteMessageAttachment", messageAttachmentId); + } + + #endregion + + #region Upgrade APIs + + public void ConvertLegacyMessages(int pageIndex, int pageSize) + { + _provider.ExecuteNonQuery("CoreMessaging_ConvertLegacyMessages", pageIndex, pageSize); + } + + public IDataReader CountLegacyMessages() + { + return _provider.ExecuteReader("CoreMessaging_CountLegacyMessages"); + } + + #endregion + + #region Queued email API's + + public IDataReader GetNextMessagesForDispatch(Guid schedulerInstance,int batchSize) + { + return _provider.ExecuteReader("CoreMessaging_GetNextMessagesForDispatch", schedulerInstance,batchSize); + } + + public void MarkMessageAsDispatched(int messageId,int recipientId) + { + _provider.ExecuteNonQuery("CoreMessaging_MarkMessageAsDispatched", messageId, recipientId); + } + + public void MarkMessageAsSent(int messageId, int recipientId) + { + _provider.ExecuteNonQuery("CoreMessaging_MarkMessageAsSent", messageId, recipientId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Messaging/Data/IDataService.cs b/DNN Platform/Library/Services/Social/Messaging/Data/IDataService.cs new file mode 100644 index 00000000000..5eacabb6e3e --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Data/IDataService.cs @@ -0,0 +1,97 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; + +using DotNetNuke.Services.Social.Messaging.Internal.Views; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Data +{ + public interface IDataService + { + #region Messages CRUD + + int SaveMessage(Message message, int portalId, int createUpdateUserId); + IDataReader GetMessage(int messageId); + IDataReader GetMessagesBySender(int messageId, int portalId); + IDataReader GetLastSentMessage(int userId, int portalId); + void DeleteMessage(int messageId); + + IDataReader GetInBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus, MessageSentStatus sentStatus); + IDataReader GetSentBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending); + IDataReader GetArchiveBoxView(int userId, int portalId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending); + IDataReader GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, ref int totalRecords); + void UpdateMessageReadStatus(int conversationId, int userId, bool read); + void UpdateMessageArchivedStatus(int conversationId, int userId, bool archived); + int CreateMessageReply(int conversationId, int portalId,string body, int senderUserId, string from, int createUpdateUserId); + int CountNewThreads(int userId, int portalId); + int CountTotalConversations(int userId, int portalId); + int CountMessagesByConversation(int conversationId); + int CountArchivedMessagesByConversation(int conversationId); + int CountSentMessages(int userId, int portalId); + int CountArchivedMessages(int userId, int portalId); + + #endregion + + #region Message_Recipients CRUD + + int SaveMessageRecipient(MessageRecipient messageRecipient, int createUpdateUserId); + void CreateMessageRecipientsForRole(int messageId, string roleIds, int createUpdateUserId); + IDataReader GetMessageRecipient(int messageRecipientId); + IDataReader GetMessageRecipientsByUser(int userId); + IDataReader GetMessageRecipientsByMessage(int messageId); + IDataReader GetMessageRecipientByMessageAndUser(int messageId, int userId); + void DeleteMessageRecipient(int messageRecipientId); + void DeleteMessageRecipientByMessageAndUser(int messageId, int userId); + + #endregion + + #region Message_Attachments CRUD + + int SaveMessageAttachment(MessageAttachment messageAttachment, int createUpdateUserId); + IDataReader GetMessageAttachment(int messageAttachmentId); + IList GetMessageAttachmentsByMessage(int messageId); + void DeleteMessageAttachment(int messageAttachmentId); + + #endregion + + #region Upgrade APIs + + void ConvertLegacyMessages(int pageIndex, int pageSize); + + IDataReader CountLegacyMessages(); + + #endregion + + #region Queued email API's + + IDataReader GetNextMessagesForDispatch(Guid schedulerInstance, int batchSize); + void MarkMessageAsDispatched(int messageId,int recipientId); + void MarkMessageAsSent(int messageId, int recipientId); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Messaging/Exceptions/AttachmentsNotAllowedException.cs b/DNN Platform/Library/Services/Social/Messaging/Exceptions/AttachmentsNotAllowedException.cs new file mode 100644 index 00000000000..b24cca77118 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Exceptions/AttachmentsNotAllowedException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.Social.Messaging.Exceptions +{ + [Serializable] + public class AttachmentsNotAllowed : Exception + { + public AttachmentsNotAllowed() + { + } + + public AttachmentsNotAllowed(string message) + : base(message) + { + } + + public AttachmentsNotAllowed(string message, Exception inner) + : base(message, inner) + { + } + + public AttachmentsNotAllowed(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Exceptions/MessageOrRecipientNotFoundException.cs b/DNN Platform/Library/Services/Social/Messaging/Exceptions/MessageOrRecipientNotFoundException.cs new file mode 100644 index 00000000000..c2c48440d50 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Exceptions/MessageOrRecipientNotFoundException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.Social.Messaging.Exceptions +{ + [Serializable] + public class MessageOrRecipientNotFoundException : Exception + { + public MessageOrRecipientNotFoundException() + { + } + + public MessageOrRecipientNotFoundException(string message) + : base(message) + { + } + + public MessageOrRecipientNotFoundException(string message, Exception inner) + : base(message, inner) + { + } + + public MessageOrRecipientNotFoundException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Exceptions/RecipientLimitExceededException.cs b/DNN Platform/Library/Services/Social/Messaging/Exceptions/RecipientLimitExceededException.cs new file mode 100644 index 00000000000..669fc252eba --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Exceptions/RecipientLimitExceededException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.Social.Messaging.Exceptions +{ + [Serializable] + public class RecipientLimitExceededException : Exception + { + public RecipientLimitExceededException() + { + } + + public RecipientLimitExceededException(string message) + : base(message) + { + } + + public RecipientLimitExceededException(string message, Exception inner) + : base(message, inner) + { + } + + public RecipientLimitExceededException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Exceptions/ThrottlingIntervalNotMetException.cs b/DNN Platform/Library/Services/Social/Messaging/Exceptions/ThrottlingIntervalNotMetException.cs new file mode 100644 index 00000000000..5f644b59e6f --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Exceptions/ThrottlingIntervalNotMetException.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Runtime.Serialization; + +namespace DotNetNuke.Services.Social.Messaging.Exceptions +{ + [Serializable] + public class ThrottlingIntervalNotMetException : Exception + { + public ThrottlingIntervalNotMetException() + { + } + + public ThrottlingIntervalNotMetException(string message) + : base(message) + { + } + + public ThrottlingIntervalNotMetException(string message, Exception inner) + : base(message, inner) + { + } + + public ThrottlingIntervalNotMetException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/IMessagingController.cs b/DNN Platform/Library/Services/Social/Messaging/IMessagingController.cs new file mode 100644 index 00000000000..a0d86cb7ba3 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/IMessagingController.cs @@ -0,0 +1,40 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +namespace DotNetNuke.Services.Social.Messaging +{ + public interface IMessagingController + { + #region Public APIs + + void SendMessage(Message message, IList roles, IList users, IList fileIDs); + + void SendMessage(Message message, IList roles, IList users, IList fileIDs, UserInfo sender); + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/IInternalMessagingController.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/IInternalMessagingController.cs new file mode 100644 index 00000000000..7228fb524b7 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/IInternalMessagingController.cs @@ -0,0 +1,136 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Social.Messaging.Internal.Views; + +namespace DotNetNuke.Services.Social.Messaging.Internal +{ + public interface IInternalMessagingController + { + #region Reply APIs + + int ReplyMessage(int conversationId, string body, IList fileIDs); + + int ReplyMessage(int conversationId, string body, IList fileIDs, UserInfo sender); + + #endregion + + + #region CRUD APIs + + Message GetMessage(int messageId); + MessageRecipient GetMessageRecipient(int messageId, int userId); + IList GetMessageRecipients(int messageId); + void DeleteMessageRecipient(int messageId, int userId); + + + void MarkRead(int conversationId, int userId); + void MarkUnRead(int conversationId, int userId); + void MarkArchived(int conversationId, int userId); + void MarkUnArchived(int conversationId, int userId); + + #endregion + + #region Admin Settings APIs + + ///How long a user needs to wait before user is allowed sending the next message + ///Time in seconds. Returns zero if user has never sent a message + /// Sender's UserInfo + int WaitTimeForNextMessage(UserInfo sender); + + ///Last message sent by the User + ///Message. Null when no message was sent + /// Sender's UserInfo + Message GetLastSentMessage(UserInfo sender); + + ///Maximum number of Recipients allowed + ///Count. Message to a Role is considered a single Recipient. Each User in the To list is counted as one User each. + /// Portal Id + int RecipientLimit(int portalId); + + ///Are attachments allowed + ///True or False + /// Portal Id + bool AttachmentsAllowed(int portalId); + + #endregion + + #region Upgrade APIs + + void ConvertLegacyMessages(int pageIndex, int pageSize); + int CountLegacyMessages(); + + #endregion + + #region Get View APIs + + MessageBoxView GetInbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool @ascending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus); + + MessageBoxView GetInbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending); + + MessageBoxView GetRecentInbox(int userId); + + MessageBoxView GetRecentInbox(int userId, int afterMessageId, int numberOfRecords); + + MessageBoxView GetSentbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool ascending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus); + + MessageBoxView GetSentbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending); + + MessageBoxView GetRecentSentbox(int userId); + + MessageBoxView GetRecentSentbox(int userId, int afterMessageId, int numberOfRecords); + + MessageBoxView GetArchivedMessages(int userId, int afterMessageId, int numberOfRecords); + + MessageThreadsView GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool ascending, ref int totalRecords); + + MessageThreadsView GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, ref int totalRecords); + + #endregion + + #region Queued email API's + + IList GetNextMessagesForDispatch(Guid schedulerInstance,int batchSize); + void MarkMessageAsDispatched(int messageId, int recipientId); + void MarkMessageAsSent(int messageId, int recipientId); + + #endregion + + #region Counter APIs + + int CountUnreadMessages(int userId, int portalId); + + int CountConversations(int userId, int portalId); + + int CountMessagesByConversation(int conversationId); + + int CountArchivedMessagesByConversation(int conversationId); + + int CountSentMessages(int userId, int portalId); + + int CountArchivedMessages(int userId, int portalId); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingController.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingController.cs new file mode 100644 index 00000000000..d9e505f8758 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingController.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Internal +{ + /// + /// Business Layer to manage Messaging. Also contains CRUD methods. + /// + public class InternalMessagingController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new InternalMessagingControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingControllerImpl.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingControllerImpl.cs new file mode 100644 index 00000000000..e9fdda2b66b --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/InternalMessagingControllerImpl.cs @@ -0,0 +1,446 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Services.Social.Messaging.Data; +using DotNetNuke.Services.Social.Messaging.Exceptions; +using DotNetNuke.Services.Social.Messaging.Internal.Views; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Internal +{ + /// ----------------------------------------------------------------------------- + /// + /// The Controller class for social Messaging + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + internal class InternalMessagingControllerImpl : IInternalMessagingController + { + #region Constants + + internal const int ConstMaxTo = 2000; + internal const int ConstMaxSubject = 400; + internal const int ConstDefaultPageIndex = 0; + internal const int ConstDefaultPageSize = 10; + internal const string ConstSortColumnDate = "CreatedOnDate"; + internal const string ConstSortColumnFrom = "From"; + internal const string ConstSortColumnSubject = "Subject"; + internal const bool ConstAscending = true; + + #endregion + + #region Private Variables + + private readonly IDataService _dataService; + + #endregion + + #region Constructors + + public InternalMessagingControllerImpl() + : this(DataService.Instance) + { + } + + public InternalMessagingControllerImpl(IDataService dataService) + { + //Argument Contract + Requires.NotNull("dataService", dataService); + + _dataService = dataService; + } + + #endregion + + #region CRUD APIs + + public virtual void DeleteMessageRecipient(int messageId, int userId) + { + _dataService.DeleteMessageRecipientByMessageAndUser(messageId, userId); + } + + public virtual Message GetMessage(int messageId) + { + return CBO.FillObject(_dataService.GetMessage(messageId)); + } + + public virtual MessageRecipient GetMessageRecipient(int messageId, int userId) + { + return CBO.FillObject(_dataService.GetMessageRecipientByMessageAndUser(messageId, userId)); + } + + public virtual IList GetMessageRecipients(int messageId) + { + return CBO.FillCollection(_dataService.GetMessageRecipientsByMessage(messageId)); + } + + public virtual void MarkArchived(int conversationId, int userId) + { + _dataService.UpdateMessageArchivedStatus(conversationId, userId, true); + } + + public virtual void MarkRead(int conversationId, int userId) + { + _dataService.UpdateMessageReadStatus(conversationId, userId, true); + } + + public virtual void MarkUnArchived(int conversationId, int userId) + { + _dataService.UpdateMessageArchivedStatus(conversationId, userId, false); + } + + public virtual void MarkUnRead(int conversationId, int userId) + { + _dataService.UpdateMessageReadStatus(conversationId, userId, false); + } + + #endregion + + #region Reply APIs + + public virtual int ReplyMessage(int conversationId, string body, IList fileIDs) + { + return ReplyMessage(conversationId, body, fileIDs, UserController.GetCurrentUserInfo()); + } + + public virtual int ReplyMessage(int conversationId, string body, IList fileIDs, UserInfo sender) + { + if (sender == null || sender.UserID <= 0) + { + throw new ArgumentException(Localization.Localization.GetString("MsgSenderRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (string.IsNullOrEmpty(body)) + { + throw new ArgumentException(Localization.Localization.GetString("MsgBodyRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + //Cannot have attachments if it's not enabled + if (fileIDs != null && !InternalMessagingController.Instance.AttachmentsAllowed(sender.PortalID)) + { + throw new AttachmentsNotAllowed(Localization.Localization.GetString("MsgAttachmentsNotAllowed", Localization.Localization.ExceptionsResourceFile)); + } + + //Profanity Filter + var profanityFilterSetting = GetPortalSetting("MessagingProfanityFilters", sender.PortalID, "NO"); + if (profanityFilterSetting.Equals("YES", StringComparison.InvariantCultureIgnoreCase)) + { + body = InputFilter(body); + } + + //call ReplyMessage + var messageId = _dataService.CreateMessageReply(conversationId, PortalController.GetEffectivePortalId(sender.PortalID), body, sender.UserID, sender.DisplayName, GetCurrentUserInfo().UserID); + if (messageId == -1) //Parent message was not found or Recipient was not found in the message + { + throw new MessageOrRecipientNotFoundException(Localization.Localization.GetString("MsgMessageOrRecipientNotFound", Localization.Localization.ExceptionsResourceFile)); + } + + //associate attachments + if (fileIDs != null) + { + foreach (var attachment in fileIDs.Select(fileId => new MessageAttachment { MessageAttachmentID = Null.NullInteger, FileID = fileId, MessageID = messageId })) + { + _dataService.SaveMessageAttachment(attachment, UserController.GetCurrentUserInfo().UserID); + } + } + + // Mark reply as read and dispatched by the sender + var recipient = GetMessageRecipient(messageId, sender.UserID); + + MarkMessageAsDispatched(messageId, recipient.RecipientID); + MarkRead(conversationId, sender.UserID); + + return messageId; + } + + + #endregion + + #region Admin Settings APIs + + /// How long a user needs to wait before sending the next message. + /// Time in seconds. Returns zero if user is Host, Admin or has never sent a message. + /// Sender's UserInfo + /// + public virtual int WaitTimeForNextMessage(UserInfo sender) + { + Requires.NotNull("sender", sender); + + var waitTime = 0; + // MessagingThrottlingInterval contains the number of MINUTES to wait before sending the next message + var interval = GetPortalSettingAsInteger("MessagingThrottlingInterval", sender.PortalID, Null.NullInteger) * 60; + if (interval > 0 && !IsAdminOrHost(sender)) + { + var lastSentMessage = GetLastSentMessage(sender); + if (lastSentMessage != null) + { + waitTime = (int)(interval - GetDateTimeNow().Subtract(lastSentMessage.CreatedOnDate).TotalSeconds); + } + } + return waitTime < 0 ? 0 : waitTime; + } + + ///Last message sent by the User + ///Message. Null when no message was sent + /// Sender's UserInfo + public virtual Message GetLastSentMessage(UserInfo sender) + { + return CBO.FillObject(_dataService.GetLastSentMessage(sender.UserID, PortalController.GetEffectivePortalId(sender.PortalID))); + } + + ///Are attachments allowed + ///True or False + /// Portal Id + public virtual bool AttachmentsAllowed(int portalId) + { + return GetPortalSetting("MessagingAllowAttachments", portalId, "YES") == "YES"; + } + + ///Maximum number of Recipients allowed + ///Count. Message to a Role is considered a single Recipient. Each User in the To list is counted as one User each. + /// Portal Id + public virtual int RecipientLimit(int portalId) + { + return GetPortalSettingAsInteger("MessagingRecipientLimit", portalId, 5); + } + + #endregion + + #region Get View APIs + + public virtual MessageBoxView GetArchivedMessages(int userId, int afterMessageId, int numberOfRecords) + { + var reader = _dataService.GetArchiveBoxView(userId, PortalController.GetEffectivePortalId(GetCurrentUserInfo().PortalID), afterMessageId, numberOfRecords, ConstSortColumnDate, !ConstAscending); + return new MessageBoxView { Conversations = CBO.FillCollection(reader) }; + } + + public virtual MessageBoxView GetInbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending) + { + return GetInbox(userId, afterMessageId, numberOfRecords, sortColumn, sortAscending, MessageReadStatus.Any, MessageArchivedStatus.UnArchived); + } + + public virtual MessageBoxView GetInbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus) + { + var reader = _dataService.GetInBoxView(userId, PortalController.GetEffectivePortalId(GetCurrentUserInfo().PortalID), afterMessageId, numberOfRecords, sortColumn, sortAscending, readStatus, archivedStatus, MessageSentStatus.Received); + return new MessageBoxView { Conversations = CBO.FillCollection(reader) }; + } + + public virtual MessageThreadsView GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, ref int totalRecords) + { + return GetMessageThread(conversationId, userId, afterMessageId, numberOfRecords, ConstSortColumnDate, !ConstAscending, ref totalRecords); + } + + public virtual MessageThreadsView GetMessageThread(int conversationId, int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, ref int totalRecords) + { + var messageThreadsView = new MessageThreadsView(); + + var dr = _dataService.GetMessageThread(conversationId, userId, afterMessageId, numberOfRecords, sortColumn, sortAscending, ref totalRecords); + + try + { + while (dr.Read()) + { + var messageThreadView = new MessageThreadView { Conversation = new MessageConversationView() }; + messageThreadView.Conversation.Fill(dr); + + if (messageThreadView.Conversation.AttachmentCount > 0) + { + messageThreadView.Attachments = _dataService.GetMessageAttachmentsByMessage(messageThreadView.Conversation.MessageID); + } + + if (messageThreadsView.Conversations == null) messageThreadsView.Conversations = new List(); + + messageThreadsView.Conversations.Add(messageThreadView); + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + return messageThreadsView; + } + + public virtual MessageBoxView GetRecentInbox(int userId) + { + return GetRecentInbox(userId, ConstDefaultPageIndex, ConstDefaultPageSize); + } + + public virtual MessageBoxView GetRecentInbox(int userId, int afterMessageId, int numberOfRecords) + { + return GetInbox(userId, afterMessageId, numberOfRecords, ConstSortColumnDate, !ConstAscending); + } + + public virtual MessageBoxView GetRecentSentbox(int userId) + { + return GetRecentSentbox(userId, ConstDefaultPageIndex, ConstDefaultPageSize); + } + + public virtual MessageBoxView GetRecentSentbox(int userId, int afterMessageId, int numberOfRecords) + { + return GetSentbox(userId, afterMessageId, numberOfRecords, ConstSortColumnDate, !ConstAscending); + } + + public virtual MessageBoxView GetSentbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending) + { + return GetSentbox(userId, afterMessageId, numberOfRecords, sortColumn, sortAscending, MessageReadStatus.Any, MessageArchivedStatus.UnArchived); + } + + public virtual MessageBoxView GetSentbox(int userId, int afterMessageId, int numberOfRecords, string sortColumn, bool sortAscending, MessageReadStatus readStatus, MessageArchivedStatus archivedStatus) + { + var reader = _dataService.GetSentBoxView(userId, PortalController.GetEffectivePortalId(GetCurrentUserInfo().PortalID), afterMessageId, numberOfRecords, sortColumn, sortAscending); + return new MessageBoxView { Conversations = CBO.FillCollection(reader) }; + } + + #endregion + + #region Counter APIs + + public virtual int CountArchivedMessagesByConversation(int conversationId) + { + return _dataService.CountArchivedMessagesByConversation(conversationId); + } + + public virtual int CountMessagesByConversation(int conversationId) + { + return _dataService.CountMessagesByConversation(conversationId); + } + + public virtual int CountConversations(int userId, int portalId) + { + return _dataService.CountTotalConversations(userId, portalId); + } + + public virtual int CountUnreadMessages(int userId, int portalId) + { + return _dataService.CountNewThreads(userId, portalId); + } + + public virtual int CountSentMessages(int userId, int portalId) + { + return _dataService.CountSentMessages(userId, portalId); + } + + public virtual int CountArchivedMessages(int userId, int portalId) + { + return _dataService.CountArchivedMessages(userId, portalId); + } + + #endregion + + #region Internal Methods + + internal virtual DateTime GetDateTimeNow() + { + return DateTime.UtcNow; + } + + internal virtual UserInfo GetCurrentUserInfo() + { + return UserController.GetCurrentUserInfo(); + } + + internal virtual int GetPortalSettingAsInteger(string key, int portalId, int defaultValue) + { + return PortalController.GetPortalSettingAsInteger(key, portalId, defaultValue); + } + + internal virtual string GetPortalSetting(string settingName, int portalId, string defaultValue) + { + return PortalController.GetPortalSetting(settingName, portalId, defaultValue); + } + + internal virtual bool IsAdminOrHost(UserInfo userInfo) + { + return userInfo.IsSuperUser || userInfo.IsInRole(TestablePortalSettings.Instance.AdministratorRoleName); + } + + internal virtual string InputFilter(string input) + { + var ps = new PortalSecurity(); + return ps.InputFilter(input, PortalSecurity.FilterFlag.NoProfanity); + } + + #endregion + + #region Upgrade APIs + + public void ConvertLegacyMessages(int pageIndex, int pageSize) + { + _dataService.ConvertLegacyMessages(pageIndex, pageSize); + } + + public int CountLegacyMessages() + { + var totalRecords = 0; + var dr = _dataService.CountLegacyMessages(); + + try + { + while (dr.Read()) + { + totalRecords = Convert.ToInt32(dr["TotalRecords"]); + } + } + finally + { + CBO.CloseDataReader(dr, true); + } + + return totalRecords; + } + + #endregion + + #region Queued email API's + + public IList GetNextMessagesForDispatch(Guid schedulerInstance, int batchSize) + { + return CBO.FillCollection(_dataService.GetNextMessagesForDispatch(schedulerInstance, batchSize)); + } + + public virtual void MarkMessageAsDispatched(int messageId, int recipientId) + { + _dataService.MarkMessageAsDispatched(messageId, recipientId); + } + + public virtual void MarkMessageAsSent(int messageId, int recipientId) + { + _dataService.MarkMessageAsSent(messageId, recipientId); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageBoxView.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageBoxView.cs new file mode 100644 index 00000000000..cf0003eff2d --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageBoxView.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Internal.Views +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging.Views + /// Class: MessageBoxView + /// ----------------------------------------------------------------------------- + /// + /// The MessageBoxView contains the View of Inbox, Sent or Archived messages + /// + /// ----------------------------------------------------------------------------- + public class MessageBoxView + { + /// + /// Total Number of Coversations + /// + public int TotalConversations { get; set; } + + /// + /// Total Number of New (Unread) Threads + /// + public int TotalNewThreads { get; set; } + + /// + /// List of Conversations + /// + public List Conversations { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageConversationView.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageConversationView.cs new file mode 100644 index 00000000000..0c406d397c1 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageConversationView.cs @@ -0,0 +1,183 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Data; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Services.Social.Messaging.Internal.Views +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging.Views + /// Class: MessageConversationView + /// ----------------------------------------------------------------------------- + /// + /// The MessageConversationView class contains details of the latest message in a Conversation. + /// + /// ----------------------------------------------------------------------------- + public class MessageConversationView : IHydratable + { + private int _messageID = -1; + private string _displayDate; + private DateTime _createdOnDate; + + /// + /// MessageID - The primary key + /// + public int MessageID + { + get + { + return _messageID; + } + set + { + _messageID = value; + } + } + + /// + /// portalID for the message + /// + public int PortalID { get; set; } + + /// + /// To list for the message. This information is saved for faster display of To list in the message + /// + public string To { get; set; } + + /// + /// Message From + /// + public string From { get; set; } + + /// + /// Message Subject + /// + public string Subject { get; set; } + + /// + /// Message body + /// + public string Body { get; set; } + + /// + /// Conversation ID of the Message. Each message has at least one ConversationId. Subsequent Replies to a Message get same ConversationId + /// + public int ConversationId { get; set; } + + /// + /// ReplyAllAllowed is a bit value to indicate if the reply to the message can be sent to all the recipients or just the sender + /// + + public bool ReplyAllAllowed { get; set; } + + /// + /// The UserID of the sender of the message + /// + public int SenderUserID { get; set; } + + /// + /// A pretty printed string with the time since the message was created + /// + public string DisplayDate + { + get + { + if (string.IsNullOrEmpty(_displayDate)) + { + _displayDate = DateUtils.CalculateDateForDisplay(_createdOnDate); + } + return _displayDate; + } + } + + /// + /// IHydratable.KeyID. + /// + public int KeyID + { + get + { + return MessageID; + } + set + { + MessageID = value; + } + } + + /// + /// RowNumber of the message in a set + /// + public int RowNumber { get; set; } + + /// + /// Count of Total Attachments in a Conversation. It is calculated by adding attachments in all the threads for a given conversation. + /// + public int AttachmentCount { get; set; } + + /// + /// Count of Total New (Unread) Threads in a Conversation. It is calculated by inspecting all the threads in a conversation and counting the ones that are not read yet. + /// + public int NewThreadCount { get; set; } + + /// + /// Count of Total Threads in a Conversation. + /// + public int ThreadCount { get; set; } + + /// + /// The Sender User Profile URL + /// + public string SenderProfileUrl + { + get + { + return Globals.UserProfileURL(SenderUserID); + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + MessageID = Convert.ToInt32(dr["MessageID"]); + To = Null.SetNullString(dr["To"]); + From = Null.SetNullString(dr["From"]); + Subject = Null.SetNullString(dr["Subject"]); + Body = Null.SetNullString(dr["Body"]); + ConversationId = Null.SetNullInteger(dr["ConversationID"]); + ReplyAllAllowed = Null.SetNullBoolean(dr["ReplyAllAllowed"]); + SenderUserID = Convert.ToInt32(dr["SenderUserID"]); + RowNumber = Convert.ToInt32(dr["RowNumber"]); + AttachmentCount = Convert.ToInt32(dr["AttachmentCount"]); + NewThreadCount = Convert.ToInt32(dr["NewThreadCount"]); + ThreadCount = Convert.ToInt32(dr["ThreadCount"]); + _createdOnDate = Null.SetNullDateTime(dr["CreatedOnDate"]); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageFileView.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageFileView.cs new file mode 100644 index 00000000000..5c2c3c1e60b --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageFileView.cs @@ -0,0 +1,76 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +namespace DotNetNuke.Services.Social.Messaging.Internal.Views +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging.Views + /// Class: MessageFileView + /// ----------------------------------------------------------------------------- + /// + /// The MessageFileView class contains details about the attachment + /// + /// ----------------------------------------------------------------------------- + public class MessageFileView + { + private string _size; + + /// + /// The name of the file with extension + /// + public string Name { get; set; } + + /// + /// Size of the File with Unit, e.g. 100 B, 12 KB, 200 MB, etc. + /// + public string Size + { + get { return _size; } + set + { + long bytes; + if (!long.TryParse(value, out bytes)) return; + const int scale = 1024; + var orders = new[] { "GB", "MB", "KB", "B" }; + var max = (long)Math.Pow(scale, orders.Length - 1); + + foreach (var order in orders) + { + if (bytes > max) + { + _size = string.Format("{0:##.##} {1}", decimal.Divide(bytes, max), order); + return; + } + + max /= scale; + } + _size = "0 B"; + } + } + + /// + /// Url of the file to download + /// + public string Url { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadView.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadView.cs new file mode 100644 index 00000000000..fca082e4dd1 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadView.cs @@ -0,0 +1,51 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Internal.Views +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging + /// Class: MessageThreadView + /// ----------------------------------------------------------------------------- + /// + /// The MessageThreadView class contains MessageConversationView and collection of MessageAttachmentView + /// + /// ----------------------------------------------------------------------------- + public class MessageThreadView + { + /// + /// MessageItemView containing consolidated information about the message + /// + public MessageConversationView Conversation { get; set; } + + /// + /// List of attachments + /// + public IList Attachments { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadsView.cs b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadsView.cs new file mode 100644 index 00000000000..0b67c562dcd --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Internal/Views/MessageThreadsView.cs @@ -0,0 +1,62 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Internal.Views +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging + /// Class: MessageThreadsView + /// ----------------------------------------------------------------------------- + /// + /// The MessageThreadsView class contains collection of MessageThreadView and other meta data + /// + /// ----------------------------------------------------------------------------- + public class MessageThreadsView + { + /// + /// Total Number of Threads + /// + public int TotalThreads { get; set; } + + /// + /// Total Number of New (Unread) Threads + /// + public int TotalNewThreads { get; set; } + + /// + /// Total Number of Archived Threads + /// + public int TotalArchivedThreads { get; set; } + + /// + /// List of Conversations + /// + public List Conversations { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Message.cs b/DNN Platform/Library/Services/Social/Messaging/Message.cs new file mode 100644 index 00000000000..a5708708c15 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Message.cs @@ -0,0 +1,167 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging + /// Class: Messages + /// ----------------------------------------------------------------------------- + /// + /// The Message class describes the content of messages sent via the system + /// As messaging is system wide process and there may be no portalID context (e.g. a host messaging "all users") the object does not tie to portalID + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class Message : BaseEntityInfo, IHydratable + { + private int _messageID = -1; + private string _displayDate; + + /// + /// MessageID - The primary key + /// + [XmlAttribute] + public int MessageID + { + get + { + return _messageID; + } + set + { + _messageID = value; + } + } + + /// + /// portalID for the message + /// + [XmlAttribute] + public int PortalID { get; set; } + + /// + /// To list for the message. This information is saved for faster display of To list in the message + /// + [XmlAttribute] + public string To { get; set; } + + /// + /// Message From + /// + [XmlAttribute] + public string From { get; set; } + + /// + /// Message Subject + /// + [XmlAttribute] + public string Subject { get; set; } + + /// + /// Message body + /// + [XmlAttribute] + public string Body { get; set; } + + /// + /// Conversation ID of the Message. Each message has at least one ConversationId. Subsequent Replies to a Message get same ConversationId + /// + [XmlAttribute] + public int ConversationId { get; set; } + + /// + /// ReplyAllAllowed is a bit value to indicate if the reply to the message can be sent to all the recipients or just the sender + /// + [XmlAttribute] + public bool ReplyAllAllowed { get; set; } + + /// + /// The UserID of the sender of the message + /// + [XmlAttribute] + public int SenderUserID { get; set; } + + /// + /// A pretty printed string with the time since the message was created + /// + [XmlAttribute] + public string DisplayDate + { + get + { + if (string.IsNullOrEmpty(_displayDate)) + { + _displayDate = DateUtils.CalculateDateForDisplay(CreatedOnDate); + } + return _displayDate; + } + } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return MessageID; + } + set + { + MessageID = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + MessageID = Convert.ToInt32(dr["MessageID"]); + PortalID = Null.SetNullInteger(dr["PortalId"]); + To = Null.SetNullString(dr["To"]); + From = Null.SetNullString(dr["From"]); + Subject = Null.SetNullString(dr["Subject"]); + Body = Null.SetNullString(dr["Body"]); + ConversationId = Null.SetNullInteger(dr["ConversationID"]); + ReplyAllAllowed = Null.SetNullBoolean(dr["ReplyAllAllowed"]); + SenderUserID = Convert.ToInt32(dr["SenderUserID"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessageArchivedStatus.cs b/DNN Platform/Library/Services/Social/Messaging/MessageArchivedStatus.cs new file mode 100644 index 00000000000..36c18ed09a8 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessageArchivedStatus.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// + /// Archived Status of a Message + /// + public enum MessageArchivedStatus + { + /// + /// Archived Message Status + /// + Archived = 1, + + /// + /// UnArchived Message Status + /// + UnArchived = 0, + + /// + /// Any Message Status - Both Archived and UnArchived + /// + Any = -1 + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessageAttachment.cs b/DNN Platform/Library/Services/Social/Messaging/MessageAttachment.cs new file mode 100644 index 00000000000..797175700f5 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessageAttachment.cs @@ -0,0 +1,109 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging + /// Class: MessageAttachment + /// ----------------------------------------------------------------------------- + /// + /// The MessageAttachment class describes the content attachments associated with a message + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class MessageAttachment : BaseEntityInfo, IHydratable + { + private int _messageattachmentID = -1; + + /// + /// MessageAttachmentID - The primary key + /// + [XmlAttribute] + public int MessageAttachmentID + { + get + { + return _messageattachmentID; + } + set + { + _messageattachmentID = value; + } + } + + /// + /// MessageID of the message that contains this attachment + /// + [XmlAttribute] + public int MessageID { get; set; } + + /// + /// The FileID of the attachment (what will be used against the Files table to provide the attachment) + /// + [XmlAttribute] + public int FileID { get; set; } + + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.MessageAttachmentID; + } + set + { + this.MessageAttachmentID = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.MessageAttachmentID = Convert.ToInt32(dr["MessageAttachmentID"]); + this.MessageID = Convert.ToInt32(dr["MessageID"]); + this.FileID = Convert.ToInt32(dr["FileID"]); + + //add audit column data + FillInternal(dr); + + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessageReadStatus.cs b/DNN Platform/Library/Services/Social/Messaging/MessageReadStatus.cs new file mode 100644 index 00000000000..1248251a9bb --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessageReadStatus.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// + /// Read Status of a Message + /// + public enum MessageReadStatus + { + /// + /// Read Message Status + /// + Read = 1, + + /// + /// UnRead Message Status + /// + UnRead = 0, + + /// + /// Any Message Status - Both Read and UnRead + /// + Any = -1 + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessageRecipient.cs b/DNN Platform/Library/Services/Social/Messaging/MessageRecipient.cs new file mode 100644 index 00000000000..b9cf1ed8e62 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessageRecipient.cs @@ -0,0 +1,123 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Messaging + /// Class: MessageRecipient + /// ----------------------------------------------------------------------------- + /// + /// The MessageRecipient class is used to store the details of all recipients of a particular message + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class MessageRecipient : BaseEntityInfo, IHydratable + { + private int _recipientID = -1; + + /// + /// RecipientID - The primary key + /// + [XmlAttribute] + public int RecipientID + { + get + { + return _recipientID; + } + set + { + _recipientID = value; + } + } + + /// + /// The messageID of who sent the message to this recipient + /// + [XmlAttribute] + public int MessageID { get; set; } + + /// + /// The UserID of the user receiving the message + /// + [XmlAttribute] + public int UserID { get; set; } + + /// + /// Is Message read. True: Yes, False: No. + /// + [XmlAttribute] + public bool Read { get; set; } + + + /// + /// Is Message archived. True: Yes, False: No. + /// + [XmlAttribute] + public bool Archived { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return this.RecipientID; + } + set + { + this.RecipientID = value; + } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + this.RecipientID = Convert.ToInt32(dr["RecipientID"]); + this.MessageID = Convert.ToInt32(dr["MessageID"]); + this.UserID = Convert.ToInt32(dr["UserID"]); + this.Archived = Null.SetNullBoolean(dr["Archived"]); + this.Read = Null.SetNullBoolean(dr["Read"]); + + //add audit column data + FillInternal(dr); + + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessageSentStatus.cs b/DNN Platform/Library/Services/Social/Messaging/MessageSentStatus.cs new file mode 100644 index 00000000000..c45b1e1abeb --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessageSentStatus.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// + /// Sent Status of a Message - Is this a Sent Message or a Received Message + /// + public enum MessageSentStatus + { + /// + /// This Message was Received + /// + Received = 1, + + /// + /// This Message was Sent + /// + Sent = 0, + + /// + /// Any Message Status - Both Sent and Received + /// + Any = -1 + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessagingController.cs b/DNN Platform/Library/Services/Social/Messaging/MessagingController.cs new file mode 100644 index 00000000000..8d377c2022e --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessagingController.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// + /// Business Layer to manage Messaging. Also contains CRUD methods. + /// + public class MessagingController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new MessagingControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/MessagingControllerImpl.cs b/DNN Platform/Library/Services/Social/Messaging/MessagingControllerImpl.cs new file mode 100644 index 00000000000..838beac43be --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/MessagingControllerImpl.cs @@ -0,0 +1,272 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Security; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Social.Messaging.Data; +using DotNetNuke.Services.Social.Messaging.Exceptions; +using DotNetNuke.Services.Social.Messaging.Internal; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging +{ + /// ----------------------------------------------------------------------------- + /// + /// The Controller class for social Messaging + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + internal class MessagingControllerImpl : IMessagingController + { + #region Constants + + internal const int ConstMaxTo = 2000; + internal const int ConstMaxSubject = 400; + internal const int ConstDefaultPageIndex = 0; + internal const int ConstDefaultPageSize = 10; + internal const string ConstSortColumnDate = "CreatedOnDate"; + internal const string ConstSortColumnFrom = "From"; + internal const string ConstSortColumnSubject = "Subject"; + internal const bool ConstAscending = true; + + #endregion + + #region Private Variables + + private readonly IDataService _dataService; + + #endregion + + #region Constructors + + public MessagingControllerImpl() + : this(DataService.Instance) + { + } + + public MessagingControllerImpl(IDataService dataService) + { + //Argument Contract + Requires.NotNull("dataService", dataService); + + _dataService = dataService; + } + + #endregion + + #region Public APIs + + public virtual void SendMessage(Message message, IList roles, IList users, IList fileIDs) + { + SendMessage(message, roles, users, fileIDs, UserController.GetCurrentUserInfo()); + } + + public virtual void SendMessage(Message message, IList roles, IList users, IList fileIDs, UserInfo sender) + { + if (sender == null || sender.UserID <= 0) + { + throw new ArgumentException(Localization.Localization.GetString("MsgSenderRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (message == null) + { + throw new ArgumentException(Localization.Localization.GetString("MsgMessageRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (string.IsNullOrEmpty(message.Subject) && string.IsNullOrEmpty(message.Body)) + { + throw new ArgumentException(Localization.Localization.GetString("MsgSubjectOrBodyRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (roles == null && users == null) + { + throw new ArgumentException(Localization.Localization.GetString("MsgRolesOrUsersRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (!string.IsNullOrEmpty(message.Subject) && message.Subject.Length > ConstMaxSubject) + { + throw new ArgumentException(string.Format(Localization.Localization.GetString("MsgSubjectTooBigError", Localization.Localization.ExceptionsResourceFile), ConstMaxSubject, message.Subject.Length)); + } + + if (roles != null && roles.Count > 0 && !IsAdminOrHost(sender)) + { + if (!roles.All(role => sender.Social.Roles.Any(userRoleInfo => role.RoleID == userRoleInfo.RoleID))) + { + throw new ArgumentException(Localization.Localization.GetString("MsgOnlyHostOrAdminOrUserInGroupCanSendToRoleError", Localization.Localization.ExceptionsResourceFile)); + } + } + + var sbTo = new StringBuilder(); + var replyAllAllowed = true; + if (roles != null) + { + foreach (var role in roles.Where(role => !string.IsNullOrEmpty(role.RoleName))) + { + sbTo.Append(role.RoleName + ","); + replyAllAllowed = false; + } + } + + if (users != null) + { + foreach (var user in users.Where(user => !string.IsNullOrEmpty(user.DisplayName))) sbTo.Append(user.DisplayName + ","); + } + + if (sbTo.Length == 0) + { + throw new ArgumentException(Localization.Localization.GetString("MsgEmptyToListFoundError", Localization.Localization.ExceptionsResourceFile)); + } + + if (sbTo.Length > ConstMaxTo) + { + throw new ArgumentException(string.Format(Localization.Localization.GetString("MsgToListTooBigError", Localization.Localization.ExceptionsResourceFile), ConstMaxTo, sbTo.Length)); + } + + //Cannot send message if within ThrottlingInterval + var waitTime = InternalMessagingController.Instance.WaitTimeForNextMessage(sender); + if (waitTime > 0) + { + var interval = GetPortalSettingAsInteger("MessagingThrottlingInterval", sender.PortalID, Null.NullInteger); + throw new ThrottlingIntervalNotMetException(string.Format(Localization.Localization.GetString("MsgThrottlingIntervalNotMet", Localization.Localization.ExceptionsResourceFile), interval)); + } + + //Cannot have attachments if it's not enabled + if (fileIDs != null && !InternalMessagingController.Instance.AttachmentsAllowed(sender.PortalID)) + { + throw new AttachmentsNotAllowed(Localization.Localization.GetString("MsgAttachmentsNotAllowed", Localization.Localization.ExceptionsResourceFile)); + } + + //Cannot exceed RecipientLimit + var recipientCount = 0; + if (users != null) recipientCount += users.Count; + if (roles != null) recipientCount += roles.Count; + if (recipientCount > InternalMessagingController.Instance.RecipientLimit(sender.PortalID)) + { + throw new RecipientLimitExceededException(Localization.Localization.GetString("MsgRecipientLimitExceeded", Localization.Localization.ExceptionsResourceFile)); + } + + //Profanity Filter + var profanityFilterSetting = GetPortalSetting("MessagingProfanityFilters", sender.PortalID, "NO"); + if (profanityFilterSetting.Equals("YES", StringComparison.InvariantCultureIgnoreCase)) + { + message.Subject = InputFilter(message.Subject); + message.Body = InputFilter(message.Body); + } + + message.To = sbTo.ToString().Trim(','); + message.MessageID = Null.NullInteger; + message.ReplyAllAllowed = replyAllAllowed; + message.SenderUserID = sender.UserID; + message.From = sender.DisplayName; + + message.MessageID = _dataService.SaveMessage(message, PortalController.GetEffectivePortalId(UserController.GetCurrentUserInfo().PortalID), UserController.GetCurrentUserInfo().UserID); + + //associate attachments + if (fileIDs != null) + { + foreach (var attachment in fileIDs.Select(fileId => new MessageAttachment { MessageAttachmentID = Null.NullInteger, FileID = fileId, MessageID = message.MessageID })) + { + _dataService.SaveMessageAttachment(attachment, UserController.GetCurrentUserInfo().UserID); + } + } + + //send message to Roles + if (roles != null) + { + var roleIds = string.Empty; + roleIds = roles + .Select(r => r.RoleID) + .Aggregate(roleIds, (current, roleId) => current + (roleId + ",")) + .Trim(','); + + _dataService.CreateMessageRecipientsForRole(message.MessageID, roleIds, UserController.GetCurrentUserInfo().UserID); + } + + //send message to each User - this should be called after CreateMessageRecipientsForRole. + if (users == null) + { + users = new List(); + } + + foreach (var recipient in from user in users where InternalMessagingController.Instance.GetMessageRecipient(message.MessageID, user.UserID) == null select new MessageRecipient { MessageID = message.MessageID, UserID = user.UserID, Read = false, RecipientID = Null.NullInteger }) + { + _dataService.SaveMessageRecipient(recipient, UserController.GetCurrentUserInfo().UserID); + } + + if (users.All(u => u.UserID != sender.UserID)) + { + //add sender as a recipient of the message + var recipientId = _dataService.SaveMessageRecipient(new MessageRecipient { MessageID = message.MessageID, UserID = sender.UserID, Read = false, RecipientID = Null.NullInteger }, UserController.GetCurrentUserInfo().UserID); + InternalMessagingController.Instance.MarkMessageAsDispatched(message.MessageID, recipientId); + } + + // Mark the conversation as read by the sender of the message. + InternalMessagingController.Instance.MarkRead(message.MessageID, sender.UserID); + } + + #endregion + + #region Internal Methods + + internal virtual UserInfo GetCurrentUserInfo() + { + return UserController.GetCurrentUserInfo(); + } + + internal virtual string GetPortalSetting(string settingName, int portalId, string defaultValue) + { + return PortalController.GetPortalSetting(settingName, portalId, defaultValue); + } + + internal virtual int GetPortalSettingAsInteger(string key, int portalId, int defaultValue) + { + return PortalController.GetPortalSettingAsInteger(key, portalId, defaultValue); + } + + internal virtual string InputFilter(string input) + { + var ps = new PortalSecurity(); + return ps.InputFilter(input, PortalSecurity.FilterFlag.NoProfanity); + } + + internal virtual bool IsAdminOrHost(UserInfo userInfo) + { + return userInfo.IsSuperUser || userInfo.IsInRole(TestablePortalSettings.Instance.AdministratorRoleName); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Messaging/Scheduler/CoreMessagingScheduler.cs b/DNN Platform/Library/Services/Social/Messaging/Scheduler/CoreMessagingScheduler.cs new file mode 100644 index 00000000000..eada4689209 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Messaging/Scheduler/CoreMessagingScheduler.cs @@ -0,0 +1,136 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Scheduling; +using DotNetNuke.Services.Social.Messaging.Internal; + +#endregion + +namespace DotNetNuke.Services.Social.Messaging.Scheduler +{ + public class CoreMessagingScheduler : SchedulerClient + { + private readonly PortalController _pController = new PortalController(); + private readonly UserController _uController = new UserController(); + + public CoreMessagingScheduler(ScheduleHistoryItem objScheduleHistoryItem) + { + ScheduleHistoryItem = objScheduleHistoryItem; + } + + private bool SendEmail(int portalId) + { + return PortalController.GetPortalSetting("MessagingSendEmail", portalId, "YES") == "YES"; + } + + public override void DoWork() + { + try + { + var schedulerInstance = Guid.NewGuid(); + ScheduleHistoryItem.AddLogNote("MessagingScheduler DoWork Starting " + schedulerInstance); + + if (string.IsNullOrEmpty(Host.SMTPServer)) + { + ScheduleHistoryItem.AddLogNote("No SMTP Servers have been configured for this host. Terminating task."); + ScheduleHistoryItem.Succeeded = true; + } + else + { + var messageLeft = true; + var messagesSent = 0; + + while (messageLeft) + { + var batchMessages = InternalMessagingController.Instance.GetNextMessagesForDispatch(schedulerInstance, Host.MessageSchedulerBatchSize); + + if (batchMessages != null && batchMessages.Count > 0) + { + try + { + foreach (var messageRecipient in batchMessages) + { + SendMessage(messageRecipient); + messagesSent = messagesSent + 1; + } + + } + catch (Exception e) + { + Errored(ref e); + } + } + else + { + messageLeft = false; + } + } + + ScheduleHistoryItem.AddLogNote(string.Format("Message Scheduler '{0}' sent a total of {1} message(s)", schedulerInstance, messagesSent)); + ScheduleHistoryItem.Succeeded = true; + } + } + catch (Exception ex) + { + ScheduleHistoryItem.Succeeded = false; + ScheduleHistoryItem.AddLogNote("MessagingScheduler Failed: " + ex); + Errored(ref ex); + } + } + + private void SendMessage(MessageRecipient messageRecipient) + { + //todo: check if host user can send to multiple portals... + var messageDetails = InternalMessagingController.Instance.GetMessage(messageRecipient.MessageID); + + if (!SendEmail(messageDetails.PortalID)) + { + InternalMessagingController.Instance.MarkMessageAsSent(messageRecipient.MessageID, messageRecipient.RecipientID); + return; + } + + var fromAddress = _pController.GetPortal(messageDetails.PortalID).Email; + var toAddress = _uController.GetUser(messageDetails.PortalID, messageRecipient.UserID).Email; + + var sender = _uController.GetUser(messageDetails.PortalID, messageDetails.SenderUserID).DisplayName; + if (string.IsNullOrEmpty(sender)) + sender = _pController.GetPortal(messageDetails.PortalID).PortalName; + var senderAddress = sender + "< " + fromAddress + ">"; + var subject = string.Format(Localization.Localization.GetString("EMAIL_SUBJECT_FORMAT", + Localization.Localization.GlobalResourceFile), sender); + + var body = string.Format(Localization.Localization.GetString("EMAIL_BODY_FORMAT", + Localization.Localization.GlobalResourceFile), messageDetails.Subject, messageDetails.Body); + + Mail.Mail.SendEmail(fromAddress, senderAddress, toAddress, subject, body); + + InternalMessagingController.Instance.MarkMessageAsDispatched(messageRecipient.MessageID, messageRecipient.RecipientID); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Social/Notifications/Data/DataService.cs b/DNN Platform/Library/Services/Social/Notifications/Data/DataService.cs new file mode 100644 index 00000000000..349bd9e797c --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/Data/DataService.cs @@ -0,0 +1,144 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; + +using DotNetNuke.ComponentModel; +using DotNetNuke.Data; +using DotNetNuke.Entities.Users; + +namespace DotNetNuke.Services.Social.Notifications.Data +{ + internal class DataService : ComponentBase, IDataService + { + private readonly DataProvider _provider = DataProvider.Instance(); + private const string Prefix = "CoreMessaging_"; + + #region Private Methods + + private static string GetFullyQualifiedName(string procedureName) + { + return Prefix + procedureName; + } + + #endregion + + #region NotificationTypes CRUD + + public int CreateNotificationType(string name, string description, int timeToLive, int desktopModuleId, int createUpdateUserId) + { + return _provider.ExecuteScalar(GetFullyQualifiedName("CreateNotificationType"), name, _provider.GetNull(description), _provider.GetNull(timeToLive), _provider.GetNull(desktopModuleId), createUpdateUserId); + } + + public void DeleteNotificationType(int notificationTypeId) + { + _provider.ExecuteNonQuery(GetFullyQualifiedName("DeleteNotificationType"), notificationTypeId); + } + + public IDataReader GetNotificationType(int notificationTypeId) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationType"), notificationTypeId); + } + + public IDataReader GetNotificationTypeByName(string name) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationTypeByName"), name); + } + + #endregion + + #region NotificationTypeActions CRUD + + public int AddNotificationTypeAction(int notificationTypeId, string nameResourceKey, string descriptionResourceKey, string confirmResourceKey, string apiCall, int createdByUserId) + { + return _provider.ExecuteScalar(GetFullyQualifiedName("AddNotificationTypeAction"), notificationTypeId, nameResourceKey, _provider.GetNull(descriptionResourceKey), _provider.GetNull(confirmResourceKey), apiCall, createdByUserId); + } + + public void DeleteNotificationTypeAction(int notificationTypeActionId) + { + _provider.ExecuteNonQuery(GetFullyQualifiedName("DeleteNotificationTypeAction"), notificationTypeActionId); + } + + public IDataReader GetNotificationTypeAction(int notificationTypeActionId) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationTypeAction"), notificationTypeActionId); + } + + public IDataReader GetNotificationTypeActionByName(int notificationTypeId, string name) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationTypeActionByName"), notificationTypeId, name); + } + + public IDataReader GetNotificationTypeActions(int notificationTypeId) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationTypeActions"), notificationTypeId); + } + + #endregion + + #region Notifications Public Methods + + public int SendNotification(Notification notification, int portalId) + { + var createdByUserId = UserController.GetCurrentUserInfo().UserID; + return _provider.ExecuteScalar(GetFullyQualifiedName("SendNotification"), + notification.NotificationTypeID, + portalId, + notification.To, + notification.From, + notification.Subject, + notification.Body, + notification.SenderUserID, + createdByUserId, + _provider.GetNull(notification.ExpirationDate), + notification.IncludeDismissAction, + notification.Context); + } + + public void DeleteNotification(int notificationId) + { + _provider.ExecuteNonQuery(GetFullyQualifiedName("DeleteNotification"), notificationId); + } + + public int CountNotifications(int userId, int portalId) + { + return _provider.ExecuteScalar(GetFullyQualifiedName("CountNotifications"), userId, portalId); + } + + public IDataReader GetNotifications(int userId, int portalId, int afterNotificationId, int numberOfRecords) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotifications"), userId, portalId, afterNotificationId, numberOfRecords); + } + + public IDataReader GetNotification(int notificationId) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotification"), notificationId); + } + + public IDataReader GetNotificationByContext(int notificationTypeId, string context) + { + return _provider.ExecuteReader(GetFullyQualifiedName("GetNotificationByContext"), notificationTypeId, context); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/Data/IDataService.cs b/DNN Platform/Library/Services/Social/Notifications/Data/IDataService.cs new file mode 100644 index 00000000000..d5a1e7137bb --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/Data/IDataService.cs @@ -0,0 +1,59 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; + +namespace DotNetNuke.Services.Social.Notifications.Data +{ + public interface IDataService + { + #region NotificationTypes CRUD + + int CreateNotificationType(string name, string description, int timeToLive, int desktopModuleId, int createUpdateUserId); + void DeleteNotificationType(int notificationTypeId); + IDataReader GetNotificationType(int notificationTypeId); + IDataReader GetNotificationTypeByName(string name); + + #endregion + + #region NotificationTypeActions CRUD + + int AddNotificationTypeAction(int notificationTypeId, string nameResourceKey, string descriptionResourceKey, string confirmResourceKey, string apiCall, int createdByUserId); + void DeleteNotificationTypeAction(int notificationTypeActionId); + IDataReader GetNotificationTypeAction(int notificationTypeActionId); + IDataReader GetNotificationTypeActionByName(int notificationTypeId, string name); + IDataReader GetNotificationTypeActions(int notificationTypeId); + + #endregion + + #region Notifications + + int SendNotification(Notification notification, int portalId); + void DeleteNotification(int notificationId); + int CountNotifications(int userId, int portalId); + IDataReader GetNotifications(int userId, int portalId, int afterNotificationId, int numberOfRecords); + IDataReader GetNotification(int notificationId); + IDataReader GetNotificationByContext(int notificationTypeId, string context); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/INotificationsController.cs b/DNN Platform/Library/Services/Social/Notifications/INotificationsController.cs new file mode 100644 index 00000000000..624399adf1c --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/INotificationsController.cs @@ -0,0 +1,183 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Roles; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// + /// Defines the methods to work with Notifications, NotificationTypes, NotificationTypeActions and NotificationActions. + /// + public interface INotificationsController + { + #region NotificationTypes Methods + + /// + /// Creates a new notification type. + /// + /// + void CreateNotificationType(NotificationType notificationType); + + /// + /// Deletes an existing notification type. + /// + /// The notification type identifier. + void DeleteNotificationType(int notificationTypeId); + + /// + /// Gets a notification type by identifier. + /// + /// The notification type identifier. + /// The notification type with the provided identifier. + NotificationType GetNotificationType(int notificationTypeId); + + /// + /// Gets a notification type by name. + /// + /// The notification type name. + /// The notification type with the provided name. + NotificationType GetNotificationType(string name); + + #endregion + + #region NotificationTypeActions Methods + + /// + /// Deletes an existing notification type action. + /// + /// The notification type action identifier. + void DeleteNotificationTypeAction(int notificationTypeActionId); + + /// + /// Gets a notification type action by identifier. + /// + /// The notification type action identifier. + /// The notification type action with the provided identifier. + NotificationTypeAction GetNotificationTypeAction(int notificationTypeActionId); + + /// + /// Gets a notification type action by notification type and name. + /// + /// The notification type identifier. + /// The notification type action name. + /// The notification type action with the provided notification type and name. + NotificationTypeAction GetNotificationTypeAction(int notificationTypeId, string name); + + /// + /// Gets the list of notification type actions for the provided notification type. + /// + /// The notification type identifier. + /// An ordered list of notification type actions for the provided notification type. + IList GetNotificationTypeActions(int notificationTypeId); + + /// + /// Set the actions for a NotificationType + /// + /// The actions + /// Id of the notification type + void SetNotificationTypeActions(IList actions, int notificationTypeId); + + #endregion + + #region Notifications Methods + + /// + /// Creates a new notification and sets is sender as the portal administrator. + /// + /// The notification + /// The portalId + /// The list of roles to send the notification to. Leave it as null to send only to individual users. + /// The list of users to send the notification to. Leave it as null to send only to roles. + /// The new notification. + void SendNotification(Notification notification, int portalId, IList roles, IList users); + + /// + /// Counts the notifications sent to the provided user in the specified portal. + /// + /// The user identifier. + /// The portal identifier. + /// The number of notifications sent to the provided user in the specified portal. + int CountNotifications(int userId, int portalId); + + /// + /// Gets a list of notifications sent to the provided user in the specified portal. + /// + /// The user identifier. + /// The portal identifier. + /// The notification identifier of the last notification displayed. Use -1 to start from the beggining of the list. + /// The number of results to retrieve. + /// The filtered list of notifications sent to the provided user in the specified portal. + /// For example, if we have the following ordered notification identifiers: 4, 6, 2, 12, 45, and we pass 2 as the afterNotificationId and 2 as the numberOfRecords, the method will return the notifications 12 and 45. + IList GetNotifications(int userId, int portalId, int afterNotificationId, int numberOfRecords); + + /// + /// Deletes an existing notification. + /// + /// It does not delete NotificationRecipient. + /// The notification identifier. + void DeleteNotification(int notificationId); + + /// + /// Deletes an individual notification recipient. + /// + /// It also deletes the notification if there are no more recipients. + /// The notification identifier. + /// The user identifier. + void DeleteNotificationRecipient(int notificationId, int userId); + + /// + /// Deletes all NotificationRecipient for the NotificationId. + /// + /// It also deletes the notification. + /// The notification identifier. + void DeleteAllNotificationRecipients(int notificationId); + + /// + /// Deletes an individual notification recipient based on NotificationTypeId, Context and UserId. + /// + /// It also deletes the notification if there are no more recipients. + /// Id of the notification type + /// Context set by creator of the notification. + /// The user identifier. + void DeleteNotificationRecipient(int notificationTypeId, string context, int userId); + + /// + /// Get a Notification + /// + /// The notificationId + /// A notification + Notification GetNotification(int notificationId); + + /// + /// Get a Notification by NotificationTypeId and Context + /// + /// Id of the notification type + /// Context set by creator of the notification. + /// The filtered list of notifications sent to the provided user in the specified portal. + IList GetNotificationByContext(int notificationTypeId, string context); + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/Notification.cs b/DNN Platform/Library/Services/Social/Notifications/Notification.cs new file mode 100644 index 00000000000..42a27343844 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/Notification.cs @@ -0,0 +1,170 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Entities.Notifications + /// Class: Notification + /// ----------------------------------------------------------------------------- + /// + /// The Notification class describes the a notification received by a user as a consecuence of an action + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class Notification : BaseEntityInfo, IHydratable + { + private int _notificationID = -1; + private string _displayDate; + + /// + /// NotificationID - The primary key + /// + [XmlAttribute] + public int NotificationID + { + get + { + return _notificationID; + } + set + { + _notificationID = value; + } + } + + /// + /// The message type identifier. + /// + [XmlAttribute] + public int NotificationTypeID { get; set; } + + /// + /// To list for the message. This information is saved for faster display of To list in the message + /// + [XmlAttribute] + public string To { get; set; } + + /// + /// Message From + /// + [XmlAttribute] + public string From { get; set; } + + /// + /// Message Subject + /// + [XmlAttribute] + public string Subject { get; set; } + + /// + /// Message body + /// + [XmlAttribute] + public string Body { get; set; } + + /// + /// Context set by creator of the notification + /// + [XmlAttribute] + public string Context { get; set; } + + /// + /// The UserID of the sender of the message + /// + [XmlAttribute] + public int SenderUserID { get; set; } + + /// + /// A pretty printed string with the time since the message was created + /// + [XmlAttribute] + public string DisplayDate + { + get + { + if (string.IsNullOrEmpty(_displayDate)) + { + _displayDate = DateUtils.CalculateDateForDisplay(CreatedOnDate); + } + return _displayDate; + } + } + + /// + /// For notifications, this field indicates when it has to be removed (or not displayed) + /// + [XmlAttribute] + public DateTime ExpirationDate { get; set; } + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get + { + return NotificationID; + } + set + { + NotificationID = value; + } + } + + /// + /// Should this notification support a dismiss action + /// + [XmlAttribute] + public bool IncludeDismissAction { get; set; } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + NotificationID = Convert.ToInt32(dr["MessageID"]); + NotificationTypeID = Convert.ToInt32(dr["NotificationTypeID"]); + To = Null.SetNullString(dr["To"]); + From = Null.SetNullString(dr["From"]); + Subject = Null.SetNullString(dr["Subject"]); + Body = Null.SetNullString(dr["Body"]); + Context = Null.SetNullString(dr["Context"]); + SenderUserID = Convert.ToInt32(dr["SenderUserID"]); + ExpirationDate = Null.SetNullDateTime(dr["ExpirationDate"]); + IncludeDismissAction = Null.SetNullBoolean(dr["IncludeDismissAction"]); + + //add audit column data + FillInternal(dr); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/NotificationType.cs b/DNN Platform/Library/Services/Social/Notifications/NotificationType.cs new file mode 100644 index 00000000000..7dcbc87f80b --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/NotificationType.cs @@ -0,0 +1,138 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Services.Social.Notifications + /// Class: NotificationType + /// ----------------------------------------------------------------------------- + /// + /// The NotificationType class describes a single notification type that can be associated to a message. + /// This message could be a notification or a standard message sent between users. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class NotificationType : BaseEntityInfo, IHydratable + { + private int _notificationTypeId = -1; + private int _desktopModuleId = -1; + + /// + /// The notification type identifier. + /// + [XmlAttribute] + public int NotificationTypeId + { + get + { + return _notificationTypeId; + } + set + { + _notificationTypeId = value; + } + } + + /// + /// The notification type name. + /// + [XmlAttribute] + public string Name { get; set; } + + /// + /// The notification type description. + /// + [XmlAttribute] + public string Description { get; set; } + + /// + /// The amount of time to add to the creation date of the message to calculate the expiration date. + /// + /// + /// Minutes precision. Seconds won't be considered. + /// + [XmlAttribute] + public TimeSpan TimeToLive { get; set; } + + /// + /// If the message type is related to a specific module, this field is used to localize actions by getting the resource file from the module folder. + /// + /// + /// The resource file used will be SharedResources by convention. + /// + [XmlAttribute] + public int DesktopModuleId + { + get + { + return _desktopModuleId; + } + set + { + _desktopModuleId = value; + } + } + + #region Implementation of IHydratable + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get { return NotificationTypeId; } + set { NotificationTypeId = value; } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + NotificationTypeId = Convert.ToInt32(dr["NotificationTypeID"]); + Name = dr["Name"].ToString(); + Description = Null.SetNullString(dr["Description"]); + var timeToLive = Null.SetNullInteger(dr["TTL"]); + if (timeToLive != Null.NullInteger) + { + TimeToLive = new TimeSpan(0, timeToLive, 0); + } + DesktopModuleId = Null.SetNullInteger(dr["DesktopModuleID"]); + + //add audit column data + FillInternal(dr); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/NotificationTypeAction.cs b/DNN Platform/Library/Services/Social/Notifications/NotificationTypeAction.cs new file mode 100644 index 00000000000..b2a7e46425a --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/NotificationTypeAction.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.Services.Social.Notifications + /// Class: NotificationTypeAction + /// ----------------------------------------------------------------------------- + /// + /// The NotificationTypeAction class describes a single notification type action that can be associated to a message. + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class NotificationTypeAction : BaseEntityInfo, IHydratable + { + private int _notificationTypeActionId = -1; + + /// + /// The notification type action identifier. + /// + [XmlAttribute] + public int NotificationTypeActionId + { + get + { + return _notificationTypeActionId; + } + set + { + _notificationTypeActionId = value; + } + } + + /// + /// The notification type identifier. + /// + [XmlAttribute] + public int NotificationTypeId { get; set; } + + /// + /// The notification type action name resource key. + /// + [XmlAttribute] + public string NameResourceKey { get; set; } + + /// + /// The notification type action description resource key. + /// + [XmlAttribute] + public string DescriptionResourceKey { get; set; } + + /// + /// The notification type action confirmation resource key. + /// + [XmlAttribute] + public string ConfirmResourceKey { get; set; } + + /// + /// The notification type action order to be used while displaying the list of available actions. + /// + [XmlAttribute] + public int Order { get; set; } + + /// + /// The Service Framework URL to be called when the action is performed. + /// + [XmlAttribute] + public string APICall { get; set; } + + #region Implementation of IHydratable + + /// + /// IHydratable.KeyID. + /// + [XmlIgnore] + public int KeyID + { + get { return NotificationTypeActionId; } + set { NotificationTypeActionId = value; } + } + + /// + /// Fill the object with data from database. + /// + /// the data reader. + public void Fill(IDataReader dr) + { + NotificationTypeActionId = Convert.ToInt32(dr["NotificationTypeActionID"]); + NotificationTypeId = Convert.ToInt32(dr["NotificationTypeID"]); + NameResourceKey = dr["NameResourceKey"].ToString(); + DescriptionResourceKey = Null.SetNullString(dr["DescriptionResourceKey"]); + ConfirmResourceKey = Null.SetNullString(dr["ConfirmResourceKey"]); + Order = Convert.ToInt32(dr["Order"]); + APICall = dr["APICall"].ToString(); + + //add audit column data + FillInternal(dr); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/NotificationsController.cs b/DNN Platform/Library/Services/Social/Notifications/NotificationsController.cs new file mode 100644 index 00000000000..8ca5f0e27e8 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/NotificationsController.cs @@ -0,0 +1,38 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +using DotNetNuke.Framework; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// + /// Business Layer to manage Notifications. Also contains CRUD methods. + /// + public class NotificationsController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new NotificationsControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Social/Notifications/NotificationsControllerImpl.cs b/DNN Platform/Library/Services/Social/Notifications/NotificationsControllerImpl.cs new file mode 100644 index 00000000000..7ed93fc40e1 --- /dev/null +++ b/DNN Platform/Library/Services/Social/Notifications/NotificationsControllerImpl.cs @@ -0,0 +1,423 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Social.Messaging; +using DotNetNuke.Services.Social.Messaging.Exceptions; +using DotNetNuke.Services.Social.Messaging.Internal; +using DotNetNuke.Services.Social.Notifications.Data; + +namespace DotNetNuke.Services.Social.Notifications +{ + /// + /// Provides the methods to work with Notifications, NotificationTypes, NotificationTypeActions and NotificationActions. + /// + internal class NotificationsControllerImpl : INotificationsController + { + #region Constants + + internal const int ConstMaxSubject = 400; + internal const int ConstMaxTo = 2000; + + #endregion + + #region Private Variables + + private readonly IDataService _dataService; + private readonly Messaging.Data.IDataService _messagingDataService; + + #endregion + + #region Constructors + + public NotificationsControllerImpl() + : this(DataService.Instance, Messaging.Data.DataService.Instance) + { + } + + public NotificationsControllerImpl(IDataService dataService, Messaging.Data.IDataService messagingDataService) + { + Requires.NotNull("dataService", dataService); + Requires.NotNull("messagingDataService", messagingDataService); + + _dataService = dataService; + _messagingDataService = messagingDataService; + } + + #endregion + + #region Public API + + public void SetNotificationTypeActions(IList actions, int notificationTypeId) + { + Requires.NotNull("actions", actions); + + if (!actions.Any()) + { + throw new ArgumentException("Actions must contain at least one item."); + } + + if (actions.Any(x => string.IsNullOrEmpty(x.APICall))) + { + throw new ArgumentException("All actions must specify an APICall"); + } + + if (actions.Any(x => string.IsNullOrEmpty(x.NameResourceKey))) + { + throw new ArgumentException("All actions must specify a NameResourceKey"); + } + + foreach (var action in actions) + { + action.NotificationTypeActionId = _dataService.AddNotificationTypeAction(notificationTypeId, + action.NameResourceKey, + action.DescriptionResourceKey, + action.ConfirmResourceKey, + action.APICall, + GetCurrentUserId()); + action.NotificationTypeId = notificationTypeId; + } + } + + public virtual int CountNotifications(int userId, int portalId) + { + return _dataService.CountNotifications(userId, portalId); + } + + public virtual void SendNotification(Notification notification, int portalId, IList roles, IList users) + { + Requires.NotNull("notification", notification); + + var pid = portalId; + if (PortalController.IsMemberOfPortalGroup(portalId)) + { + pid = PortalController.GetEffectivePortalId(portalId); + } + + if (notification.SenderUserID < 1) + { + notification.SenderUserID = GetAdminUser().UserID; + } + + if (string.IsNullOrEmpty(notification.Subject) && string.IsNullOrEmpty(notification.Body)) + { + throw new ArgumentException(Localization.Localization.GetString("MsgSubjectOrBodyRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (roles == null && users == null) + { + throw new ArgumentException(Localization.Localization.GetString("MsgRolesOrUsersRequiredError", Localization.Localization.ExceptionsResourceFile)); + } + + if (!string.IsNullOrEmpty(notification.Subject) && notification.Subject.Length > ConstMaxSubject) + { + throw new ArgumentException(string.Format(Localization.Localization.GetString("MsgSubjectTooBigError", Localization.Localization.ExceptionsResourceFile), ConstMaxSubject, notification.Subject.Length)); + } + + var sbTo = new StringBuilder(); + if (roles != null) + { + foreach (var role in roles.Where(role => !string.IsNullOrEmpty(role.RoleName))) + { + sbTo.Append(role.RoleName + ","); + } + } + + if (users != null) + { + foreach (var user in users.Where(user => !string.IsNullOrEmpty(user.DisplayName))) sbTo.Append(user.DisplayName + ","); + } + + if (sbTo.Length == 0) + { + throw new ArgumentException(Localization.Localization.GetString("MsgEmptyToListFoundError", Localization.Localization.ExceptionsResourceFile)); + } + + if (sbTo.Length > ConstMaxTo) + { + throw new ArgumentException(string.Format(Localization.Localization.GetString("MsgToListTooBigError", Localization.Localization.ExceptionsResourceFile), ConstMaxTo, sbTo.Length)); + } + + //Cannot exceed RecipientLimit + var recipientCount = 0; + if (users != null) recipientCount += users.Count; + if (roles != null) recipientCount += roles.Count; + if (recipientCount > InternalMessagingController.Instance.RecipientLimit(pid)) + { + throw new RecipientLimitExceededException(Localization.Localization.GetString("MsgRecipientLimitExceeded", Localization.Localization.ExceptionsResourceFile)); + } + + //Profanity Filter + var profanityFilterSetting = GetPortalSetting("MessagingProfanityFilters", pid, "NO"); + if (profanityFilterSetting.Equals("YES", StringComparison.InvariantCultureIgnoreCase)) + { + notification.Subject = InputFilter(notification.Subject); + notification.Body = InputFilter(notification.Body); + } + + notification.To = sbTo.ToString().Trim(','); + if (notification.ExpirationDate != new DateTime()) + { + notification.ExpirationDate = GetExpirationDate(notification.NotificationTypeID); + } + + notification.NotificationID = _dataService.SendNotification(notification, pid); + + //send message to Roles + if (roles != null) + { + var roleIds = string.Empty; + roleIds = roles + .Select(r => r.RoleID) + .Aggregate(roleIds, (current, roleId) => current + (roleId + ",")) + .Trim(','); + + _messagingDataService.CreateMessageRecipientsForRole( + notification.NotificationID, + roleIds, + UserController.GetCurrentUserInfo().UserID); + } + + //send message to each User - this should be called after CreateMessageRecipientsForRole. + if (users == null) + { + users = new List(); + } + + var recipients = from user in users + where InternalMessagingController.Instance.GetMessageRecipient(notification.NotificationID, user.UserID) == null + select new MessageRecipient + { + MessageID = notification.NotificationID, + UserID = user.UserID, + Read = false, + RecipientID = Null.NullInteger + }; + + foreach (var recipient in recipients) + { + _messagingDataService.SaveMessageRecipient( + recipient, + UserController.GetCurrentUserInfo().UserID); + } + } + + public void CreateNotificationType(NotificationType notificationType) + { + Requires.NotNull("notificationType", notificationType); + Requires.NotNullOrEmpty("notificationType.Name", notificationType.Name); + + if (notificationType.DesktopModuleId <= 0) + { + notificationType.DesktopModuleId = Null.NullInteger; + } + + notificationType.NotificationTypeId = _dataService.CreateNotificationType(notificationType.Name, + notificationType.Description, + (int)notificationType.TimeToLive.TotalMinutes == 0 ? Null.NullInteger : (int)notificationType.TimeToLive.TotalMinutes, + notificationType.DesktopModuleId, + GetCurrentUserId()); + } + + public virtual void DeleteNotification(int notificationId) + { + _dataService.DeleteNotification(notificationId); + } + + public virtual void DeleteNotificationRecipient(int notificationId, int userId) + { + InternalMessagingController.Instance.DeleteMessageRecipient(notificationId, userId); + var recipients = InternalMessagingController.Instance.GetMessageRecipients(notificationId); + if (recipients.Count == 0) + { + DeleteNotification(notificationId); + } + } + + public virtual void DeleteAllNotificationRecipients(int notificationId) + { + foreach (var recipient in InternalMessagingController.Instance.GetMessageRecipients(notificationId)) + { + DeleteNotificationRecipient(notificationId, recipient.UserID); + } + } + + public virtual void DeleteNotificationRecipient(int notificationTypeId, string context, int userId) + { + foreach (var notification in GetNotificationByContext(notificationTypeId, context)) + { + DeleteNotificationRecipient(notification.NotificationID, userId); + } + } + + public Notification GetNotification(int notificationId) + { + return CBO.FillObject(_dataService.GetNotification(notificationId)); + } + + public virtual IList GetNotificationByContext(int notificationTypeId, string context) + { + return CBO.FillCollection(_dataService.GetNotificationByContext(notificationTypeId, context)); + } + + public virtual void DeleteNotificationType(int notificationTypeId) + { + _dataService.DeleteNotificationType(notificationTypeId); + + RemoveNotificationTypeCache(); + } + + public virtual void DeleteNotificationTypeAction(int notificationTypeActionId) + { + _dataService.DeleteNotificationTypeAction(notificationTypeActionId); + + RemoveNotificationTypeActionCache(); + } + + public virtual IList GetNotifications(int userId, int portalId, int afterNotificationId, int numberOfRecords) + { + var pid = portalId; + if (PortalController.IsMemberOfPortalGroup(portalId)) + { + pid = PortalController.GetEffectivePortalId(portalId); + } + return CBO.FillCollection(_dataService.GetNotifications(userId, pid, afterNotificationId, numberOfRecords)); + } + + public virtual NotificationType GetNotificationType(int notificationTypeId) + { + var notificationTypeCacheKey = string.Format(DataCache.NotificationTypesCacheKey, notificationTypeId); + var cacheItemArgs = new CacheItemArgs(notificationTypeCacheKey, DataCache.NotificationTypesTimeOut, DataCache.NotificationTypesCachePriority, notificationTypeId); + return CBO.GetCachedObject(cacheItemArgs, GetNotificationTypeCallBack); + } + + public virtual NotificationType GetNotificationType(string name) + { + Requires.NotNullOrEmpty("name", name); + + var notificationTypeCacheKey = string.Format(DataCache.NotificationTypesCacheKey, name); + var cacheItemArgs = new CacheItemArgs(notificationTypeCacheKey, DataCache.NotificationTypesTimeOut, DataCache.NotificationTypesCachePriority, name); + return CBO.GetCachedObject(cacheItemArgs, GetNotificationTypeByNameCallBack); + } + + public virtual NotificationTypeAction GetNotificationTypeAction(int notificationTypeActionId) + { + var notificationTypeActionCacheKey = string.Format(DataCache.NotificationTypeActionsCacheKey, notificationTypeActionId); + var cacheItemArgs = new CacheItemArgs(notificationTypeActionCacheKey, DataCache.NotificationTypeActionsTimeOut, DataCache.NotificationTypeActionsPriority, notificationTypeActionId); + return CBO.GetCachedObject(cacheItemArgs, GetNotificationTypeActionCallBack); + } + + public virtual NotificationTypeAction GetNotificationTypeAction(int notificationTypeId, string name) + { + Requires.NotNullOrEmpty("name", name); + + var notificationTypeActionCacheKey = string.Format(DataCache.NotificationTypeActionsByNameCacheKey, notificationTypeId, name); + var cacheItemArgs = new CacheItemArgs(notificationTypeActionCacheKey, DataCache.NotificationTypeActionsTimeOut, DataCache.NotificationTypeActionsPriority, notificationTypeId, name); + return CBO.GetCachedObject(cacheItemArgs, GetNotificationTypeActionByNameCallBack); + } + + public virtual IList GetNotificationTypeActions(int notificationTypeId) + { + return CBO.FillCollection(_dataService.GetNotificationTypeActions(notificationTypeId)); + } + + #endregion + + #region Internal Methods + + internal virtual UserInfo GetAdminUser() + { + return UserController.GetUserById(PortalSettings.Current.PortalId, PortalSettings.Current.AdministratorId); + } + + internal virtual int GetCurrentUserId() + { + return UserController.GetCurrentUserInfo().UserID; + } + + internal virtual DateTime GetExpirationDate(int notificationTypeId) + { + var notificationType = GetNotificationType(notificationTypeId); + + return notificationType.TimeToLive.TotalMinutes > 0 + ? DateTime.UtcNow.AddMinutes(notificationType.TimeToLive.TotalMinutes) + : DateTime.MinValue; + } + + internal virtual object GetNotificationTypeActionCallBack(CacheItemArgs cacheItemArgs) + { + var notificationTypeActionId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillObject(_dataService.GetNotificationTypeAction(notificationTypeActionId)); + } + + internal virtual object GetNotificationTypeActionByNameCallBack(CacheItemArgs cacheItemArgs) + { + var notificationTypeId = (int)cacheItemArgs.ParamList[0]; + var name = cacheItemArgs.ParamList[1].ToString(); + return CBO.FillObject(_dataService.GetNotificationTypeActionByName(notificationTypeId, name)); + } + + internal virtual object GetNotificationTypeByNameCallBack(CacheItemArgs cacheItemArgs) + { + var notificationName = cacheItemArgs.ParamList[0].ToString(); + return CBO.FillObject(_dataService.GetNotificationTypeByName(notificationName)); + } + + internal virtual object GetNotificationTypeCallBack(CacheItemArgs cacheItemArgs) + { + var notificationTypeId = (int)cacheItemArgs.ParamList[0]; + return CBO.FillObject(_dataService.GetNotificationType(notificationTypeId)); + } + + internal virtual string GetPortalSetting(string settingName, int portalId, string defaultValue) + { + return PortalController.GetPortalSetting(settingName, portalId, defaultValue); + } + + internal virtual string InputFilter(string input) + { + var ps = new PortalSecurity(); + return ps.InputFilter(input, PortalSecurity.FilterFlag.NoProfanity); + } + + internal virtual void RemoveNotificationTypeActionCache() + { + DataCache.ClearCache("NotificationTypeActions:"); + } + + internal virtual void RemoveNotificationTypeCache() + { + DataCache.ClearCache("NotificationTypes:"); + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Syndication/RssHandler.cs b/DNN Platform/Library/Services/Syndication/RssHandler.cs new file mode 100644 index 00000000000..4068936df50 --- /dev/null +++ b/DNN Platform/Library/Services/Syndication/RssHandler.cs @@ -0,0 +1,156 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Search; +using DotNetNuke.Services.Search.Controllers; +using DotNetNuke.Services.Search.Entities; +using DotNetNuke.Services.Search.Internals; + +#endregion + +namespace DotNetNuke.Services.Syndication +{ + public class RssHandler : SyndicationHandlerBase + { + /// + /// This method + /// + /// + /// + /// + protected override void PopulateChannel(string channelName, string userName) + { + var objModules = new ModuleController(); + ModuleInfo objModule; + if (Request == null || Settings == null || Settings.ActiveTab == null || ModuleId == Null.NullInteger) + { + return; + } + Channel["title"] = Settings.PortalName; + Channel["link"] = Globals.AddHTTP(Globals.GetDomainName(Request)); + if (!String.IsNullOrEmpty(Settings.Description)) + { + Channel["description"] = Settings.Description; + } + else + { + Channel["description"] = Settings.PortalName; + } + Channel["language"] = Settings.DefaultLanguage; + Channel["copyright"] = !string.IsNullOrEmpty(Settings.FooterText) ? Settings.FooterText.Replace("[year]", DateTime.Now.Year.ToString()) : string.Empty; + Channel["webMaster"] = Settings.Email; + + IList searchResults = null; + var query = new SearchQuery(); + query.PortalIds = new[] { Settings.PortalId }; + query.TabId = TabId; + query.ModuleId = ModuleId; + query.SearchTypeIds = new[] { SearchHelper.Instance.GetSearchTypeByName("module").SearchTypeId }; + + try + { + searchResults = SearchController.Instance.ModuleSearch(query).Results; + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + if (searchResults != null) + { + foreach (var result in searchResults) + { + if (!result.UniqueKey.StartsWith(Constants.ModuleMetaDataPrefixTag) && TabPermissionController.CanViewPage()) + { + if (Settings.ActiveTab.StartDate < DateTime.Now && Settings.ActiveTab.EndDate > DateTime.Now) + { + objModule = objModules.GetModule(result.ModuleId, query.TabId); + if (objModule != null && objModule.DisplaySyndicate && objModule.IsDeleted == false) + { + if (ModulePermissionController.CanViewModule(objModule)) + { + if (Convert.ToDateTime(objModule.StartDate == Null.NullDate ? DateTime.MinValue : objModule.StartDate) < DateTime.Now && + Convert.ToDateTime(objModule.EndDate == Null.NullDate ? DateTime.MaxValue : objModule.EndDate) > DateTime.Now) + { + Channel.Items.Add(GetRssItem(result)); + } + } + } + } + } + } + } + } + + /// + /// Creates an RSS Item + /// + /// + /// + /// + private GenericRssElement GetRssItem(SearchResult searchResult) + { + var item = new GenericRssElement(); + var url = searchResult.Url; + if (url.Trim() == "") + { + url = Globals.NavigateURL(searchResult.TabId); + if (url.ToLower().IndexOf(HttpContext.Current.Request.Url.Host.ToLower()) == -1) + { + url = Globals.AddHTTP(HttpContext.Current.Request.Url.Host) + url; + } + } + + item["title"] = searchResult.Title; + item["description"] = searchResult.Description; + item["pubDate"] = searchResult.ModifiedTimeUtc.ToUniversalTime().ToString("r"); + item["link"] = url; + item["guid"] = url; + //TODO: JMB: We need to figure out how to persist the dc prefix in the XML output. See the Render method below. + //item("dc:creator") = SearchItem.AuthorName + + return item; + } + + /// + /// The PreRender event is used to set the Caching Policy for the Feed. This mimics the behavior from the + /// OutputCache directive in the old Rss.aspx file. @OutputCache Duration="60" VaryByParam="moduleid" + /// + /// Event Args. + /// + protected override void OnPreRender(EventArgs ea) + { + base.OnPreRender(ea); + + Context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(60)); + Context.Response.Cache.SetCacheability(HttpCacheability.Public); + Context.Response.Cache.VaryByParams["moduleid"] = true; + } + } +} diff --git a/DNN Platform/Library/Services/Syndication/SyndicationHandlerBase.cs b/DNN Platform/Library/Services/Syndication/SyndicationHandlerBase.cs new file mode 100644 index 00000000000..c6539b1e911 --- /dev/null +++ b/DNN Platform/Library/Services/Syndication/SyndicationHandlerBase.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.Services.Syndication +{ + public class SyndicationHandlerBase : GenericRssHttpHandlerBase + { + private int _moduleId = Null.NullInteger; + + private int _tabId = Null.NullInteger; + + public PortalSettings Settings + { + get + { + return Globals.GetPortalSettings(); + } + } + + public int TabId + { + get + { + if (_tabId == Null.NullInteger && Request.QueryString["tabid"] != null) + { + if (! Int32.TryParse(Request.QueryString["tabid"], out _tabId)) + { + _tabId = Null.NullInteger; + } + } + return _tabId; + } + } + + public int ModuleId + { + get + { + if (_moduleId == Null.NullInteger && Request.QueryString["moduleid"] != null) + { + if (! Int32.TryParse(Request.QueryString["moduleid"], out _moduleId)) + { + _moduleId = Null.NullInteger; + } + } + return _moduleId; + } + } + + public HttpRequest Request + { + get + { + return HttpContext.Current.Request; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/SystemDateTime/SystemDateTime.cs b/DNN Platform/Library/Services/SystemDateTime/SystemDateTime.cs new file mode 100644 index 00000000000..0af92d3f095 --- /dev/null +++ b/DNN Platform/Library/Services/SystemDateTime/SystemDateTime.cs @@ -0,0 +1,86 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Common; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +#endregion + +namespace DotNetNuke.Services.SystemDateTime +{ + /// + /// The SystemDateTime provides static method to obtain System's Time. + /// + /// + /// DateTime information is collected from Database. The methods are created to find one unified timestamp from database + /// as opposed to depending on web server's timestamp. This method becomes more relevant in a web farm configuration + /// + public class SystemDateTime + { + private static readonly DataProvider Provider = DataProvider.Instance(); + + /// ----------------------------------------------------------------------------- + /// + /// GetCurrentTimeUtc get current utc time from database + /// + /// DateTime in Utc + /// ----------------------------------------------------------------------------- + public static DateTime GetCurrentTimeUtc() + { + return Provider.GetDatabaseTimeUtc(); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetCurrentTimeUtc get current time from database + /// + /// DateTime + /// ----------------------------------------------------------------------------- + public static DateTime GetCurrentTime() + { + return Provider.GetDatabaseTime(); + } + + } +} diff --git a/DNN Platform/Library/Services/Tokens/BaseCustomTokenReplace.cs b/DNN Platform/Library/Services/Tokens/BaseCustomTokenReplace.cs new file mode 100644 index 00000000000..dad6ff123db --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/BaseCustomTokenReplace.cs @@ -0,0 +1,245 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + #region " Type Definitions " + + /// + /// Scope informs the property access classes about the planned usage of the token + /// + /// + /// The result of a token replace operation depends on the current context, privacy settings + /// and the current scope. The scope should be the lowest scope needed for the current purpose. + /// The property access classes should evaluate and use the scope before returning a value. + /// + public enum Scope + { + /// + /// Only access to Date and Time + /// + NoSettings = 0, + /// + /// Tokens for Host, Portal, Tab (, Module), user name + /// + Configuration = 1, + /// + /// Configuration, Current User data and user data allowed for registered members + /// + DefaultSettings = 2, + /// + /// System notifications to users and adminstrators + /// + SystemMessages = 3, + /// + /// internal debugging, error messages, logs + /// + Debug = 4 + } + + /// + /// CacheLevel is used to specify the cachability of a string, determined as minimum of the used token cachability + /// + /// + /// CacheLevel is determined as minimum of the used tokens' cachability + /// + public enum CacheLevel : byte + { + /// + /// Caching of the text is not suitable and might expose security risks + /// + notCacheable = 0, + /// + /// Caching of the text might result in inaccurate display (e.g. time), but does not expose a security risk + /// + secureforCaching = 5, + /// + /// Caching of the text can be done without limitations or any risk + /// + fullyCacheable = 10 + } + + #endregion + + /// + /// BaseCustomTokenReplace allows to add multiple sources implementing IPropertyAccess + /// + /// + public abstract class BaseCustomTokenReplace : BaseTokenReplace + { + protected Dictionary PropertySource = new Dictionary(); + #region "Protected Properties" + + /// + /// Gets/sets the current Access Level controlling access to critical user settings + /// + /// A TokenAccessLevel as defined above + protected Scope CurrentAccessLevel { get; set; } + + + #endregion + + #region "Public Properties" + + /// + /// Gets/sets the user object representing the currently accessing user (permission) + /// + /// UserInfo oject + public UserInfo AccessingUser { get; set; } + + /// + /// If DebugMessages are enabled, unknown Tokens are replaced with Error Messages + /// + /// + /// + /// + public bool DebugMessages { get; set; } + + #endregion + + #region "Protected Methods" + + protected override string replacedTokenValue(string strObjectName, string strPropertyName, string strFormat) + { + string result = string.Empty; + bool PropertyNotFound = false; + if (PropertySource.ContainsKey(strObjectName.ToLower())) + { + result = PropertySource[strObjectName.ToLower()].GetProperty(strPropertyName, strFormat, FormatProvider, AccessingUser, CurrentAccessLevel, ref PropertyNotFound); + } + else + { + if (DebugMessages) + { + string message = Localization.Localization.GetString("TokenReplaceUnknownObject", Localization.Localization.SharedResourceFile, FormatProvider.ToString()); + if (message == string.Empty) + { + message = "Error accessing [{0}:{1}], {0} is an unknown datasource"; + } + result = string.Format(message, strObjectName, strPropertyName); + } + } + if (DebugMessages && PropertyNotFound) + { + string message; + if (result == PropertyAccess.ContentLocked) + { + message = Localization.Localization.GetString("TokenReplaceRestrictedProperty", Localization.Localization.GlobalResourceFile, FormatProvider.ToString()); + } + else + { + message = Localization.Localization.GetString("TokenReplaceUnknownProperty", Localization.Localization.GlobalResourceFile, FormatProvider.ToString()); + } + if (message == string.Empty) + { + message = "Error accessing [{0}:{1}], {1} is unknown for datasource {0}"; + } + result = string.Format(message, strObjectName, strPropertyName); + } + + return result; + } + + #endregion + + #region "Public Methods" + + /// + /// Checks for present [Object:Property] tokens + /// + /// String with [Object:Property] tokens + /// + /// + /// 08/10/2007 [sleupold] created + /// 10/19/2007 [sleupold] corrected to ignore unchanged text returned (issue DNN-6526) + /// + public bool ContainsTokens(string strSourceText) + { + if (!string.IsNullOrEmpty(strSourceText)) + { + foreach (Match currentMatch in TokenizerRegex.Matches(strSourceText)) + { + if (currentMatch.Result("${object}").Length > 0) + { + return true; + } + } + } + return false; + } + + /// + /// returns cacheability of the passed text regarding all contained tokens + /// + /// the text to parse for tokens to replace + /// cacheability level (not - safe - fully) + /// always check cacheability before caching a module! + /// + /// 10/19/2007 [sleupold] corrected to handle non-empty strings + /// + public CacheLevel Cacheability(string strSourcetext) + { + CacheLevel IsSafe = CacheLevel.fullyCacheable; + if (strSourcetext != null && !string.IsNullOrEmpty(strSourcetext)) + { + //initialize PropertyAccess classes + string DummyResult = ReplaceTokens(strSourcetext); + + var Result = new StringBuilder(); + foreach (Match currentMatch in TokenizerRegex.Matches(strSourcetext)) + { + string strObjectName = currentMatch.Result("${object}"); + if (!String.IsNullOrEmpty(strObjectName)) + { + if (strObjectName == "[") + { + //nothing + } + else if (!PropertySource.ContainsKey(strObjectName.ToLower())) + { + } + else + { + CacheLevel c = PropertySource[strObjectName.ToLower()].Cacheability; + if (c < IsSafe) + { + IsSafe = c; + } + } + } + } + } + return IsSafe; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Tokens/BaseTokenReplace.cs b/DNN Platform/Library/Services/Tokens/BaseTokenReplace.cs new file mode 100644 index 00000000000..4d8ad2fb7bd --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/BaseTokenReplace.cs @@ -0,0 +1,174 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + /// + /// The BaseTokenReplace class provides the tokenization of tokens formatted + /// [object:property] or [object:property|format|ifEmpty] or [custom:no] within a string + /// with the appropriate current property/custom values. + /// + /// + public abstract class BaseTokenReplace + { + private const string ExpressionDefault = + "(?:\\[(?:(?[^\\]\\[:]+):(?[^\\]\\[\\|]+))(?:\\|(?:(?[^\\]\\[]+)\\|(?[^\\]\\[]+))|\\|(?:(?[^\\|\\]\\[]+)))?\\])|(?\\[[^\\]\\[]+\\])|(?[^\\]\\[]+)"; + + private const string ExpressionObjectLess = + "(?:\\[(?:(?[^\\]\\[:]+):(?[^\\]\\[\\|]+))(?:\\|(?:(?[^\\]\\[]+)\\|(?[^\\]\\[]+))|\\|(?:(?[^\\|\\]\\[]+)))?\\])" + + "|(?:(?\\[)(?[A-Z0-9._]+)(?:\\|(?:(?[^\\]\\[]+)\\|(?[^\\]\\[]+))|\\|(?:(?[^\\|\\]\\[]+)))?\\])" + "|(?\\[[^\\]\\[]+\\])" + + "|(?[^\\]\\[]+)"; + + protected const string ObjectLessToken = "no_object"; + private CultureInfo _FormatProvider; + private string _Language; + + protected bool UseObjectLessExpression { get; set; } + + private string TokenReplaceCacheKey + { + get + { + if (UseObjectLessExpression) + { + return "TokenReplaceRegEx_Objectless"; + } + else + { + return "TokenReplaceRegEx_Default"; + } + } + } + + private string RegExpression + { + get + { + if (UseObjectLessExpression) + { + return ExpressionObjectLess; + } + else + { + return ExpressionDefault; + } + } + } + + /// + /// Gets the Regular expression for the token to be replaced + /// + /// A regular Expression + protected Regex TokenizerRegex + { + get + { + var tokenizer = (Regex) DataCache.GetCache(TokenReplaceCacheKey); + if (tokenizer == null) + { + tokenizer = new Regex(RegExpression, RegexOptions.Compiled); + DataCache.SetCache(TokenReplaceCacheKey, tokenizer); + } + return tokenizer; + } + } + + /// + /// Gets/sets the language to be used, e.g. for date format + /// + /// A string, representing the locale + public string Language + { + get + { + return _Language; + } + set + { + _Language = value; + _FormatProvider = new CultureInfo(_Language); + } + } + + /// + /// Gets the Format provider as Culture info from stored language or current culture + /// + /// An CultureInfo + protected CultureInfo FormatProvider + { + get + { + if (_FormatProvider == null) + { + _FormatProvider = Thread.CurrentThread.CurrentUICulture; + } + return _FormatProvider; + } + } + + protected virtual string ReplaceTokens(string strSourceText) + { + if (strSourceText == null) + { + return string.Empty; + } + var Result = new StringBuilder(); + foreach (Match currentMatch in TokenizerRegex.Matches(strSourceText)) + { + string strObjectName = currentMatch.Result("${object}"); + if (!String.IsNullOrEmpty(strObjectName)) + { + if (strObjectName == "[") + { + strObjectName = ObjectLessToken; + } + string strPropertyName = currentMatch.Result("${property}"); + string strFormat = currentMatch.Result("${format}"); + string strIfEmptyReplacment = currentMatch.Result("${ifEmpty}"); + string strConversion = replacedTokenValue(strObjectName, strPropertyName, strFormat); + if (!String.IsNullOrEmpty(strIfEmptyReplacment) && String.IsNullOrEmpty(strConversion)) + { + strConversion = strIfEmptyReplacment; + } + Result.Append(strConversion); + } + else + { + Result.Append(currentMatch.Result("${text}")); + } + } + return Result.ToString(); + } + + protected abstract string replacedTokenValue(string strObjectName, string strPropertyName, string strFormat); + } +} diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/ArrayListPropertyAccesss.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/ArrayListPropertyAccesss.cs new file mode 100644 index 00000000000..39f4bbe1ac5 --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/ArrayListPropertyAccesss.cs @@ -0,0 +1,96 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public class ArrayListPropertyAccess : IPropertyAccess + { + private readonly ArrayList custom; + + public ArrayListPropertyAccess(ArrayList list) + { + custom = list; + } + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + if (custom == null) + { + return string.Empty; + } + object valueObject = null; + string OutputFormat = format; + if (string.IsNullOrEmpty(format)) + { + OutputFormat = "g"; + } + int intIndex = int.Parse(propertyName); + if ((custom != null) && custom.Count > intIndex) + { + valueObject = custom[intIndex].ToString(); + } + if ((valueObject != null)) + { + switch (valueObject.GetType().Name) + { + case "String": + return PropertyAccess.FormatString((string) valueObject, format); + case "Boolean": + return (PropertyAccess.Boolean2LocalizedYesNo((bool) valueObject, formatProvider)); + case "DateTime": + case "Double": + case "Single": + case "Int32": + case "Int64": + return (((IFormattable) valueObject).ToString(OutputFormat, formatProvider)); + default: + return PropertyAccess.FormatString(valueObject.ToString(), format); + } + } + else + { + PropertyNotFound = true; + return string.Empty; + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/CulturePropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/CulturePropertyAccess.cs new file mode 100644 index 00000000000..f34273a1cca --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/CulturePropertyAccess.cs @@ -0,0 +1,131 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Globalization; + +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public class CulturePropertyAccess : IPropertyAccess + { + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + CultureInfo ci = formatProvider; + if (propertyName.ToLower() == CultureDropDownTypes.EnglishName.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.EnglishName), format); + } + if (propertyName.ToLower() == CultureDropDownTypes.Lcid.ToString().ToLowerInvariant()) + { + return ci.LCID.ToString(); + } + if (propertyName.ToLower() == CultureDropDownTypes.Name.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(ci.Name, format); + } + if (propertyName.ToLower() == CultureDropDownTypes.NativeName.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.NativeName), format); + } + if (propertyName.ToLower() == CultureDropDownTypes.TwoLetterIsoCode.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(ci.TwoLetterISOLanguageName, format); + } + if (propertyName.ToLower() == CultureDropDownTypes.ThreeLetterIsoCode.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(ci.ThreeLetterISOLanguageName, format); + } + if (propertyName.ToLower() == CultureDropDownTypes.DisplayName.ToString().ToLowerInvariant()) + { + return PropertyAccess.FormatString(ci.DisplayName, format); + } + if (propertyName.ToLower() == "languagename") + { + if(ci.IsNeutralCulture) + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.EnglishName), format); + } + else + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.Parent.EnglishName), format); + } + } + if (propertyName.ToLower() == "languagenativename") + { + if(ci.IsNeutralCulture) + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.NativeName), format); + } + else + { + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(ci.Parent.NativeName), format); + } + } + if (propertyName.ToLower() == "countryname") + { + if(ci.IsNeutralCulture) + { + //Neutral culture do not include region information + return ""; + } + else + { + RegionInfo country = new RegionInfo(new CultureInfo(ci.Name, false).LCID); + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(country.EnglishName), format); + } + } + if (propertyName.ToLower() == "countrynativename") + { + if(ci.IsNeutralCulture) + { + //Neutral culture do not include region information + return ""; + } + else + { + RegionInfo country = new RegionInfo(new CultureInfo(ci.Name, false).LCID); + return PropertyAccess.FormatString(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(country.NativeName), format); + } + + + } + PropertyNotFound = true; + return string.Empty; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.fullyCacheable; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/DataRowPropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/DataRowPropertyAccess.cs new file mode 100644 index 00000000000..dcd652348ac --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/DataRowPropertyAccess.cs @@ -0,0 +1,91 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Data; +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public class DataRowPropertyAccess : IPropertyAccess + { + private readonly DataRow dr; + + public DataRowPropertyAccess(DataRow row) + { + dr = row; + } + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + if (dr == null) + { + return string.Empty; + } + object valueObject = dr[propertyName]; + string OutputFormat = format; + if (string.IsNullOrEmpty(format)) + { + OutputFormat = "g"; + } + if (valueObject != null) + { + switch (valueObject.GetType().Name) + { + case "String": + return PropertyAccess.FormatString(Convert.ToString(valueObject), format); + case "Boolean": + return (PropertyAccess.Boolean2LocalizedYesNo(Convert.ToBoolean(valueObject), formatProvider)); + case "DateTime": + case "Double": + case "Single": + case "Int32": + case "Int64": + return (((IFormattable) valueObject).ToString(OutputFormat, formatProvider)); + default: + return PropertyAccess.FormatString(valueObject.ToString(), format); + } + } + else + { + PropertyNotFound = true; + return string.Empty; + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/DateTimePropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/DateTimePropertyAccess.cs new file mode 100644 index 00000000000..72f21de7603 --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/DateTimePropertyAccess.cs @@ -0,0 +1,81 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public class DateTimePropertyAccess : IPropertyAccess + { + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + TimeZoneInfo userTimeZone = AccessingUser.Profile.PreferredTimeZone; + switch (propertyName.ToLower()) + { + case "current": + if (format == string.Empty) + { + format = "D"; + } + return TimeZoneInfo.ConvertTime(DateTime.Now, userTimeZone).ToString(format, formatProvider); + case "now": + if (format == string.Empty) + { + format = "g"; + } + return TimeZoneInfo.ConvertTime(DateTime.Now, userTimeZone).ToString(format, formatProvider); + case "system": + if (format == String.Empty) + { + format = "g"; + } + return DateTime.Now.ToString(format, formatProvider); + case "utc": + if (format == String.Empty) + { + format = "g"; + } + return DateTime.Now.ToUniversalTime().ToString(format, formatProvider); + default: + PropertyNotFound = true; + return string.Empty; + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.secureforCaching; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/DictionaryPropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/DictionaryPropertyAccess.cs new file mode 100644 index 00000000000..413f36d72a4 --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/DictionaryPropertyAccess.cs @@ -0,0 +1,91 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public class DictionaryPropertyAccess : IPropertyAccess + { + private readonly IDictionary NameValueCollection; + + public DictionaryPropertyAccess(IDictionary list) + { + NameValueCollection = list; + } + + #region IPropertyAccess Members + + public virtual string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + if (NameValueCollection == null) + { + return string.Empty; + } + object valueObject = NameValueCollection[propertyName]; + string OutputFormat = format; + if (string.IsNullOrEmpty(format)) + { + OutputFormat = "g"; + } + if (valueObject != null) + { + switch (valueObject.GetType().Name) + { + case "String": + return PropertyAccess.FormatString(Convert.ToString(valueObject), format); + case "Boolean": + return (PropertyAccess.Boolean2LocalizedYesNo(Convert.ToBoolean(valueObject), formatProvider)); + case "DateTime": + case "Double": + case "Single": + case "Int32": + case "Int64": + return (((IFormattable) valueObject).ToString(OutputFormat, formatProvider)); + default: + return PropertyAccess.FormatString(valueObject.ToString(), format); + } + } + else + { + PropertyNotFound = true; + return string.Empty; + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/EmptyPropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/EmptyPropertyAccess.cs new file mode 100644 index 00000000000..b1ad779362b --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/EmptyPropertyAccess.cs @@ -0,0 +1,54 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + /// + /// Returns an Empty String for all Properties + /// + /// + public class EmptyPropertyAccess : IPropertyAccess + { + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + return string.Empty; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/IPropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/IPropertyAccess.cs new file mode 100644 index 00000000000..1eff541337c --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/IPropertyAccess.cs @@ -0,0 +1,37 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + public interface IPropertyAccess + { + CacheLevel Cacheability { get; } + + string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo accessingUser, Scope accessLevel, ref bool propertyNotFound); + } +} diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/PropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/PropertyAccess.cs new file mode 100644 index 00000000000..e6676c4daca --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/PropertyAccess.cs @@ -0,0 +1,159 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; +using System.Reflection; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + /// + /// Property Access to Objects using Relection + /// + /// + public class PropertyAccess : IPropertyAccess + { + private readonly object obj; + + public PropertyAccess(object TokenSource) + { + obj = TokenSource; + } + + public static string ContentLocked + { + get + { + return "*******"; + } + } + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + if (obj == null) + { + return string.Empty; + } + return GetObjectProperty(obj, propertyName, format, formatProvider, ref PropertyNotFound); + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.notCacheable; + } + } + + #endregion + + /// + /// Boolean2LocalizedYesNo returns the translated string for "yes" or "no" against a given boolean value. + /// + /// + /// + /// + /// + public static string Boolean2LocalizedYesNo(bool value, CultureInfo formatProvider) + { + string strValue = Convert.ToString(value ? "Yes" : "No"); + return Localization.Localization.GetString(strValue, null, formatProvider.ToString()); + } + + /// + /// Returns a formatted String if a format is given, otherwise it returns the unchanged value. + /// + /// string to be formatted + /// format specification + /// formatted string + /// + public static string FormatString(string value, string format) + { + if (format.Trim() == string.Empty) + { + return value; + } + else if (value != string.Empty) + { + return string.Format(format, value); + } + else + { + return string.Empty; + } + } + + /// + /// Returns the localized property of any object as string using reflection + /// + /// Object to access + /// Name of property + /// Format String + /// specify formatting + /// out: specifies, whether property was found + /// Localized Property + /// + public static string GetObjectProperty(object objObject, string strPropertyName, string strFormat, CultureInfo formatProvider, ref bool PropertyNotFound) + { + PropertyInfo objProperty = null; + PropertyNotFound = false; + if (CBO.GetProperties(objObject.GetType()).TryGetValue(strPropertyName, out objProperty)) + { + object propValue = objProperty.GetValue(objObject, null); + Type t = typeof (string); + if (propValue != null) + { + switch (objProperty.PropertyType.Name) + { + case "String": + return FormatString(Convert.ToString(propValue), strFormat); + case "Boolean": + return (Boolean2LocalizedYesNo(Convert.ToBoolean(propValue), formatProvider)); + case "DateTime": + case "Double": + case "Single": + case "Int32": + case "Int64": + if (strFormat == string.Empty) + { + strFormat = "g"; + } + return (((IFormattable) propValue).ToString(strFormat, formatProvider)); + } + } + else + { + return ""; + } + } + PropertyNotFound = true; + return string.Empty; + } + } +} diff --git a/DNN Platform/Library/Services/Tokens/PropertyAccess/TicksPropertyAccess.cs b/DNN Platform/Library/Services/Tokens/PropertyAccess/TicksPropertyAccess.cs new file mode 100644 index 00000000000..144e7a7802c --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/PropertyAccess/TicksPropertyAccess.cs @@ -0,0 +1,63 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; + +using DotNetNuke.Entities.Users; + +#endregion + +// ReSharper disable CheckNamespace +namespace DotNetNuke.Services.Tokens +// ReSharper restore CheckNamespace +{ + public class TicksPropertyAccess : IPropertyAccess + { + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope AccessLevel, ref bool PropertyNotFound) + { + switch (propertyName.ToLower()) + { + case "now": + return DateTime.Now.Ticks.ToString(formatProvider); + case "today": + return DateTime.Today.Ticks.ToString(formatProvider); + case "ticksperday": + return TimeSpan.TicksPerDay.ToString(formatProvider); + } + PropertyNotFound = true; + return string.Empty; + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.secureforCaching; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Tokens/TokenReplace.cs b/DNN Platform/Library/Services/Tokens/TokenReplace.cs new file mode 100644 index 00000000000..a0db46790d9 --- /dev/null +++ b/DNN Platform/Library/Services/Tokens/TokenReplace.cs @@ -0,0 +1,447 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; + +#endregion + +namespace DotNetNuke.Services.Tokens +{ + /// + /// The TokenReplace class provides the option to replace tokens formatted + /// [object:property] or [object:property|format] or [custom:no] within a string + /// with the appropriate current property/custom values. + /// Example for Newsletter: 'Dear [user:Displayname],' ==> 'Dear Superuser Account,' + /// Supported Token Sources: User, Host, Portal, Tab, Module, Membership, Profile, + /// Row, Date, Ticks, ArrayList (Custom), IDictionary + /// + /// + public class TokenReplace : BaseCustomTokenReplace + { + #region "Private Fields " + + private Dictionary _Hostsettings; + private int _ModuleId = int.MinValue; + private ModuleInfo _ModuleInfo; + private PortalSettings _PortalSettings; + private UserInfo _User; + + #endregion + + #region "Constructors" + + /// + /// creates a new TokenReplace object for default context + /// + /// + /// 08/10/2007 sLeupold documented + /// + public TokenReplace() : this(Scope.DefaultSettings, null, null, null, Null.NullInteger) + { + } + + /// + /// creates a new TokenReplace object for default context and the current module + /// + /// ID of the current module + /// + /// 10/19/2007 sLeupold added + /// + public TokenReplace(int ModuleID) : this(Scope.DefaultSettings, null, null, null, ModuleID) + { + } + + /// + /// creates a new TokenReplace object for custom context + /// + /// Security level granted by the calling object + /// + /// 08/10/2007 sLeupold documented + /// + public TokenReplace(Scope AccessLevel) : this(AccessLevel, null, null, null, Null.NullInteger) + { + } + + /// + /// creates a new TokenReplace object for custom context + /// + /// Security level granted by the calling object + /// ID of the current module + /// + /// 08/10/2007 sLeupold documented + /// 10/19/2007 sLeupold added + /// + public TokenReplace(Scope AccessLevel, int ModuleID) : this(AccessLevel, null, null, null, ModuleID) + { + } + + /// + /// creates a new TokenReplace object for custom context + /// + /// Security level granted by the calling object + /// Locale to be used for formatting etc. + /// PortalSettings to be used + /// user, for which the properties shall be returned + /// + /// 08/10/2007 sLeupold documented + /// + public TokenReplace(Scope AccessLevel, string Language, PortalSettings PortalSettings, UserInfo User) : this(AccessLevel, Language, PortalSettings, User, Null.NullInteger) + { + } + + /// + /// creates a new TokenReplace object for custom context + /// + /// Security level granted by the calling object + /// Locale to be used for formatting etc. + /// PortalSettings to be used + /// user, for which the properties shall be returned + /// ID of the current module + /// + /// 08/10/2007 sleupold documented + /// 10/19/2007 sleupold ModuleID added + /// + public TokenReplace(Scope AccessLevel, string Language, PortalSettings PortalSettings, UserInfo User, int ModuleID) + { + CurrentAccessLevel = AccessLevel; + if (AccessLevel != Scope.NoSettings) + { + if (PortalSettings == null) + { + if (HttpContext.Current != null) + { + this.PortalSettings = PortalController.GetCurrentPortalSettings(); + } + } + else + { + this.PortalSettings = PortalSettings; + } + if (User == null) + { + if (HttpContext.Current != null) + { + this.User = (UserInfo) HttpContext.Current.Items["UserInfo"]; + } + else + { + this.User = new UserInfo(); + } + AccessingUser = this.User; + } + else + { + this.User = User; + if (HttpContext.Current != null) + { + AccessingUser = (UserInfo) HttpContext.Current.Items["UserInfo"]; + } + else + { + AccessingUser = new UserInfo(); + } + } + if (string.IsNullOrEmpty(Language)) + { + this.Language = new Localization.Localization().CurrentUICulture; + } + else + { + this.Language = Language; + } + if (ModuleID != Null.NullInteger) + { + ModuleId = ModuleID; + } + } + PropertySource["date"] = new DateTimePropertyAccess(); + PropertySource["datetime"] = new DateTimePropertyAccess(); + PropertySource["ticks"] = new TicksPropertyAccess(); + PropertySource["culture"] = new CulturePropertyAccess(); + } + + #endregion + + #region "Public Properties " + + /// + /// Gets the Host settings from Portal + /// + /// A hashtable with all settings + private Dictionary HostSettings + { + get + { + if (_Hostsettings == null) + { + _Hostsettings = HostController.Instance.GetSettings().Where(c => !c.Value.IsSecure).ToDictionary(c => c.Key, c => c.Value.Value); + } + return _Hostsettings; + } + } + + /// + /// Gets/sets the current ModuleID to be used for 'User:' token replacement + /// + /// ModuleID (Integer) + public int ModuleId + { + get + { + return _ModuleId; + } + set + { + _ModuleId = value; + } + } + + /// + /// Gets/sets the module settings object to use for 'Module:' token replacement + /// + public ModuleInfo ModuleInfo + { + get + { + if (ModuleId > int.MinValue && (_ModuleInfo == null || _ModuleInfo.ModuleID != ModuleId)) + { + var mc = new ModuleController(); + if (PortalSettings != null && PortalSettings.ActiveTab != null) + { + _ModuleInfo = mc.GetModule(ModuleId, PortalSettings.ActiveTab.TabID, false); + } + else + { + _ModuleInfo = mc.GetModule(ModuleId); + } + } + return _ModuleInfo; + } + set + { + _ModuleInfo = value; + } + } + + /// + /// Gets/sets the portal settings object to use for 'Portal:' token replacement + /// + /// PortalSettings oject + public PortalSettings PortalSettings + { + get + { + return _PortalSettings; + } + set + { + _PortalSettings = value; + } + } + + /// + /// Gets/sets the user object to use for 'User:' token replacement + /// + /// UserInfo oject + public UserInfo User + { + get + { + return _User; + } + set + { + _User = value; + } + } + + #endregion + + #region "Public Replace Methods" + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// string containing replaced values + public string ReplaceEnvironmentTokens(string strSourceText) + { + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// + /// string containing replaced values + public string ReplaceEnvironmentTokens(string strSourceText, DataRow row) + { + var rowProperties = new DataRowPropertyAccess(row); + PropertySource["field"] = rowProperties; + PropertySource["row"] = rowProperties; + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// + /// + /// string containing replaced values + public string ReplaceEnvironmentTokens(string strSourceText, ArrayList Custom, string CustomCaption) + { + PropertySource[CustomCaption.ToLower()] = new ArrayListPropertyAccess(Custom); + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// NameValueList for replacing [custom:name] tokens, where 'custom' is specified in next param and name is either thekey or the index number in the string + /// Token name to be used inside token [custom:name] + /// string containing replaced values + /// + /// 08/10/2007 sLeupold created + /// + public string ReplaceEnvironmentTokens(string strSourceText, IDictionary Custom, string CustomCaption) + { + PropertySource[CustomCaption.ToLower()] = new DictionaryPropertyAccess(Custom); + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// NameValueList for replacing [custom:name] tokens, where 'custom' is specified in next param and name is either thekey or the index number in the string + /// Token names to be used inside token [custom:name], where 'custom' is one of the values in the string array + /// string containing replaced values + /// + /// 01/25/2012 vnguyen created + /// + public string ReplaceEnvironmentTokens(string strSourceText, IDictionary Custom, string[] CustomCaptions) + { + foreach (var customCaption in CustomCaptions) + { + PropertySource[customCaption.ToLower()] = new DictionaryPropertyAccess(Custom); + } + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values + /// + /// String with [Object:Property] tokens + /// NameValueList for replacing [custom:name] tokens, where 'custom' is specified in next param and name is either thekey or the index number in the string + /// Token name to be used inside token [custom:name] + /// DataRow, from which field values shall be used for replacement + /// string containing replaced values + /// + /// 08/10/2007 sLeupold created + /// + public string ReplaceEnvironmentTokens(string strSourceText, ArrayList Custom, string CustomCaption, DataRow Row) + { + var rowProperties = new DataRowPropertyAccess(Row); + PropertySource["field"] = rowProperties; + PropertySource["row"] = rowProperties; + PropertySource[CustomCaption.ToLower()] = new ArrayListPropertyAccess(Custom); + return ReplaceTokens(strSourceText); + } + + /// + /// Replaces tokens in strSourceText parameter with the property values, skipping environment objects + /// + /// String with [Object:Property] tokens + /// string containing replaced values + /// + /// 08/10/2007 sLeupold created + /// + protected override string ReplaceTokens(string strSourceText) + { + InitializePropertySources(); + return base.ReplaceTokens(strSourceText); + } + + #endregion + + #region "Private methods" + + /// + /// setup context by creating appropriate objects + /// + /// + /// /08/10/2007 sCullmann created + /// + /// + /// security is not the purpose of the initialization, this is in the responsibility of each property access class + /// + private void InitializePropertySources() + { + //Cleanup, by default "" is returned for these objects and any property + IPropertyAccess DefaultPropertyAccess = new EmptyPropertyAccess(); + PropertySource["portal"] = DefaultPropertyAccess; + PropertySource["tab"] = DefaultPropertyAccess; + PropertySource["host"] = DefaultPropertyAccess; + PropertySource["module"] = DefaultPropertyAccess; + PropertySource["user"] = DefaultPropertyAccess; + PropertySource["membership"] = DefaultPropertyAccess; + PropertySource["profile"] = DefaultPropertyAccess; + + //initialization + if (CurrentAccessLevel >= Scope.Configuration) + { + if (PortalSettings != null) + { + PropertySource["portal"] = PortalSettings; + PropertySource["tab"] = PortalSettings.ActiveTab; + } + PropertySource["host"] = new HostPropertyAccess(); + if (ModuleInfo != null) + { + PropertySource["module"] = ModuleInfo; + } + } + if (CurrentAccessLevel >= Scope.DefaultSettings && !(User == null || User.UserID == -1)) + { + PropertySource["user"] = User; + PropertySource["membership"] = new MembershipPropertyAccess(User); + PropertySource["profile"] = new ProfilePropertyAccess(User); + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/DnnInstallLogger.cs b/DNN Platform/Library/Services/Upgrade/DnnInstallLogger.cs new file mode 100644 index 00000000000..4b6209a007a --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/DnnInstallLogger.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.Compilation; + +using DotNetNuke.Instrumentation; + +namespace DotNetNuke.Services.Upgrade +{ + /// + /// This class is used to write log into separate installer log file. + /// + internal class DnnInstallLogger + { + private static StackFrame CallingFrame + { + get + { + StackFrame frame = null; + StackFrame[] stack = new StackTrace().GetFrames(); + + int frameDepth = 0; + if (stack != null) + { + Type reflectedType = stack[frameDepth].GetMethod().ReflectedType; + while (reflectedType == BuildManager.GetType("DotNetNuke.Services.Exceptions.Exceptions", false) || reflectedType == typeof(DnnInstallLogger)) + { + frameDepth++; + reflectedType = stack[frameDepth].GetMethod().ReflectedType; + } + frame = stack[frameDepth]; + } + return frame; + } + } + + private static Type CallingType + { + get + { + return CallingFrame.GetMethod().DeclaringType; + } + } + + #region InstallLog + + public static void InstallLogError(object message) + { + LogInstaller("[ERROR]", message.ToString()); + } + + public static void InstallLogError(string message, Exception exception) + { + LogInstaller("[ERROR]", message.ToString(CultureInfo.InvariantCulture) + " : " + exception); + } + + public static void InstallLogInfo(object message) + { + LogInstaller("[INFO]", message.ToString()); + } + + #endregion + + private static void LogInstaller(string logType, string message) + { + string logFile = "InstallerLog" + DateTime.Now.Year.ToString(CultureInfo.InvariantCulture) + DateTime.Now.Month.ToString(CultureInfo.InvariantCulture) + DateTime.Now.Day.ToString(CultureInfo.InvariantCulture) + ".resources"; + string logfilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Portals\_default\Logs\" + logFile); + using (var writer = new StreamWriter(logfilePath, true)) + { + writer.WriteLine(DateTime.UtcNow.ToString(CultureInfo.InvariantCulture) + " " + logType + " " + CallingType + " " + message); + } + + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/IInstallController.cs b/DNN Platform/Library/Services/Upgrade/Internals/IInstallController.cs new file mode 100644 index 00000000000..bbbdf4ea1a9 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/IInstallController.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Upgrade.Internals.InstallConfiguration; + +namespace DotNetNuke.Services.Upgrade.Internals +{ + /// ----------------------------------------------------------------------------- + /// + /// Interface for InstallController. This Interface is meant for Internal use only + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + public interface IInstallController + { + bool IsValidSqlServerVersion(string connectionString); + + bool IsAbleToPerformDatabaseActions(string connectionString); + + bool IsValidDotNetVersion(); + + bool IsSqlServerDbo(); + + bool IsAvailableLanguagePack(string cultureCode); + + /// + /// GetInstallConfig - Returns configuration stored in DotNetNuke.Install.Config + /// + /// ConnectionConfig object. Null if information is not present in the config file + InstallConfig GetInstallConfig(); + + /// + /// SetInstallConfig - Saves configuration n DotNetNuke.Install.Config + /// + void SetInstallConfig(InstallConfig installConfig); + + /// + /// RemoveFromInstallConfig - Removes the specified XML Node from the InstallConfig + /// + /// + void RemoveFromInstallConfig(string xmlNodePath); + + /// + /// GetConnectionFromWebConfig - Returns Connection Configuration in web.config file + /// + /// ConnectionConfig object. Null if information is not present in the config file + ConnectionConfig GetConnectionFromWebConfig(); + + CultureInfo GetCurrentLanguage(); + + string TestDatabaseConnection(ConnectionConfig connectionConfig); + + CultureInfo GetCultureFromCookie(); + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/ConnectionConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/ConnectionConfig.cs new file mode 100644 index 00000000000..c1b2ed29602 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/ConnectionConfig.cs @@ -0,0 +1,47 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// ConnectionConfig - A class that represents Install/DotNetNuke.Install.Config/Connection + /// + /// ----------------------------------------------------------------------------- + + public class ConnectionConfig + { + public string Server { get; set; } + public string Database { get; set; } + public string File { get; set; } + public bool Integrated { get; set; } + public string User { get; set; } + public string Password { get; set; } + public bool RunAsDbowner { get; set; } + public string Qualifier { get; set; } + public string UpgradeConnectionString { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/HostSettingConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/HostSettingConfig.cs new file mode 100644 index 00000000000..6474c121241 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/HostSettingConfig.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// HostSettingConfig - A class that represents Install/DotNetNuke.Install.Config/Settings + /// + /// ----------------------------------------------------------------------------- + + public class HostSettingConfig + { + public string Name { get; set; } + public string Value { get; set; } + public bool IsSecure { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/InstallConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/InstallConfig.cs new file mode 100644 index 00000000000..d67aba5ec21 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/InstallConfig.cs @@ -0,0 +1,57 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallConfig - A class that represents DotNetNuke.Install.Config XML configuration file + /// TODO This class may not capture all the details from the config file + /// + /// ----------------------------------------------------------------------------- + + public class InstallConfig + { + public IList Scripts { get; set; } + public string Version { get; set; } + public string InstallCulture { get; set; } + public SuperUserConfig SuperUser { get; set; } + public ConnectionConfig Connection { get; set; } + public LicenseConfig License { get; set; } + public IList Portals { get; set; } + public IList Settings { get; set; } + + public InstallConfig() + { + Portals = new List(); + Scripts = new List(); + Settings = new List(); + } + } + + +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/LicenseConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/LicenseConfig.cs new file mode 100644 index 00000000000..e4803042c72 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/LicenseConfig.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// LicenseConfig - A class that represents Install/DotNetNuke.Install.Config/LicenseActivation + /// + /// ----------------------------------------------------------------------------- + + public class LicenseConfig + { + public string AccountEmail { get; set; } + public string InvoiceNumber { get; set; } + public string WebServer { get; set; } + public string LicenseType { get; set; } + public bool TrialRequest { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/PortalConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/PortalConfig.cs new file mode 100644 index 00000000000..c4bbc8cdafa --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/PortalConfig.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// PortalConfig - A class that represents Install/DotNetNuke.Install.Config/Portals/Portal + /// + /// ----------------------------------------------------------------------------- + + public class PortalConfig + { + public string PortalName { get; set; } + public string AdminFirstName { get; set; } + public string AdminLastName { get; set; } + public string AdminUserName { get; set; } + public string AdminPassword { get; set; } + public string AdminEmail { get; set; } + public string Description { get; set; } + public string Keywords { get; set; } + public string TemplateFileName { get; set; } + public bool IsChild { get; set; } + public string HomeDirectory { get; set; } + public IList PortAliases { get; set; } + + public PortalConfig() + { + PortAliases = new List(); + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/SuperUserConfig.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/SuperUserConfig.cs new file mode 100644 index 00000000000..882505e61bb --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallConfiguration/SuperUserConfig.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.InstallConfiguration +{ + /// ----------------------------------------------------------------------------- + /// + /// SuperUserConfig - A class that represents Install/DotNetNuke.Install.Config/SuperUser + /// + /// ----------------------------------------------------------------------------- + + public class SuperUserConfig + { + public string FirstName { get; set; } + public string LastName { get; set; } + public string UserName { get; set; } + public string Password { get; set; } + public string Email { get; set; } + public string Locale { get; set; } + public bool UpdatePassword { get; set; } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallController.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallController.cs new file mode 100644 index 00000000000..a36ee8f666e --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallController.cs @@ -0,0 +1,43 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; + +using DotNetNuke.Framework; +using DotNetNuke.Services.Upgrade.InternalController; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals +{ + /// + /// Business Layer to manage Messaging. Also contains CRUD methods. + /// + public class InstallController : ServiceLocator + { + protected override Func GetFactory() + { + return () => new InstallControllerImpl(); + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/InstallControllerImpl.cs b/DNN Platform/Library/Services/Upgrade/Internals/InstallControllerImpl.cs new file mode 100644 index 00000000000..77a378176e2 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/InstallControllerImpl.cs @@ -0,0 +1,693 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; +using System.Data.Common; +using System.Data.SqlClient; +using System.Globalization; +using System.Net; +using System.Web; +using System.Xml; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Services.Installer; +using DotNetNuke.Services.Upgrade.Internals.InstallConfiguration; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals +{ + /// ----------------------------------------------------------------------------- + /// + /// The Controller class for Installer + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + internal class InstallControllerImpl : IInstallController + { + #region IInstallController Members + + /// + /// GetConnectionFromWebConfig - Returns Connection Configuration in web.config file + /// + /// ConnectionConfig object. Null if information is not present in the config file + public ConnectionConfig GetConnectionFromWebConfig() + { + var connectionConfig = new ConnectionConfig(); + + string connection = Config.GetConnectionString(); + foreach (string connectionParam in connection.Split(';')) + { + int index = connectionParam.IndexOf("="); + if (index > 0) + { + string key = connectionParam.Substring(0, index); + string value = connectionParam.Substring(index + 1); + switch (key.ToLower()) + { + case "server": + case "data source": + case "address": + case "addr": + case "network address": + connectionConfig.Server = value; + break; + case "database": + case "initial catalog": + connectionConfig.Database = value; + break; + case "uid": + case "user id": + case "user": + connectionConfig.User = value; + break; + case "pwd": + case "password": + connectionConfig.Password = value; + break; + case "integrated security": + connectionConfig.Integrated = (value.ToLower() == "true"); + break; + case "attachdbfilename": + connectionConfig.File = value.Replace("|DataDirectory|", ""); + break; + } + } + } + + connectionConfig.Qualifier = Config.GetObjectQualifer(); + connectionConfig.RunAsDbowner = Config.GetDataBaseOwner() == "dbo."; + connectionConfig.UpgradeConnectionString = Config.GetUpgradeConnectionString(); + + return connectionConfig; + } + + /// + /// SetInstallConfig - Saves configuration n DotNetNuke.Install.Config + /// + public void SetInstallConfig(InstallConfig installConfig) + { + if (installConfig == null) + { + return; + } + + //Load Template + var installTemplate = new XmlDocument(); + Upgrade.GetInstallTemplate(installTemplate); + XmlNode dotnetnukeNode = installTemplate.SelectSingleNode("//dotnetnuke"); + + //Set Version + if (!string.IsNullOrEmpty(installConfig.Version)) + { + XmlNode versionNode = installTemplate.SelectSingleNode("//dotnetnuke/version"); + + if (versionNode == null) + { + versionNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "version", installConfig.Version); + } + + versionNode.InnerText = installConfig.Version; + } + + //Set installer culture + if (!string.IsNullOrEmpty(installConfig.InstallCulture)) + { + XmlNode versionNode = installTemplate.SelectSingleNode("//dotnetnuke/installCulture"); + + if (versionNode == null) + { + versionNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "installCulture", installConfig.InstallCulture); + } + + versionNode.InnerText = installConfig.InstallCulture; + } + + //Set SuperUser + if (installConfig.SuperUser != null) + { + XmlNode superUserNode = installTemplate.SelectSingleNode("//dotnetnuke/superuser"); + if (superUserNode == null) + { + superUserNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "superuser", installConfig.Version); + } + else + { + superUserNode.RemoveAll(); + } + + AppendNewXmlNode(ref installTemplate, ref superUserNode, "firstname", installConfig.SuperUser.FirstName); + AppendNewXmlNode(ref installTemplate, ref superUserNode, "lastname", installConfig.SuperUser.LastName); + AppendNewXmlNode(ref installTemplate, ref superUserNode, "username", installConfig.SuperUser.UserName); + AppendNewXmlNode(ref installTemplate, ref superUserNode, "password", installConfig.SuperUser.Password); + AppendNewXmlNode(ref installTemplate, ref superUserNode, "email", installConfig.SuperUser.Email); + AppendNewXmlNode(ref installTemplate, ref superUserNode, "updatepassword", "false"); + } + + //Set Portals + if (installConfig.Portals != null && installConfig.Portals.Count > 0) + { + XmlNode portalsNode = installTemplate.SelectSingleNode("//dotnetnuke/portals"); + if (portalsNode == null) + { + portalsNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "portals", installConfig.Version); + } + else + { + portalsNode.RemoveAll(); + } + + + foreach (PortalConfig portalConfig in installConfig.Portals) + { + XmlNode portalNode = AppendNewXmlNode(ref installTemplate, ref portalsNode, "portal", null); + XmlNode administratorNode = AppendNewXmlNode(ref installTemplate, ref portalNode, "administrator", null); + XmlNode portalAliasesNode = AppendNewXmlNode(ref installTemplate, ref portalNode, "portalaliases", null); + AppendNewXmlNode(ref installTemplate, ref portalNode, "portalname", portalConfig.PortalName); + AppendNewXmlNode(ref installTemplate, ref administratorNode, "firstname", portalConfig.AdminFirstName); + AppendNewXmlNode(ref installTemplate, ref administratorNode, "lastname", portalConfig.AdminLastName); + AppendNewXmlNode(ref installTemplate, ref administratorNode, "username", portalConfig.AdminUserName); + AppendNewXmlNode(ref installTemplate, ref administratorNode, "password", portalConfig.AdminPassword); + AppendNewXmlNode(ref installTemplate, ref administratorNode, "email", portalConfig.AdminEmail); + AppendNewXmlNode(ref installTemplate, ref portalNode, "description", portalConfig.Description); + AppendNewXmlNode(ref installTemplate, ref portalNode, "keywords", portalConfig.Keywords); + AppendNewXmlNode(ref installTemplate, ref portalNode, "templatefile", portalConfig.TemplateFileName); + AppendNewXmlNode(ref installTemplate, ref portalNode, "ischild", portalConfig.IsChild.ToString().ToLower()); + AppendNewXmlNode(ref installTemplate, ref portalNode, "homedirectory", portalConfig.HomeDirectory); + + foreach (string portalAliase in portalConfig.PortAliases) + { + AppendNewXmlNode(ref installTemplate, ref portalAliasesNode, "portalalias", portalAliase); + } + } + } + + //Set the settings + if (installConfig.Settings != null && installConfig.Settings.Count > 0) + { + XmlNode settingsNode = installTemplate.SelectSingleNode("//dotnetnuke/settings"); + if (settingsNode == null) + { + settingsNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "settings", null); + } + else + { + settingsNode.RemoveAll(); + } + + foreach (HostSettingConfig setting in installConfig.Settings) + { + XmlNode settingNode = AppendNewXmlNode(ref installTemplate, ref settingsNode, setting.Name, setting.Value); + if (setting.IsSecure) + { + XmlAttribute attribute = installTemplate.CreateAttribute("Secure"); + attribute.Value = "true"; + settingNode.Attributes.Append(attribute); + } + } + } + + //Set Connection + if (installConfig.Connection != null) + { + XmlNode connectionNode = installTemplate.SelectSingleNode("//dotnetnuke/connection"); + if (connectionNode == null) + { + connectionNode = AppendNewXmlNode(ref installTemplate, ref dotnetnukeNode, "connection", null); + } + else + { + connectionNode.RemoveAll(); + } + + AppendNewXmlNode(ref installTemplate, ref connectionNode, "server", installConfig.Connection.Server); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "database", installConfig.Connection.Database); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "file", installConfig.Connection.File); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "integrated", installConfig.Connection.Integrated.ToString().ToLower()); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "user", installConfig.Connection.User); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "password", installConfig.Connection.Password); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "runasdbowner", installConfig.Connection.RunAsDbowner.ToString().ToLower()); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "qualifier", installConfig.Connection.Qualifier); + AppendNewXmlNode(ref installTemplate, ref connectionNode, "upgradeconnectionstring", installConfig.Connection.UpgradeConnectionString); + } + + Upgrade.SetInstallTemplate(installTemplate); + } + + public void RemoveFromInstallConfig(string xmlNodePath) + { + InstallConfig config = GetInstallConfig(); + if (config == null) + { + return; + } + var installTemplate = new XmlDocument(); + Upgrade.GetInstallTemplate(installTemplate); + XmlNodeList nodes = installTemplate.SelectNodes(xmlNodePath); + if (nodes != null && nodes.Count > 0 && nodes[0].ParentNode != null) + { + nodes[0].ParentNode.RemoveChild(nodes[0]); + } + Upgrade.SetInstallTemplate(installTemplate); + } + + /// + /// GetInstallConfig - Returns configuration stored in DotNetNuke.Install.Config + /// + /// ConnectionConfig object. Null if information is not present in the config file + public InstallConfig GetInstallConfig() + { + var installConfig = new InstallConfig(); + + //Load Template + var installTemplate = new XmlDocument(); + Upgrade.GetInstallTemplate(installTemplate); + + //Parse the root node + XmlNode rootNode = installTemplate.SelectSingleNode("//dotnetnuke"); + if (rootNode != null) + { + installConfig.Version = XmlUtils.GetNodeValue(rootNode.CreateNavigator(), "version"); + installConfig.InstallCulture = XmlUtils.GetNodeValue(rootNode.CreateNavigator(), "installCulture") ?? Localization.Localization.SystemLocale; + } + + //Parse the scripts node + XmlNode scriptsNode = installTemplate.SelectSingleNode("//dotnetnuke/scripts"); + if (scriptsNode != null) + { + foreach (XmlNode scriptNode in scriptsNode) + { + if (scriptNode != null) + { + installConfig.Scripts.Add(scriptNode.InnerText); + } + } + } + + //Parse the connection node + XmlNode connectionNode = installTemplate.SelectSingleNode("//dotnetnuke/connection"); + if (connectionNode != null) + { + var connectionConfig = new ConnectionConfig(); + + //Build connection string from the file + connectionConfig.Server = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "server"); + connectionConfig.Database = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "database"); + connectionConfig.File = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "file"); + connectionConfig.Integrated = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "integrated").ToLower() == "true"; + connectionConfig.User = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "user"); + connectionConfig.Password = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "password"); + connectionConfig.RunAsDbowner = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "runasdbowner").ToLower() == "true"; + connectionConfig.Qualifier = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "qualifier"); + connectionConfig.UpgradeConnectionString = XmlUtils.GetNodeValue(connectionNode.CreateNavigator(), "upgradeconnectionstring"); + + installConfig.Connection = connectionConfig; + } + + //Parse the superuser node + XmlNode superUserNode = installTemplate.SelectSingleNode("//dotnetnuke/superuser"); + if (superUserNode != null) + { + var superUserConfig = new SuperUserConfig(); + + superUserConfig.FirstName = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "firstname"); + superUserConfig.LastName = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "lastname"); + superUserConfig.UserName = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "username"); + superUserConfig.Password = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "password"); + superUserConfig.Email = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "email"); + superUserConfig.Locale = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "locale"); + superUserConfig.UpdatePassword = XmlUtils.GetNodeValue(superUserNode.CreateNavigator(), "updatepassword").ToLower() == "true"; + + installConfig.SuperUser = superUserConfig; + } + + //Parse the license node + XmlNode licenseNode = installTemplate.SelectSingleNode("//dotnetnuke/license"); + if (licenseNode != null) + { + var licenseConfig = new LicenseConfig(); + + licenseConfig.AccountEmail = XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "accountEmail"); + licenseConfig.InvoiceNumber = XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "invoiceNumber"); + licenseConfig.WebServer = XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "webServer"); + licenseConfig.LicenseType = XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "licenseType"); + + if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "trial"))) + { + licenseConfig.TrialRequest = bool.Parse(XmlUtils.GetNodeValue(licenseNode.CreateNavigator(), "trial")); + } + + installConfig.License = licenseConfig; + } + + //Parse the settings node + XmlNode settingsNode = installTemplate.SelectSingleNode("//dotnetnuke/settings"); + if (settingsNode != null) + { + foreach (XmlNode settingNode in settingsNode.ChildNodes) + { + if (settingNode != null && !string.IsNullOrEmpty(settingNode.Name)) + { + bool settingIsSecure = false; + if (settingNode.Attributes != null) + { + XmlAttribute secureAttrib = settingNode.Attributes["Secure"]; + if ((secureAttrib != null)) + { + if (secureAttrib.Value.ToLower() == "true") + { + settingIsSecure = true; + } + } + } + installConfig.Settings.Add(new HostSettingConfig {Name = settingNode.Name, Value = settingNode.InnerText, IsSecure = settingIsSecure}); + } + } + } + + //Parse the portals node + XmlNodeList portalsNode = installTemplate.SelectNodes("//dotnetnuke/portals/portal"); + if (portalsNode != null) + { + foreach (XmlNode portalNode in portalsNode) + { + if (portalNode != null) + { + var portalConfig = new PortalConfig(); + portalConfig.PortalName = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "portalname"); + + XmlNode adminNode = portalNode.SelectSingleNode("administrator"); + if (adminNode != null) + { + portalConfig.AdminFirstName = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "firstname"); + portalConfig.AdminLastName = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "lastname"); + portalConfig.AdminUserName = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "username"); + portalConfig.AdminPassword = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "password"); + portalConfig.AdminEmail = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "email"); + } + portalConfig.Description = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "description"); + portalConfig.Keywords = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "keywords"); + portalConfig.TemplateFileName = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "templatefile"); + portalConfig.IsChild = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "ischild").ToLower() == "true"; + ; + portalConfig.HomeDirectory = XmlUtils.GetNodeValue(portalNode.CreateNavigator(), "homedirectory"); + + //Get the Portal Alias + XmlNodeList portalAliases = portalNode.SelectNodes("portalaliases/portalalias"); + if (portalAliases != null) + { + foreach (XmlNode portalAliase in portalAliases) + { + if (!string.IsNullOrEmpty(portalAliase.InnerText)) + { + portalConfig.PortAliases.Add(portalAliase.InnerText); + } + } + } + installConfig.Portals.Add(portalConfig); + } + } + } + + return installConfig; + } + + public bool IsValidSqlServerVersion(string connectionString) + { + //todo: check if we can use globals.DatabaseEngineVersion instead + + bool isValidVersion = false; + var sqlConnection = new SqlConnection(connectionString); + try + { + sqlConnection.Open(); + + string serverVersion = sqlConnection.ServerVersion; + if (serverVersion != null) + { + string[] serverVersionDetails = serverVersion.Split(new[] {"."}, StringSplitOptions.None); + + int versionNumber = int.Parse(serverVersionDetails[0]); + + switch (versionNumber) + { + case 8: + //sql 2000 + case 9: + //sql 2005 + isValidVersion = false; + break; + case 10: + //sql 2008 + case 11: + //sql 2010 + case 12: + //sql 2012 + isValidVersion = true; + break; + default: + //covers unknown versions and later releases + isValidVersion = true; + break; + } + } + } + catch (Exception) + { + //cannot connect with the details + isValidVersion = false; + } + finally + { + sqlConnection.Close(); + } + return isValidVersion; + } + + public bool IsAbleToPerformDatabaseActions(string connectionString) + { + //todo: will need to generate a unique faketable name and introduce the dbo user + string databaseActions = "CREATE TABLE [dbo].[faketable]([fakeColumn] [int] NULL);select * from faketable;drop table faketable;"; + //TODO: this is an obsolete member, need a better solution to support querystring from install.config (i think) + string strExceptions = DataProvider.Instance().ExecuteScript(connectionString, databaseActions); + //if no exceptions we have necessary drop etc permissions + return string.IsNullOrEmpty(strExceptions); + } + + public bool IsValidDotNetVersion() + { + //todo: check that this works for 4.5 etc. + return Upgrade.IsNETFrameworkCurrent("4.0"); + } + + public bool IsSqlServerDbo() + { + string dbo = DataProvider.Instance().Settings["databaseOwner"]; + if (dbo.Trim().ToLower() != "dbo.") + { + return true; + } + else + { + return false; + } + } + + public bool IsAvailableLanguagePack(string cultureCode) + { + try + { + string downloadUrl = UpdateService.GetLanguageDownloadUrl(cultureCode); + + string installFolder = HttpContext.Current.Server.MapPath("~/Install/language"); + //no need to download english, always there + if (cultureCode != "en-us" && String.IsNullOrEmpty(downloadUrl) != true) + { + GetLanguagePack(downloadUrl, installFolder); + return true; + } + return false; + } + catch (Exception) + { + return false; + } + } + + public CultureInfo GetCurrentLanguage() + { + CultureInfo pageCulture = null; + + + // 1. querystring + pageCulture = GetCultureFromQs(); + + // 2. cookie + pageCulture = GetCultureFromCookie(); + + // 3. browser + pageCulture = GetCultureFromBrowser(); + + return pageCulture; + } + + /// + /// Tests the Database Connection using the database connection config + /// + /// + /// + /// + /// + public string TestDatabaseConnection(ConnectionConfig config) + { + DbConnectionStringBuilder builder = DataProvider.Instance().GetConnectionStringBuilder(); + string owner = string.Empty; + string objectQualifier = config.Qualifier; + + builder["data source"] = config.Server; + builder["integrated security"] = config.Integrated; + builder["uid"] = config.User; + builder["pwd"] = config.Password; + + if (!string.IsNullOrEmpty(config.File)) + { + builder["attachDbFilename"] = "|DataDirectory|" + config.File; + builder["user instance"] = true; + } + else + { + builder["initial catalog"] = config.Database; + } + + if (config.RunAsDbowner) + { + owner = "dbo."; + } + + return DataProvider.Instance().TestDatabaseConnection(builder, owner, objectQualifier); + } + + public CultureInfo GetCultureFromCookie() + { + string language = HttpContext.Current.Request.Cookies["language"].Value; + var culture = new CultureInfo(language); + return culture; + } + + #endregion + + public CultureInfo GetCultureFromBrowser() + { + CultureInfo culture = null; + foreach (string userLang in HttpContext.Current.Request.UserLanguages) + { + //split userlanguage by ";"... all but the first language will contain a preferrence index eg. ;q=.5 + string language = userLang.Split(';')[0]; + culture = new CultureInfo(language); + } + return culture; + } + + private CultureInfo GetCultureFromQs() + { + if (HttpContext.Current == null || HttpContext.Current.Request["language"] == null) + { + return null; + } + + string language = HttpContext.Current.Request["language"]; + var culture = new CultureInfo(language); + return culture; + } + + private static string UpgradeRedirect() + { + //todo: will need to replace DotNetNukeContext.Current.Application.Type with "LanguagePack" + return UpgradeRedirect(DotNetNukeContext.Current.Application.Version, DotNetNukeContext.Current.Application.Type, DotNetNukeContext.Current.Application.Name, ""); + } + + private static string UpgradeRedirect(Version version, string packageType, string packageName, string culture) + { + string url; + if (!string.IsNullOrEmpty(Config.GetSetting("UpdateServiceRedirect"))) + { + url = Config.GetSetting("UpdateServiceRedirect"); + } + else + { + url = DotNetNukeContext.Current.Application.UpgradeUrl + "/redirect.aspx"; + url += "?core=" + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, "00", 3, ""); + url += "&version=" + Globals.FormatVersion(version, "00", 3, ""); + url += "&type=" + packageType; + url += "&name=" + packageName; + if (!string.IsNullOrEmpty(culture)) + { + url += "&culture=" + culture; + } + } + return url; + } + + + private void GetLanguagePack(string downloadUrl, string installFolder) + { + string myfile = ""; + WebResponse wr = Util.GetExternalRequest(downloadUrl, + null, + null, + null, + null, + null, + -1, + null, + null, + false, + "DotNetNuke-Appgallery/1.0.0.0(Microsoft Windows NT 6.1.7600.0", + "wpi://2.1.0.0/Microsoft Windows NT 6.1.7600.0", + out myfile, + 10000); + //use fixed name for later installation + myfile = "installlanguage.resources"; + Util.DeployExtension(wr, myfile, installFolder); + } + + private static XmlNode AppendNewXmlNode(ref XmlDocument document, ref XmlNode parentNode, string elementName, string elementValue) + { + XmlNode newNode = document.CreateNode(XmlNodeType.Element, elementName, null); + if (!string.IsNullOrEmpty(elementValue)) + { + newNode.InnerText = elementValue; + } + parentNode.AppendChild(newNode); + return newNode; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/ActivateLicenseStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/ActivateLicenseStep.cs new file mode 100644 index 00000000000..b37d86b5a3a --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/ActivateLicenseStep.cs @@ -0,0 +1,68 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using DotNetNuke.Instrumentation; + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + /// ------------------------------------------------------------------------------------------------ + /// + /// DatabaseVerificationStep - Step that performs database verification checks prior to installation + /// + /// ------------------------------------------------------------------------------------------------ + public class ActivateLicenseStep : BaseInstallationStep + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ActivateLicenseStep)); + + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + Details = Localization.Localization.GetString("LicenseActivation", LocalInstallResourceFile); + var installConfig = InstallController.Instance.GetInstallConfig(); + var licenseConfig = (installConfig != null) ? installConfig.License : null; + + if (licenseConfig != null && (!string.IsNullOrEmpty(licenseConfig.AccountEmail) && !string.IsNullOrEmpty(licenseConfig.InvoiceNumber) + && !string.IsNullOrEmpty(licenseConfig.LicenseType) && !string.IsNullOrEmpty(licenseConfig.WebServer))) + { + try + { + var activationResult = ""; + activationResult = Upgrade.ActivateLicense(); + + if (!activationResult.ToLower().Contains("success")) + { + Errors.Add(Localization.Localization.GetString("LicenseActivation", LocalInstallResourceFile) + ": " + activationResult); + Logger.TraceFormat("ActivateLicense Status - {0}", activationResult); + } + } + catch (Exception ex) + { + Errors.Add(Localization.Localization.GetString("LicenseActivation", LocalInstallResourceFile) + ": " + ex.Message); + Logger.TraceFormat("ActivateLicense Status - {0}", ex.Message); + } + } + + Status = Errors.Count > 0 ? StepStatus.Retry : StepStatus.Done; + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/BaseInstallationStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/BaseInstallationStep.cs new file mode 100644 index 00000000000..91aaaa89a82 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/BaseInstallationStep.cs @@ -0,0 +1,103 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// BaseInstallationStep - Abstract class to perform common tasks for the various installation steps + /// + /// ----------------------------------------------------------------------------- + public abstract class BaseInstallationStep : IInstallationStep + { + #region Protected + + protected string LocalInstallResourceFile = "~/Install/App_LocalResources/InstallWizard.aspx.resx"; + protected string LocalUpgradeResourceFile = "~/Install/App_LocalResources/UpgradeWizard.aspx.resx"; + + #endregion + + #region Private + + private string _details = string.Empty; + + #endregion + + protected BaseInstallationStep() + { + Percentage = 0; + Errors = new List(); + } + + #region Implementation of IInstallationStep + + /// + /// Any details of the task while it's executing + /// + public string Details + { + get + { + return _details; + } + set + { + _details = value; + DnnInstallLogger.InstallLogInfo(_details); + if (Activity != null) + Activity(_details); + } + } + + /// + /// Percentage done + /// + public int Percentage { get; set; } + + /// + /// Step Status + /// + public StepStatus Status { get; set; } + + /// + /// List of Errors + /// + public IList Errors { get; set; } + + /// + /// Main method to execute the step + /// + public abstract void Execute(); + + /// + /// This event gets fired when any activity gets recorded + /// + public event ActivityEventHandler Activity; + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/FilePermissionCheckStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/FilePermissionCheckStep.cs new file mode 100644 index 00000000000..06bf7c55938 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/FilePermissionCheckStep.cs @@ -0,0 +1,94 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// FilePermissionCheck - Step that performs file permission checks prior to installation + /// + /// ----------------------------------------------------------------------------- + public class FilePermissionCheckStep : BaseInstallationStep + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (FilePermissionCheckStep)); + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var verifiers = new List + { + new FileSystemPermissionVerifier(HttpContext.Current.Server.MapPath("~")), + new FileSystemPermissionVerifier(HttpContext.Current.Server.MapPath("~/App_Data")) + }; + + //FolderCreate + Details = Localization.Localization.GetString("FolderCreateCheck", LocalInstallResourceFile); + Logger.TraceFormat("FilePermissionCheck - {0}", Details); + if(!verifiers.All(v => v.VerifyFolderCreate())) + Errors.Add(string.Format(Localization.Localization.GetString("StepFailed", LocalInstallResourceFile),Details)); + Percentage += 20; + + //FileCreate + Details = Localization.Localization.GetString("FileCreateCheck", LocalInstallResourceFile); + Logger.TraceFormat("FilePermissionCheck - {0}", Details); + if (!verifiers.All(v => v.VerifyFileCreate())) + Errors.Add(string.Format(Localization.Localization.GetString("StepFailed", LocalInstallResourceFile), Details)); + Percentage += 20; + + //FileDelete + Details = Localization.Localization.GetString("FileDeleteCheck", LocalInstallResourceFile); + Logger.TraceFormat("FilePermissionCheck - {0}", Details); + if (!verifiers.All(v => v.VerifyFileDelete())) + Errors.Add(string.Format(Localization.Localization.GetString("StepFailed", LocalInstallResourceFile), Details)); + Percentage += 20; + + //FolderDelete + Details = Localization.Localization.GetString("FolderDeleteCheck", LocalInstallResourceFile); + Logger.TraceFormat("FilePermissionCheck - {0}", Details); + if (!verifiers.All(v => v.VerifyFolderDelete())) + Errors.Add(string.Format(Localization.Localization.GetString("StepFailed", LocalInstallResourceFile), Details)); + Percentage += 20; + + Status = Errors.Count > 0 ? StepStatus.Retry : StepStatus.Done; + Logger.TraceFormat("FilePermissionCheck Status - {0}", Status); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/IISVerificationStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/IISVerificationStep.cs new file mode 100644 index 00000000000..ba25c22f1bb --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/IISVerificationStep.cs @@ -0,0 +1,45 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Web; + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + public class IISVerificationStep : BaseInstallationStep + { + public override void Execute() + { + Status = StepStatus.Running; + + Details = Localization.Localization.GetString("CheckingIIS", LocalInstallResourceFile); + + if (HttpRuntime.UsingIntegratedPipeline) + { + Status = StepStatus.Done; + } + else + { + Errors.Add(Localization.Localization.GetString("IISVerificationFail", LocalInstallResourceFile)); + Status = StepStatus.Abort; + } + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/IInstallationStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/IInstallationStep.cs new file mode 100644 index 00000000000..c454b89b7ed --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/IInstallationStep.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + + /// + /// This event gets fired when any activity gets recorded + /// + public delegate void ActivityEventHandler(string status); + + /// + /// Interface for an Installation Step + /// + /// ----------------------------------------------------------------------------- + public interface IInstallationStep + { + #region Properties + + /// + /// Any details of the task while it's executing + /// + string Details { get; } + + /// + /// Percentage done + /// + int Percentage { get; } + + /// + /// Step Status + /// + StepStatus Status { get; } + + /// + /// List of Errors + /// + IList Errors { get; } + + #endregion + + #region Methods + + /// + /// Main method to execute the step + /// + void Execute(); + + #endregion + + #region Events + + /// + /// This event gets fired when any activity gets recorded + /// + event ActivityEventHandler Activity; + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InitializeHostSettingsStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InitializeHostSettingsStep.cs new file mode 100644 index 00000000000..13af91452c6 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InitializeHostSettingsStep.cs @@ -0,0 +1,102 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallSuperUserStep - Step that installs SuperUser Account + /// + /// ----------------------------------------------------------------------------- + public class InitializeHostSettingsStep : BaseInstallationStep + { + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + Details = Localization.Localization.GetString("InitHostSetting", LocalInstallResourceFile); + var installConfig = InstallController.Instance.GetInstallConfig(); + + //Need to clear the cache to pick up new HostSettings from the SQLDataProvider script + DataCache.RemoveCache(DataCache.HostSettingsCacheKey); + + string domainName = Globals.GetDomainName(HttpContext.Current.Request); + foreach (var setting in installConfig.Settings) + { + var settingName = setting.Name; + var settingValue = setting.Value; + + switch (settingName) + { + case "HostURL": + if (string.IsNullOrEmpty(settingValue)) + { + settingValue = domainName; + } + break; + case "HostEmail": + if (string.IsNullOrEmpty(settingValue)) + { + settingValue = "support@" + domainName; + + //Remove any folders + settingValue = settingValue.Substring(0, settingValue.IndexOf("/")); + + //Remove port number + if (settingValue.IndexOf(":") != -1) + { + settingValue = settingValue.Substring(0, settingValue.IndexOf(":")); + } + } + + break; + } + HostController.Instance.Update(settingName, settingValue, setting.IsSecure); + } + + //Synchronise Host Folder + FolderManager.Instance.Synchronize(Null.NullInteger, "", true, true); + + Status = StepStatus.Done; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallDatabaseStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallDatabaseStep.cs new file mode 100644 index 00000000000..4bc84defe26 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallDatabaseStep.cs @@ -0,0 +1,182 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallDatabaseStep - Step that installs Database + /// + /// ----------------------------------------------------------------------------- + public class InstallDatabaseStep : BaseInstallationStep + { + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var counter = 0; + const int totalSteps = 6; + const int percentForEachStep = 100 / totalSteps; + var percentForMiniStep = 0; + + var installConfig = InstallController.Instance.GetInstallConfig(); + var providerPath = DataProvider.Instance().GetProviderPath(); + + //Step 1 - Install Base Database. Only when it's not already installed. Globals.DataBaseVersion is null when SPs are not present + if (Globals.DataBaseVersion == null) + { + var defaultProvider = Config.GetDefaultProvider("data").Name; + + percentForMiniStep = percentForEachStep / (installConfig.Scripts.Count + 1); + foreach (var script in installConfig.Scripts) + { + var scriptFile = providerPath + script + "." + defaultProvider; + var description = Localization.Localization.GetString("InstallingDataBaseScriptStep", LocalInstallResourceFile); + Details = description + Upgrade.GetFileNameWithoutExtension(scriptFile); + var exception = Upgrade.ExecuteScript(scriptFile, false); + if (!string.IsNullOrEmpty(exception)) + { + Errors.Add(exception); + Status = StepStatus.Retry; + return; + } + Percentage += percentForMiniStep; + } + + // update the version + Globals.UpdateDataBaseVersion(new Version(installConfig.Version)); + + Details = Localization.Localization.GetString("InstallingMembershipDatabaseScriptStep", LocalInstallResourceFile); + //Optionally Install the memberRoleProvider + var exceptions = Upgrade.InstallMemberRoleProvider(providerPath, false); + if (!string.IsNullOrEmpty(exceptions)) + { + Errors.Add(exceptions); + Status = StepStatus.Retry; + return; + } + } + Percentage = percentForEachStep * counter++; + + //Step 2 - Process the Upgrade Script files + var versions = new List(); + var scripts = Upgrade.GetUpgradeScripts(providerPath, DataProvider.Instance().GetVersion()); + if (scripts.Count > 0) + { + percentForMiniStep = percentForEachStep/(scripts.Count); + foreach (string scriptFile in scripts) + { + var fileName = Upgrade.GetFileNameWithoutExtension(scriptFile); + versions.Add(new Version(fileName)); + string description = Localization.Localization.GetString("ProcessingUpgradeScript", LocalInstallResourceFile); + Details = description + fileName; + var exceptions = Upgrade.UpgradeVersion(scriptFile, false); + if (!string.IsNullOrEmpty(exceptions)) + { + Errors.Add(exceptions); + Status = StepStatus.Retry; + return; + } + Percentage += percentForMiniStep; + } + } + Percentage = percentForEachStep * counter++; + + //Step 3 - Perform version specific application upgrades + foreach (Version ver in versions) + { + string description = Localization.Localization.GetString("UpgradingVersionApplication", LocalInstallResourceFile); + Details = description + ver; + var exceptions = Upgrade.UpgradeApplication(providerPath, ver, false); + if (!string.IsNullOrEmpty(exceptions)) + { + Errors.Add(exceptions); + Status = StepStatus.Retry; + return; + } + Percentage += percentForMiniStep; + } + Percentage = percentForEachStep * counter++; + + + //Step 4 - Execute config file updates + foreach (Version ver in versions) + { + string description = Localization.Localization.GetString("UpdatingConfigFile", LocalInstallResourceFile); + Details = description + ver; + var exceptions = Upgrade.UpdateConfig(providerPath, ver, false); + if (!string.IsNullOrEmpty(exceptions)) + { + Errors.Add(exceptions); + Status = StepStatus.Retry; + return; + } + Percentage += percentForMiniStep; + } + Percentage = percentForEachStep * counter++; + + //Step 5 - Delete files which are no longer used + foreach (Version ver in versions) + { + string description = Localization.Localization.GetString("DeletingOldFiles", LocalInstallResourceFile); + Details = description + ver; + var exceptions = Upgrade.DeleteFiles(providerPath, ver, false); + if (!string.IsNullOrEmpty(exceptions)) + { + Errors.Add(exceptions); + Status = StepStatus.Retry; + return; + } + Percentage += percentForMiniStep; + } + Percentage = percentForEachStep * counter++; + + //Step 6 - Perform general application upgrades + Details = Localization.Localization.GetString("UpgradingNormalApplication", LocalInstallResourceFile); + Upgrade.UpgradeApplication(); + + DataCache.ClearHostCache(true); + Percentage = percentForEachStep * counter++; + + Status = Errors.Count > 0 ? StepStatus.Retry : StepStatus.Done; + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallExtensionsStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallExtensionsStep.cs new file mode 100644 index 00000000000..3f6723d7477 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallExtensionsStep.cs @@ -0,0 +1,111 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using DotNetNuke.Common; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallExtensionsStep - Step that installs all the Extensions + /// + /// ----------------------------------------------------------------------------- + public class InstallExtensionsStep : BaseInstallationStep + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (InstallExtensionsStep)); + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var extensions = new string[] { "Module", "Skin", "Container", "Language", "Provider", "AuthSystem", "Package" }; + var percentForEachStep = 100 / extensions.Length; + var counter = 0; + + foreach (var extension in extensions) + { + try + { + InstallPackages(extension); + Percentage = percentForEachStep * counter++; + } + + catch (Exception ex) + { + Errors.Add(Localization.Localization.GetString("InstallingExtensionType", LocalInstallResourceFile) + ": " + ex.Message); + } + } + + Status = Errors.Count > 0 ? StepStatus.Retry : StepStatus.Done; + } + + #endregion + + #region private methods + + private void InstallPackages(string packageType) + { + + Details = string.Format(Localization.Localization.GetString("InstallingExtensionType", LocalInstallResourceFile), packageType); + Logger.Trace(Details); + var installPackagePath = Globals.ApplicationMapPath + "\\Install\\" + packageType; + if (Directory.Exists(installPackagePath)) + { + var files = Directory.GetFiles(installPackagePath); + if (files.Length > 0) + { + var percentForEachStep = 100/files.Length; + var counter = 0; + foreach (string file in files) + { + if (Path.GetExtension(file.ToLower()) == ".zip") + { + var message = string.Format(Localization.Localization.GetString("InstallingExtension", LocalInstallResourceFile), packageType, Path.GetFileName(file)); + Details = message; + Logger.Trace(Details); + var success = Upgrade.InstallPackage(file, packageType, false); + if (!success) + { + Errors.Add(message); + break; + } + } + Percentage = percentForEachStep * counter++; + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSiteStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSiteStep.cs new file mode 100644 index 00000000000..aa1855c8fb8 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSiteStep.cs @@ -0,0 +1,174 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security.Membership; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.InstallConfiguration; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallSiteStep - Step that installs Website + /// + /// ----------------------------------------------------------------------------- + public class InstallSiteStep : BaseInstallationStep + { + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + + //Set Status to None + Globals.SetStatus(Globals.UpgradeStatus.None); + + + var installConfig = InstallController.Instance.GetInstallConfig(); + var percentForEachStep = 100 / installConfig.Portals.Count; + var counter = 0; + foreach (var portal in installConfig.Portals) + { + string description = Localization.Localization.GetString("CreatingSite", LocalInstallResourceFile); + Details = string.Format(description, portal.PortalName); + CreateSite(portal, installConfig); + + counter++; + Percentage = percentForEachStep * counter++; + } + + Status = StepStatus.Done; + } + + #endregion + + #region Private Methods + + private void CreateSite(PortalConfig portal, InstallConfig installConfig) + { + + var domain = ""; + if ((HttpContext.Current != null)) + { + domain = Globals.GetDomainName(HttpContext.Current.Request, true).ToLowerInvariant().Replace("/install/launchautoinstall", "").Replace("/install", "").Replace("/runinstall", ""); + } + + var portalController = new PortalController(); + var serverPath = Globals.ApplicationMapPath + "\\"; + + //Get the Portal Alias + var portalAlias = domain; + if (portal.PortAliases.Count > 0) portalAlias = portal.PortAliases[0]; + + //Verify that portal alias is not present + if (PortalAliasController.GetPortalAliasLookup(portalAlias.ToLower()) != null) + { + string description = Localization.Localization.GetString("SkipCreatingSite", LocalInstallResourceFile); + Details = string.Format(description, portalAlias); + return; + } + + //Create default email + var email = portal.AdminEmail; + if (string.IsNullOrEmpty(email)) + { + email = "admin@" + domain.Replace("www.", ""); + //Remove any domain subfolder information ( if it exists ) + if (email.IndexOf("/") != -1) + { + email = email.Substring(0, email.IndexOf("/")); + } + } + + //install LP if installing in a different language + string culture = installConfig.InstallCulture; + if (!culture.Equals("en-us", StringComparison.InvariantCultureIgnoreCase)) + { + string installFolder = HttpContext.Current.Server.MapPath("~/Install/language"); + Upgrade.InstallPackage(installFolder + "\\installlanguage.resources", "Language", false); + } + + var template = Upgrade.FindBestTemplate(portal.TemplateFileName); + UserInfo userInfo; + + if (!String.IsNullOrEmpty(portal.AdminUserName)) + userInfo = Upgrade.CreateUserInfo(portal.AdminFirstName, portal.AdminLastName, portal.AdminUserName, portal.AdminPassword, email); + else + userInfo = Upgrade.CreateUserInfo(installConfig.SuperUser.FirstName, installConfig.SuperUser.LastName, installConfig.SuperUser.UserName, installConfig.SuperUser.Password, installConfig.SuperUser.Email); + + var childPath = string.Empty; + if (portal.IsChild) + childPath = portalAlias.Substring(portalAlias.LastIndexOf("/") + 1); + + //Create Portal + var portalId = portalController.CreatePortal(portal.PortalName, + userInfo, + portal.Description, + portal.Keywords, + template, + portal.HomeDirectory, + portalAlias, + serverPath, + serverPath + childPath, + portal.IsChild); + + if (portalId > -1) + { + foreach (var alias in portal.PortAliases) + { + portalController.AddPortalAlias(portalId, alias); + } + } + + //remove en-US from portal if installing in a different language + if (!culture.Equals("en-us", StringComparison.InvariantCultureIgnoreCase)) + { + var locale = LocaleController.Instance.GetLocale("en-US"); + Localization.Localization.RemoveLanguageFromPortal(portalId, locale.LanguageId); + } + + //Log user in to site + var loginStatus = UserLoginStatus.LOGIN_FAILURE; + UserController.UserLogin(portalId, userInfo.Username, installConfig.SuperUser.Password, "", "", "", ref loginStatus, false); + + InstallController.Instance.RemoveFromInstallConfig("//dotnetnuke/superuser/password"); + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSuperUserStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSuperUserStep.cs new file mode 100644 index 00000000000..1b611d3a0cf --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallSuperUserStep.cs @@ -0,0 +1,100 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// InstallSuperUserStep - Step that installs SuperUser Account + /// + /// ----------------------------------------------------------------------------- + public class InstallSuperUserStep : BaseInstallationStep + { + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + Details = Localization.Localization.GetString("CreateSuperUser", LocalInstallResourceFile); + var installConfig = InstallController.Instance.GetInstallConfig(); + + //Set admin user to be a superuser + var adminSuperUser = UserController.GetUserByName(0, installConfig.SuperUser.UserName); + if (adminSuperUser != null) + { + adminSuperUser.IsSuperUser = true; + adminSuperUser.Membership.UpdatePassword = false; + //refresh the profile to get definitions for super user. + adminSuperUser.Profile = null; + adminSuperUser.Profile.PreferredLocale = installConfig.SuperUser.Locale; + adminSuperUser.Profile.PreferredTimeZone = TimeZoneInfo.Local; + UserController.UpdateUser(0, adminSuperUser); + } + else + { + //Construct UserInfo object + var superUser = new UserInfo + { + PortalID = -1, + FirstName = installConfig.SuperUser.FirstName, + LastName = installConfig.SuperUser.LastName, + Username = installConfig.SuperUser.UserName, + DisplayName = installConfig.SuperUser.FirstName + " " + installConfig.SuperUser.LastName, + Membership = {Password = installConfig.SuperUser.Password}, + Email = installConfig.SuperUser.Email, + IsSuperUser = true + }; + superUser.Membership.Approved = true; + + superUser.Profile.FirstName = installConfig.SuperUser.FirstName; + superUser.Profile.LastName = installConfig.SuperUser.LastName; + superUser.Profile.PreferredLocale = installConfig.SuperUser.Locale; + superUser.Profile.PreferredTimeZone = TimeZoneInfo.Local; + superUser.Membership.UpdatePassword = false; + + //Create SuperUser if not present + if (UserController.GetUserByName(superUser.PortalID, superUser.Username) == null) + UserController.CreateUser(ref superUser); + } + + Details = Localization.Localization.GetString("CreatingSuperUser", LocalInstallResourceFile) + installConfig.SuperUser.UserName; + + Status = StepStatus.Done; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallVersionStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallVersionStep.cs new file mode 100644 index 00000000000..9e330b21f0a --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/InstallVersionStep.cs @@ -0,0 +1,56 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Instrumentation; + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + /// ------------------------------------------------------------------------------------------------ + /// + /// DatabaseVerificationStep - Step that performs database verification checks prior to installation + /// + /// ------------------------------------------------------------------------------------------------ + public class InstallVersionStep : BaseInstallationStep + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(InstallVersionStep)); + + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var databaseVersion = DataProvider.Instance().GetInstallVersion(); + + string strError = Config.UpdateInstallVersion(databaseVersion); + + if (!string.IsNullOrEmpty(strError)) + { + Errors.Add(Localization.Localization.GetString("InstallVersion", LocalInstallResourceFile) + ": " + strError); + Logger.TraceFormat("Adding InstallVersion : {0}", strError); + } + + Status = Errors.Count > 0 ? StepStatus.Retry : StepStatus.Done; + } + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/StepStatus.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/StepStatus.cs new file mode 100644 index 00000000000..738499d7e89 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/StepStatus.cs @@ -0,0 +1,65 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Upgrade.Internals.Steps +{ + /// + /// Status of an Installation Step + /// + /// ----------------------------------------------------------------------------- + public enum StepStatus + { + /// + /// Step not Started yet. + /// + NotStarted = 0, + + /// + /// Step is running. + /// + Running = 1, + + /// + /// Step is done and was successful. + /// + Done = 2, + + /// + /// Step failed. Retry the existing step. + /// + Retry = 3, + + /// + /// Step failed. Abort the next step. + /// + Abort = 4, + + /// + /// Step resulted in Application Restart. You should redirect to the same page. + /// + AppRestart = 5 + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/SynchConnectionStringStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/SynchConnectionStringStep.cs new file mode 100644 index 00000000000..10cca5fc0c5 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/SynchConnectionStringStep.cs @@ -0,0 +1,171 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// SynchConnectionStringStep - Step that synchs connection string between DotNetNuke.Install.Config and Web.Config + /// The connection information stored in DotNetNuke.Install.Config takes precendence (if present) + /// Synchornization only happens when settings are different + /// + /// ----------------------------------------------------------------------------- + public class SynchConnectionStringStep : BaseInstallationStep + { + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var installConfig = InstallController.Instance.GetInstallConfig(); + if(installConfig == null) + { + Status = StepStatus.Done; + return; + } + + var connectionConfig = installConfig.Connection; + if (connectionConfig == null) + { + Status = StepStatus.Done; + return; + } + + if (string.IsNullOrEmpty(connectionConfig.File) && string.IsNullOrEmpty(connectionConfig.Database)) + { + Errors.Add(Localization.Localization.GetString("RequiresFileOrDatabase", LocalInstallResourceFile)); + Status = StepStatus.Abort; + return; + } + + var builder = DataProvider.Instance().GetConnectionStringBuilder(); + + if (!string.IsNullOrEmpty(connectionConfig.Server)) + builder["Data Source"] = connectionConfig.Server; + + if (!string.IsNullOrEmpty(connectionConfig.Database)) + builder["Initial Catalog"] = connectionConfig.Database; + else if (!string.IsNullOrEmpty(connectionConfig.File)) + { + builder["attachdbfilename"] = "|DataDirectory|" + connectionConfig.File; + builder["user instance"] = "true"; + } + + if (connectionConfig.Integrated) + builder["integrated security"] = "true"; + + if (!string.IsNullOrEmpty(connectionConfig.User)) + builder["uid"] = connectionConfig.User; + + if (!string.IsNullOrEmpty(connectionConfig.Password)) + builder["pwd"] = connectionConfig.Password; + + string dbowner; + if (connectionConfig.RunAsDbowner) + { + dbowner = "dbo."; + } + else + { + dbowner = (string.IsNullOrEmpty(GetUpgradeConnectionStringUserID())) + ? connectionConfig.User + "." + : GetUpgradeConnectionStringUserID(); + } + + var connectionString = builder.ToString(); + + //load web.config connection string for comparison + var appConnectionString = Config.GetConnectionString(); + + var modified = false; + //save to web.config if different + if(appConnectionString.ToLower() != connectionString.ToLower()) + { + Config.UpdateConnectionString(connectionString); + modified = true; + } + + //Compare (and overwrite) Owner and Qualifier in Data Provider + if (Config.GetDataBaseOwner().ToLower() != dbowner.ToLower() || + (Config.GetObjectQualifer().ToLower() != connectionConfig.Qualifier.ToLower())) + { + Config.UpdateDataProvider("SqlDataProvider", dbowner, connectionConfig.Qualifier); + modified = true; + } + + //Compare (and overwrite) Owner and Qualifier in Data Provider + if (!string.IsNullOrEmpty(connectionConfig.UpgradeConnectionString) && Config.GetUpgradeConnectionString().ToLower() != connectionConfig.UpgradeConnectionString.ToLower()) + { + Config.UpdateUpgradeConnectionString("SqlDataProvider", connectionConfig.UpgradeConnectionString); + modified = true; + } + + Status = modified ? StepStatus.AppRestart : StepStatus.Done; + } + + #endregion + + #region Private Methods + + private string GetUpgradeConnectionStringUserID() + { + string dbUser = ""; + string connection = Config.GetUpgradeConnectionString(); + + //If connection string does not use integrated security, then get user id. + if (connection.ToLower().Contains("user id") || connection.ToLower().Contains("uid") || connection.ToLower().Contains("user")) + { + string[] connectionParams = connection.Split(';'); + + foreach (string connectionParam in connectionParams) + { + int index = connectionParam.IndexOf("="); + if (index > 0) + { + string key = connectionParam.Substring(0, index); + string value = connectionParam.Substring(index + 1); + if ("user id|uuid|user".Contains(key.Trim().ToLower())) + { + dbUser = value.Trim(); + } + } + } + } + return dbUser; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/Steps/UpdateLanguagePackStep.cs b/DNN Platform/Library/Services/Upgrade/Internals/Steps/UpdateLanguagePackStep.cs new file mode 100644 index 00000000000..a4237e6e8c8 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/Steps/UpdateLanguagePackStep.cs @@ -0,0 +1,87 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; +using System.Web.Configuration; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; + +#endregion + +namespace DotNetNuke.Services.Upgrade.InternalController.Steps +{ + /// ----------------------------------------------------------------------------- + /// + /// UpdateLanguagePackStep - Step that downloads and installs language pack + /// + /// ----------------------------------------------------------------------------- + public class UpdateLanguagePackStep : BaseInstallationStep + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof(UpdateLanguagePackStep)); + #region Implementation of IInstallationStep + + /// + /// Main method to execute the step + /// + public override void Execute() + { + Percentage = 0; + Status = StepStatus.Running; + + var installConfig = InstallController.Instance.GetInstallConfig(); + string culture = installConfig.InstallCulture; + + if (culture.ToLower() != "en-us") + { + try + { + //need apply the Licensing module after packages installed, so that we can know whats the edition of install instance. CE/PE/EE + var document = Config.Load(); + var licensingNode = document.SelectSingleNode("/configuration/system.webServer/modules/add[@name='Licensing']"); + if (licensingNode != null) + { + var type = licensingNode.Attributes["type"].Value; + var module = Reflection.CreateObject(type, null, false) as IHttpModule; + module.Init(HttpContext.Current.ApplicationInstance); + } + + InstallController.Instance.IsAvailableLanguagePack(culture); + } + catch (Exception ex) + { + //we shouldn't break the install process when LP download failed, for admin user can install the LP after website created. + //so we logged what's wrong here, and user can check it later. + Logger.Error(ex); + } + + } + Status = StepStatus.Done; + } + + #endregion + } +} diff --git a/DNN Platform/Library/Services/Upgrade/Internals/UpdateService.cs b/DNN Platform/Library/Services/Upgrade/Internals/UpdateService.cs new file mode 100644 index 00000000000..49b9ef4d4ef --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Internals/UpdateService.cs @@ -0,0 +1,98 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.IO; +using System.Net; + +using DotNetNuke.Application; +using DotNetNuke.Common; + +namespace DotNetNuke.Services.Upgrade.Internals +{ + public class UpdateService + { + private static String ApplicationVersion + { + get + { + return Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, "00", 3, ""); + } + } + + private static String ApplicationName + { + get + { + return DotNetNukeContext.Current.Application.Name; + } + } + + + public static StreamReader GetLanguageList() + { + String url = DotNetNukeContext.Current.Application.UpgradeUrl + "/languages.aspx"; + url += "?core=" + ApplicationVersion; + url += "&type=Framework"; + url += "&name=" + ApplicationName; + + StreamReader myResponseReader = GetResponseAsStream(url); + return myResponseReader; + } + + public static String GetLanguageDownloadUrl(String cultureCode) + { + String url = DotNetNukeContext.Current.Application.UpgradeUrl + "/languages.aspx"; + url += "?core=" + ApplicationVersion; + url += "&type=Framework"; + url += "&name=" + ApplicationName; + url += "&culture=" + cultureCode; + + StreamReader myResponseReader = GetResponseAsStream(url); + string downloadUrl = myResponseReader.ReadToEnd(); + return downloadUrl; + } + + private static StreamReader GetResponseAsStream(string url) + { + //creating the proxy for the service call using the HttpWebRequest class + var webReq = (HttpWebRequest) WebRequest.Create(url); + + //Set the method/action type + webReq.Method = "GET"; + + //We use form contentType + webReq.ContentType = "text/xml; charset=utf-8"; + + //Get the response handle, we have no true response yet! + var webResp = (HttpWebResponse) webReq.GetResponse(); + + //Now, we read the response (the string), and output it. + Stream myResponse = webResp.GetResponseStream(); + + //read the stream into streamreader + var myResponseReader = new StreamReader(myResponse); + return myResponseReader; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Upgrade/Upgrade.cs b/DNN Platform/Library/Services/Upgrade/Upgrade.cs new file mode 100644 index 00000000000..3f612a945a2 --- /dev/null +++ b/DNN Platform/Library/Services/Upgrade/Upgrade.cs @@ -0,0 +1,5310 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Data.SqlClient; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.Configuration; +using System.Xml; +using System.Xml.XPath; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Content; +using DotNetNuke.Entities.Content.Taxonomy; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Entities.Users.Social; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Modules.Dashboard.Components.Modules; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Analytics; +using DotNetNuke.Services.Authentication; +using DotNetNuke.Services.EventQueue.Config; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Installer; +using DotNetNuke.Services.Installer.Log; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Localization.Internal; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Social.Messaging.Internal; +using DotNetNuke.Services.Social.Notifications; +using DotNetNuke.Services.Upgrade.InternalController.Steps; +using DotNetNuke.Services.Upgrade.Internals; +using DotNetNuke.Services.Upgrade.Internals.Steps; +using DotNetNuke.UI.Internals; + +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; +using ModuleInfo = DotNetNuke.Entities.Modules.ModuleInfo; +using Util = DotNetNuke.Entities.Content.Common.Util; + +#endregion + +namespace DotNetNuke.Services.Upgrade +{ + ///----------------------------------------------------------------------------- + /// + /// The Upgrade class provides Shared/Static methods to Upgrade/Install + /// a DotNetNuke Application + /// + /// + /// + /// + /// [cnurse] 11/6/2004 documented + /// + ///----------------------------------------------------------------------------- + public class Upgrade + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Upgrade)); + #region Private Shared Field + + private static DateTime _startTime; + + #endregion + + #region Public Properties + + public static string DefaultProvider + { + get + { + return Config.GetDefaultProvider("data").Name; + } + } + + public static TimeSpan RunTime + { + get + { + DateTime currentTime = DateTime.Now; + return currentTime.Subtract(_startTime); + } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// AddAdminPages adds an Admin Page and an associated Module to all configured Portals + /// + /// The Name to give this new Tab + /// Description. + /// The Icon for this new Tab + /// The large Icon for this new Tab + /// A flag indicating whether the tab is visible + /// The Module Deinition Id for the module to be aded to this tab + /// The Module's title + /// The Module's icon + /// + /// [cnurse] 11/16/2004 created + /// + /// ----------------------------------------------------------------------------- + private static void AddAdminPages(string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible, int moduleDefId, string moduleTitle, string moduleIconFile) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddAdminPages:" + tabName); + //Call overload with InheritPermisions=True + AddAdminPages(tabName, description, tabIconFile, tabIconFileLarge, isVisible, moduleDefId, moduleTitle, moduleIconFile, true); + + } + + private static void AddAdminRoleToPage(string tabPath) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddAdminRoleToPage:" + tabPath); + var portalController = new PortalController(); + var tabController = new TabController(); + TabInfo tab; + + foreach (PortalInfo portal in portalController.GetPortals()) + { + int tabID = TabController.GetTabByTabPath(portal.PortalID, tabPath, Null.NullString); + if ((tabID != Null.NullInteger)) + { + tab = tabController.GetTab(tabID, portal.PortalID, true); + + if ((tab.TabPermissions.Count == 0)) + { + AddPagePermission(tab.TabPermissions, "View", Convert.ToInt32(portal.AdministratorRoleId)); + AddPagePermission(tab.TabPermissions, "Edit", Convert.ToInt32(portal.AdministratorRoleId)); + TabPermissionController.SaveTabPermissions(tab); + } + } + } + } + + private static void AddConsoleModuleSettings(int moduleID) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddConsoleModuleSettings:" + moduleID); + var moduleController = new ModuleController(); + + moduleController.UpdateModuleSetting(moduleID, "DefaultSize", "IconFileLarge"); + moduleController.UpdateModuleSetting(moduleID, "AllowSizeChange", "False"); + moduleController.UpdateModuleSetting(moduleID, "DefaultView", "Hide"); + moduleController.UpdateModuleSetting(moduleID, "AllowViewChange", "False"); + moduleController.UpdateModuleSetting(moduleID, "ShowTooltip", "True"); + } + + private static void AddEventQueueApplicationStartFirstRequest() + { + //Add new EventQueue Event + var config = EventQueueConfiguration.GetConfig(); + if (config != null) + { + if (!config.PublishedEvents.ContainsKey("Application_Start_FirstRequest")) + { + foreach (SubscriberInfo subscriber in config.EventQueueSubscribers.Values) + { + EventQueueConfiguration.RegisterEventSubscription(config, "Application_Start_FirstRequest", subscriber); + } + + EventQueueConfiguration.SaveConfig(config, string.Format("{0}EventQueue\\EventQueue.config", Globals.HostMapPath)); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleControl adds a new Module Control to the system + /// + /// + /// + /// The Module Definition Id + /// The key for this control in the Definition + /// The title of this control + /// Te source of ths control + /// The icon file + /// The type of control + /// The vieworder for this module + /// The Help Url + /// + /// [cnurse] 11/08/2004 documented + /// + /// ----------------------------------------------------------------------------- + private static void AddModuleControl(int moduleDefId, string controlKey, string controlTitle, string controlSrc, string iconFile, SecurityAccessLevel controlType, int viewOrder, string helpURL) + { + AddModuleControl(moduleDefId, controlKey, controlTitle, controlSrc, iconFile, controlType, viewOrder, helpURL, false); + } + + private static void AddModuleControl(int moduleDefId, string controlKey, string controlTitle, string controlSrc, string iconFile, SecurityAccessLevel controlType, int viewOrder, string helpURL, bool supportsPartialRendering) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddModuleControl:" + moduleDefId); + // check if module control exists + var moduleControl = ModuleControlController.GetModuleControlByControlKey(controlKey, moduleDefId); + if (moduleControl == null) + { + moduleControl = new ModuleControlInfo + { + ModuleControlID = Null.NullInteger, + ModuleDefID = moduleDefId, + ControlKey = controlKey, + ControlTitle = controlTitle, + ControlSrc = controlSrc, + ControlType = controlType, + ViewOrder = viewOrder, + IconFile = iconFile, + HelpURL = helpURL, + SupportsPartialRendering = supportsPartialRendering + }; + + ModuleControlController.AddModuleControl(moduleControl); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleDefinition adds a new Core Module Definition to the system + /// + /// + /// This overload allows the caller to determine whether the module has a controller + /// class + /// + /// The Friendly Name of the Module to Add + /// Description of the Module + /// The Module Definition Name + /// A flag representing whether the module is a Premium module + /// A flag representing whether the module is an Admin module + /// The Module Definition Id of the new Module + /// + /// [cnurse] 10/14/2004 documented + /// [cnurse] 11/11/2004 removed addition of Module Control (now in AddMOduleControl) + /// + /// ----------------------------------------------------------------------------- + private static int AddModuleDefinition(string desktopModuleName, string description, string moduleDefinitionName, bool premium, bool admin) + { + return AddModuleDefinition(desktopModuleName, description, moduleDefinitionName, "", false, premium, admin); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleDefinition adds a new Core Module Definition to the system + /// + /// + /// This overload allows the caller to determine whether the module has a controller + /// class + /// + /// The Friendly Name of the Module to Add + /// Description of the Module + /// The Module Definition Name + /// Business Control Class. + /// Whether the module is enable for portals. + /// A flag representing whether the module is a Premium module + /// A flag representing whether the module is an Admin module + /// The Module Definition Id of the new Module + /// + /// [cnurse] 10/14/2004 documented + /// [cnurse] 11/11/2004 removed addition of Module Control (now in AddMOduleControl) + /// + /// ----------------------------------------------------------------------------- + private static int AddModuleDefinition(string desktopModuleName, string description, string moduleDefinitionName, string businessControllerClass, bool isPortable, bool premium, bool admin) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddModuleDefinition:" + desktopModuleName); + // check if desktop module exists + var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(desktopModuleName, Null.NullInteger); + if (desktopModule == null) + { + var package = new PackageInfo + { + Description = description, + FriendlyName = desktopModuleName, + Name = string.Concat("DotNetNuke.", desktopModuleName), + PackageType = "Module", + Owner = "DotNetNuke", + Organization = "DotNetNuke Corporation", + Url = "www.dotnetnuke.com", + Email = "support@dotnetnuke.com" + }; + if (desktopModuleName == "Extensions" || desktopModuleName == "Skin Designer" || desktopModuleName == "Dashboard") + { + package.IsSystemPackage = true; + } + package.Version = new Version(1, 0, 0); + + package.PackageID = PackageController.AddPackage(package, false); + + string moduleName = desktopModuleName.Replace(" ", ""); + desktopModule = new DesktopModuleInfo + { + DesktopModuleID = Null.NullInteger, + PackageID = package.PackageID, + FriendlyName = desktopModuleName, + FolderName = "Admin/" + moduleName, + ModuleName = moduleName, + Description = description, + Version = "01.00.00", + BusinessControllerClass = businessControllerClass, + IsPortable = isPortable, + SupportedFeatures = 0 + }; + if ((isPortable)) + { + desktopModule.SupportedFeatures = 1; + } + desktopModule.IsPremium = premium; + desktopModule.IsAdmin = admin; + + desktopModule.DesktopModuleID = DesktopModuleController.SaveDesktopModule(desktopModule, false, false); + + if (!premium) + { + DesktopModuleController.AddDesktopModuleToPortals(desktopModule.DesktopModuleID); + } + } + + // check if module definition exists + var moduleDefinition = ModuleDefinitionController.GetModuleDefinitionByFriendlyName(moduleDefinitionName, desktopModule.DesktopModuleID); + if (moduleDefinition == null) + { + moduleDefinition = new ModuleDefinitionInfo {ModuleDefID = Null.NullInteger, DesktopModuleID = desktopModule.DesktopModuleID, FriendlyName = moduleDefinitionName}; + + moduleDefinition.ModuleDefID = ModuleDefinitionController.SaveModuleDefinition(moduleDefinition, false, false); + } + return moduleDefinition.ModuleDefID; + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleToPage adds a module to a Page + /// + /// + /// This overload assumes ModulePermissions will be inherited + /// + /// The Page to add the Module to + /// The Module Deinition Id for the module to be aded to this tab + /// The Module's title + /// The Module's icon + /// + /// [cnurse] 11/11/2004 created + /// + /// ----------------------------------------------------------------------------- + private static int AddModuleToPage(TabInfo page, int moduleDefId, string moduleTitle, string moduleIconFile) + { + //Call overload with InheritPermisions=True + return AddModuleToPage(page, moduleDefId, moduleTitle, moduleIconFile, true); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPage adds a Tab Page + /// + /// + /// Adds a Tab to a parentTab + /// + /// The Parent Tab + /// The Name to give this new Tab + /// Description. + /// The Icon for this new Tab + /// The Large Icon for this new Tab + /// A flag indicating whether the tab is visible + /// Page Permissions Collection for this page + /// Is an admin page + /// + /// [cnurse] 11/11/2004 created + /// + /// ----------------------------------------------------------------------------- + private static TabInfo AddPage(TabInfo parentTab, string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible, TabPermissionCollection permissions, bool isAdmin) + { + int parentId = Null.NullInteger; + int portalId = Null.NullInteger; + + if ((parentTab != null)) + { + parentId = parentTab.TabID; + portalId = parentTab.PortalID; + } + + + return AddPage(portalId, parentId, tabName, description, tabIconFile, tabIconFileLarge, isVisible, permissions, isAdmin); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPage adds a Tab Page + /// + /// The Id of the Portal + /// The Id of the Parent Tab + /// The Name to give this new Tab + /// Description. + /// The Icon for this new Tab + /// The large Icon for this new Tab + /// A flag indicating whether the tab is visible + /// Page Permissions Collection for this page + /// Is and admin page + /// + /// [cnurse] 11/11/2004 created + /// + /// ----------------------------------------------------------------------------- + private static TabInfo AddPage(int portalId, int parentId, string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible, TabPermissionCollection permissions, bool isAdmin) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddPage:" + tabName); + var tabController = new TabController(); + + TabInfo tab = tabController.GetTabByName(tabName, portalId, parentId); + + if (tab == null || tab.ParentId != parentId) + { + tab = new TabInfo + { + TabID = Null.NullInteger, + PortalID = portalId, + TabName = tabName, + Title = "", + Description = description, + KeyWords = "", + IsVisible = isVisible, + DisableLink = false, + ParentId = parentId, + IconFile = tabIconFile, + IconFileLarge = tabIconFileLarge, + IsDeleted = false + }; + tab.TabID = tabController.AddTab(tab, !isAdmin); + + if (((permissions != null))) + { + foreach (TabPermissionInfo tabPermission in permissions) + { + tab.TabPermissions.Add(tabPermission, true); + } + TabPermissionController.SaveTabPermissions(tab); + } + } + return tab; + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPagePermission adds a TabPermission to a TabPermission Collection + /// + /// Page Permissions Collection for this page + /// The Permission key + /// The role given the permission + /// + /// [cnurse] 11/11/2004 created + /// + /// ----------------------------------------------------------------------------- + private static void AddPagePermission(TabPermissionCollection permissions, string key, int roleId) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddPagePermission:" + key); + var permissionController = new PermissionController(); + var permission = (PermissionInfo) permissionController.GetPermissionByCodeAndKey("SYSTEM_TAB", key)[0]; + + var tabPermission = new TabPermissionInfo {PermissionID = permission.PermissionID, RoleID = roleId, AllowAccess = true}; + + permissions.Add(tabPermission); + } + + private static void AddProfessionalPreviewPage(int parentId, string tabPath, string moduleFriendlyName, string tabName, string tabDescription, string smallIcon, string largeIcon) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddProfessionalPreviewPage:" + parentId); + var tabController = new TabController(); + TabInfo hostTab; + + //Get web servers module + ModuleDefinitionInfo moduleDef = ModuleDefinitionController.GetModuleDefinitionByFriendlyName(moduleFriendlyName); + + //Add Pages under Professional Features Tab + int tabId = TabController.GetTabByTabPath(Null.NullInteger, tabPath, Null.NullString); + if (tabId == Null.NullInteger) + { + //Add host page + hostTab = AddHostPage(tabName, tabDescription, smallIcon, largeIcon, true); + hostTab.ParentId = parentId; + tabController.UpdateTab(hostTab); + + //Add module to page + AddModuleToPage(hostTab, moduleDef.ModuleDefID, tabName, largeIcon, true); + } + } + + private static void AddLinkedProfessionalPreviewPage(int parentId, string tabPath, string url, string tabName, string tabDescription, string smallIcon, string largeIcon) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddLinkedProfessionalPreviewPage:" + parentId); + var tabController = new TabController(); + TabInfo newTab; + + if (TabController.GetTabByTabPath(Null.NullInteger, tabPath, Null.NullString) == Null.NullInteger) + { + newTab = AddHostPage(tabName, tabDescription, smallIcon, largeIcon, true); + newTab.ParentId = parentId; + newTab.Url = url; + tabController.UpdateTab(newTab); + } + } + + private static void AddProfessionalPreviewPages() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddProfessionalPreviewPages:"); + var tabController = new TabController(); + TabInfo newTab; + + //Add new Professional Preview module + int moduleDefID = AddModuleDefinition("ProfessionalPreview", "", "ProfessionalPreview", false, true); + AddModuleControl(moduleDefID, "", "", "DesktopModules/Admin/ProfessionalPreview/ProfessionalPreview.ascx", "~/images/icon_profeatures_16px.png", SecurityAccessLevel.Host, 0); + + //Add Advanced Features - hidden tab + int advancedFeaturesTabID = TabController.GetTabByTabPath(Null.NullInteger, "//Host//ProfessionalFeatures", Null.NullString); + if (advancedFeaturesTabID == Null.NullInteger) + { + newTab = AddHostPage("Professional Features", "", "~/images/icon_profeatures_16px.gif", "", true); + newTab.DisableLink = true; + tabController.UpdateTab(newTab); + advancedFeaturesTabID = newTab.TabID; + } + + //Add Pages under Advanced Features Tab + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//ManageWebServers", + "ProfessionalPreview", + "Manage Web Servers", + "Manage web servers in a web farm.", + "~/images/icon_webservers_16px.gif", + "~/images/icon_webservers_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//HealthMonitoring", + "ProfessionalPreview", + "Health Monitoring", + "Monitor health of your DotNetNuke web site.", + "~/images/icon_health_16px.gif", + "~/images/icon_health_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//ApplicationIntegrity", + "ProfessionalPreview", + "Application Integrity", + "View files that are different than the core framework version.", + "~/images/icon_appintegrity_16px.gif", + "~/images/icon_appintegrity_32px.gif"); + + AddLinkedProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//KnowledgeBase", + "http://customers.dotnetnuke.com/KB/root.aspx", + "Knowledge Base", + "Comprehensive Knowledge Base that provides guidance for DotNetNuke administrative tasks and answers to common technical questions.", + "~/images/icon_kb_16px.gif", + "~/images/icon_kb_32px.gif"); + + AddLinkedProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//SoftwareAndDocumentation", + "http://www.dotnetnuke.com/Resources/Manuals/tabid/1667/Default.aspx", + "Software and Documentation", + "Download upgrades, subscribed products and additional documentation for professional edition customers.", + "~/images/icon_software_16px.gif", + "~/images/icon_software_32px.gif"); + + AddLinkedProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//TechnicalSupport", + "http://customers.dotnetnuke.com", + "Technical Support", + "Visit the technical support home page to find the latest support news, knowledge base articles and more.", + "~/images/icon_support_16px.gif", + "~/images/icon_support_32px.gif"); + + AddLinkedProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//MySupportTickets", + "http://customers.dotnetnuke.com/Main/frmTickets.aspx", + "My Support Tickets", + "The Support Ticket system will allow you to email support questions to our staff. A staff member will promptly reply to your request and progress will be tracked using the ticket. You can 'Start a new Ticket' and view your existing tickets here.", + "~/images/icon_mytickets_16px.gif", + "~/images/icon_mytickets_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//ActivateyourLicense", + "ProfessionalPreview", + "Activate Your License", + "Activate your DotNetNuke Professional licenses. Activating your license will ensure that you continue to receive the benefits provided to our customers.", + "~/images/icon_activatelicense_16px.gif", + "~/images/icon_activatelicense_32px.gif"); + + AddLinkedProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//LicenseManagement", + "http://www.dotnetnuke.com/tabid/1205/Default.aspx", + "License Management", + "Manage licenses for your subscribed products.", + "~/images/icon_licensemgmt_16px.gif", + "~/images/icon_licensemgmt_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//SearchCrawlerAdmin", + "ProfessionalPreview", + "SearchCrawler Admin", + "Administration of Search Crawler attributes..", + "~/images/SearchCrawler_16px.gif", + "~/images/SearchCrawler_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//SecurityCenter", + "ProfessionalPreview", + "Security Center", + "Displays Security Bulletins for this instance of DotNetNuke.", + "~/images/icon_securityroles_16px.gif", + "~/images/icon_securityroles_32px.gif"); + + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//UserSwitcher", + "ProfessionalPreview", + "User Switcher", + "Switch to another user's identity.", + "~/images/icon_usersSwitcher_16px.gif", + "~/images/icon_usersSwitcher_32px.gif"); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddSearchResults adds a top level Hidden Search Results Page + /// + /// The Module Deinition Id for the Search Results Module + /// + /// [cnurse] 11/11/2004 created + /// + /// ----------------------------------------------------------------------------- + private static void AddSearchResults(int moduleDefId) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddSearchResults:" + moduleDefId); + var portalController = new PortalController(); + PortalInfo portal; + var portals = portalController.GetPortals(); + int intPortal; + + //Add Page to Admin Menu of all configured Portals + for (intPortal = 0; intPortal <= portals.Count - 1; intPortal++) + { + var tabPermissions = new TabPermissionCollection(); + + portal = (PortalInfo) portals[intPortal]; + + AddPagePermission(tabPermissions, "View", Convert.ToInt32(Globals.glbRoleAllUsers)); + AddPagePermission(tabPermissions, "View", Convert.ToInt32(portal.AdministratorRoleId)); + AddPagePermission(tabPermissions, "Edit", Convert.ToInt32(portal.AdministratorRoleId)); + + //Create New Page (or get existing one) + var tab = AddPage(portal.PortalID, Null.NullInteger, "Search Results", "", "", "", false, tabPermissions, false); + + //Add Module To Page + AddModuleToPage(tab, moduleDefId, "Search Results", ""); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// AddSkinControl adds a new Module Control to the system + /// + /// + /// + /// The key for this control in the Definition + /// Package Name. + /// Te source of ths control + /// + /// [cnurse] 05/26/2008 created + /// + /// ----------------------------------------------------------------------------- + private static void AddSkinControl(string controlKey, string packageName, string controlSrc) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddSkinControl:" + controlKey); + // check if skin control exists + SkinControlInfo skinControl = SkinControlController.GetSkinControlByKey(controlKey); + if (skinControl == null) + { + var package = new PackageInfo {Name = packageName, FriendlyName = string.Concat(controlKey, "SkinObject"), PackageType = "SkinObject", Version = new Version(1, 0, 0)}; + LegacyUtil.ParsePackageName(package); + + int packageId = PackageController.AddPackage(package, false); + + skinControl = new SkinControlInfo {PackageID = packageId, ControlKey = controlKey, ControlSrc = controlSrc, SupportsPartialRendering = false}; + + SkinControlController.SaveSkinControl(skinControl); + } + } + + private static void AddDefaultModuleIcons() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddDefaultModuleIcons"); + var pkg = PackageController.GetPackageByName("DotNetNuke.Google Analytics"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Analytics"; + pkg.IconFile = "~/DesktopModules/Admin/Analytics/analytics.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Configuration Manager"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/XmlMerge"; + pkg.IconFile = "~/DesktopModules/Admin/XmlMerge/xmlMerge.png"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Console"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Console"; + pkg.IconFile = "~/DesktopModules/Admin/Console/console.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.ContentList"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/ContentList"; + pkg.IconFile = "~/DesktopModules/Admin/ContentList/contentList.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Dashboard"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Dashboard"; + pkg.IconFile = "~/DesktopModules/Admin/Dashboard/dashboard.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Languages"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Languages"; + pkg.IconFile = "~/DesktopModules/Admin/Languages/languages.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Marketplace"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Marketplace"; + pkg.IconFile = "~/DesktopModules/Admin/Marketplace/marketplace.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Sitemap"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Sitemap"; + pkg.IconFile = "~/DesktopModules/Admin/Sitemap/sitemap.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Skin Designer"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/SkinDesigner"; + pkg.IconFile = "~/DesktopModules/Admin/SkinDesigner/skinDesigner.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.Skins"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/Skins"; + pkg.IconFile = "~/DesktopModules/Admin/Skins/skins.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.ViewProfile"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/ViewProfile"; + pkg.IconFile = "~/DesktopModules/Admin/ViewProfile/viewProfile.gif"; + PackageController.UpdatePackage(pkg); + } + + pkg = PackageController.GetPackageByName("DotNetNuke.ProfessionalPreview"); + if (pkg != null) + { + pkg.FolderName = "DesktopModules/Admin/ProfessionalPreview"; + pkg.IconFile = "~/DesktopModules/Admin/ProfessionalPreview/professionalPreview.gif"; + PackageController.UpdatePackage(pkg); + } + } + + private static void AddModuleCategories() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddModuleCategories"); + DesktopModuleController.AddModuleCategory("< None >"); + DesktopModuleController.AddModuleCategory("Admin"); + DesktopModuleController.AddModuleCategory("Common"); + + + foreach (var desktopModuleInfo in DesktopModuleController.GetDesktopModules(Null.NullInteger)) + { + bool update = false; + switch (desktopModuleInfo.Value.ModuleName) + { + case "Portals": + case "SQL": + case "HostSettings": + case "Scheduler": + case "SearchAdmin": + case "Lists": + case "Extensions": + case "WhatsNew": + case "Dashboard": + case "Marketplace": + case "ConfigurationManager": + case "Security": + case "Tabs": + case "Vendors": + case "Banners": + case "FileManager": + case "SiteLog": + case "Newsletters": + case "RecycleBin": + case "LogViewer": + case "SiteWizard": + case "Languages": + case "Skins": + case "SkinDesigner": + case "GoogleAnalytics": + case "Sitemap": + case "DotNetNuke.Taxonomy": + desktopModuleInfo.Value.Category = "Admin"; + update = true; + break; + default: + break; + } + if (update) + { + if (desktopModuleInfo.Value.PackageID == Null.NullInteger) + { + LegacyUtil.ProcessLegacyModule(desktopModuleInfo.Value); + } + DesktopModuleController.SaveDesktopModule(desktopModuleInfo.Value, false, false); + } + } + } + + private static int CountLegacyFiles() + { + return DataProvider.Instance().CountLegacyFiles(); + } + + + + /// ----------------------------------------------------------------------------- + /// + /// CoreModuleExists determines whether a Core Module exists on the system + /// + /// + /// + /// The Friendly Name of the Module + /// True if the Module exists, otherwise False + /// + /// [cnurse] 10/14/2004 documented + /// + /// ----------------------------------------------------------------------------- + private static bool CoreModuleExists(string desktopModuleName) + { + var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(desktopModuleName, Null.NullInteger); + + return ((desktopModule != null)); + } + + private static void EnableModalPopUps() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "EnableModalPopUps"); + foreach (var desktopModuleInfo in DesktopModuleController.GetDesktopModules(Null.NullInteger)) + { + switch (desktopModuleInfo.Value.ModuleName) + { + case "Portals": + case "SQL": + case "HostSettings": + case "Scheduler": + case "SearchAdmin": + case "Lists": + case "Extensions": + case "WhatsNew": + case "Dashboard": + case "Marketplace": + case "ConfigurationManager": + case "Security": + case "Tabs": + case "Vendors": + case "Banners": + case "FileManager": + case "SiteLog": + case "Newsletters": + case "RecycleBin": + case "LogViewer": + case "SiteWizard": + case "Languages": + case "Skins": + case "SkinDesigner": + case "GoogleAnalytics": + case "Sitemap": + case "DotNetNuke.Taxonomy": + foreach(ModuleDefinitionInfo definition in desktopModuleInfo.Value.ModuleDefinitions.Values) + { + foreach(ModuleControlInfo control in definition.ModuleControls.Values) + { + if (!String.IsNullOrEmpty(control.ControlKey)) + { + control.SupportsPopUps = true; + ModuleControlController.SaveModuleControl(control, false); + } + } + } + break; + default: + break; + } + } + + foreach(ModuleControlInfo control in ModuleControlController.GetModuleControlsByModuleDefinitionID(Null.NullInteger).Values) + { + control.SupportsPopUps = true; + ModuleControlController.SaveModuleControl(control, false); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ExecuteScript executes a SQl script file + /// + /// + /// + /// The script to Execute + /// Need to output feedback message. + /// + /// [cnurse] 11/09/2004 created + /// + /// ----------------------------------------------------------------------------- + internal static string ExecuteScript(string scriptFile, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "ExecuteScript:" + scriptFile); + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, Localization.Localization.GetString("ExecutingScript", Localization.Localization.GlobalResourceFile) + ":" + Path.GetFileName(scriptFile)); + } + + // read script file for installation + string script = FileSystemUtils.ReadFile(scriptFile); + + // execute SQL installation script + string exceptions = DataProvider.Instance().ExecuteScript(script); + + //add installer logging + if (string.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "ExecuteScript:" + scriptFile); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + + // log the results + try + { + using (var streamWriter = File.CreateText(scriptFile.Replace("." + DefaultProvider, "") + ".log.resources")) + { + streamWriter.WriteLine(exceptions); + streamWriter.Close(); + } + } + catch (Exception exc) + { + //does not have permission to create the log file + Logger.Error(exc); + } + + if (writeFeedback) + { + string resourcesFile = Path.GetFileName(scriptFile); + if (!String.IsNullOrEmpty(resourcesFile)) + { + HtmlUtils.WriteScriptSuccessError(HttpContext.Current.Response, (string.IsNullOrEmpty(exceptions)), resourcesFile.Replace("." + DefaultProvider, ".log.resources")); + } + } + + return exceptions; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleDefinition gets the Module Definition Id of a module + /// + /// The Friendly Name of the Module to Add + /// The Module Definition Name + /// The Module Definition Id of the Module (-1 if no module definition) + /// + /// [cnurse] 11/16/2004 created + /// + /// ----------------------------------------------------------------------------- + private static int GetModuleDefinition(string desktopModuleName, string moduleDefinitionName) + { + // get desktop module + var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(desktopModuleName, Null.NullInteger); + if (desktopModule == null) + { + return -1; + } + + // get module definition + ModuleDefinitionInfo objModuleDefinition = ModuleDefinitionController.GetModuleDefinitionByFriendlyName(moduleDefinitionName, desktopModule.DesktopModuleID); + if (objModuleDefinition == null) + { + return -1; + } + + + return objModuleDefinition.ModuleDefID; + } + + /// ----------------------------------------------------------------------------- + /// + /// HostTabExists determines whether a tab of a given name exists under the Host tab + /// + /// + /// + /// The Name of the Tab + /// True if the Tab exists, otherwise False + /// + /// [cnurse] 11/08/2004 documented + /// + /// ----------------------------------------------------------------------------- + private static bool HostTabExists(string tabName) + { + bool tabExists = false; + var tabController = new TabController(); + var hostTab = tabController.GetTabByName("Host", Null.NullInteger); + + var tab = tabController.GetTabByName(tabName, Null.NullInteger, hostTab.TabID); + if ((tab != null)) + { + tabExists = true; + } + + + return tabExists; + } + + /// ----------------------------------------------------------------------------- + /// + /// InstallMemberRoleProvider - Installs the MemberRole Provider Db objects + /// + /// + /// + /// The Path to the Provider Directory + /// Whether need to output feedback message. + /// + /// [cnurse] 02/02/2005 created + /// + /// ----------------------------------------------------------------------------- + internal static string InstallMemberRoleProvider(string providerPath, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallMemberRoleProvider"); + + string exceptions = ""; + + bool installMemberRole = true; + if ((Config.GetSetting("InstallMemberRole") != null)) + { + installMemberRole = bool.Parse(Config.GetSetting("InstallMemberRole")); + } + + if (installMemberRole) + { + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Installing MemberRole Provider:
    "); + } + + //Install Common + exceptions += InstallMemberRoleProviderScript(providerPath, "InstallCommon", writeFeedback); + //Install Membership + exceptions += InstallMemberRoleProviderScript(providerPath, "InstallMembership", writeFeedback); + //Install Profile + //exceptions += InstallMemberRoleProviderScript(providerPath, "InstallProfile", writeFeedback); + //Install Roles + //exceptions += InstallMemberRoleProviderScript(providerPath, "InstallRoles", writeFeedback); + } + + if (String.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "InstallMemberRoleProvider"); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + + return exceptions; + } + + /// ----------------------------------------------------------------------------- + /// + /// InstallMemberRoleProviderScript - Installs a specific MemberRole Provider script + /// + /// + /// + /// The Path to the Provider Directory + /// The Name of the Script File + /// Whether or not to echo results + /// + /// + /// ----------------------------------------------------------------------------- + private static string InstallMemberRoleProviderScript(string providerPath, string scriptFile, bool writeFeedback) + { + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "Executing Script: " + scriptFile + "
    "); + } + + string exceptions = DataProvider.Instance().ExecuteScript(FileSystemUtils.ReadFile(providerPath + scriptFile + ".sql")); + + // log the results + try + { + using (StreamWriter streamWriter = File.CreateText(providerPath + scriptFile + ".log.resources")) + { + streamWriter.WriteLine(exceptions); + streamWriter.Close(); + } + } + catch (Exception exc) + { + //does not have permission to create the log file + Logger.Error(exc); + } + + return exceptions; + } + + /// ----------------------------------------------------------------------------- + /// + /// ParseFiles parses the Host Template's Files node + /// + /// + /// + /// The Files node + /// The PortalId (-1 for Host Files) + /// + /// [cnurse] 11/08/2004 created + /// + /// ----------------------------------------------------------------------------- + private static void ParseFiles(XmlNode node, int portalId) + { + //Parse the File nodes + if (node != null) + { + XmlNodeList nodes = node.SelectNodes("file"); + if (nodes != null) + { + var folderManager = FolderManager.Instance; + var fileManager = FileManager.Instance; + + foreach (XmlNode fileNode in nodes) + { + string fileName = XmlUtils.GetNodeValue(fileNode.CreateNavigator(), "filename"); + string extension = XmlUtils.GetNodeValue(fileNode.CreateNavigator(), "extension"); + long size = long.Parse(XmlUtils.GetNodeValue(fileNode.CreateNavigator(), "size")); + int width = XmlUtils.GetNodeValueInt(fileNode, "width"); + int height = XmlUtils.GetNodeValueInt(fileNode, "height"); + string contentType = XmlUtils.GetNodeValue(fileNode.CreateNavigator(), "contentType"); + string folder = XmlUtils.GetNodeValue(fileNode.CreateNavigator(), "folder"); + + var folderInfo = folderManager.GetFolder(portalId, folder); + var file = new FileInfo(portalId, fileName, extension, (int) size, width, height, contentType, folder, folderInfo.FolderID, folderInfo.StorageLocation, true); + + using (var fileContent = fileManager.GetFileContent(file)) + { + var addedFile = fileManager.AddFile(folderInfo, file.FileName, fileContent, false); + + file.FileId = addedFile.FileId; + file.EnablePublishPeriod = addedFile.EnablePublishPeriod; + file.EndDate = addedFile.EndDate; + file.StartDate = addedFile.StartDate; + } + + fileManager.UpdateFile(file); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// RemoveCoreModule removes a Core Module from the system + /// + /// + /// + /// The Friendly Name of the Module to Remove + /// The Name of the parent Tab/Page for this module + /// The Name to tab that contains the Module + /// A flag to determine whether to remove the Tab if it has no + /// other modules + /// + /// [cnurse] 10/14/2004 documented + /// + /// ----------------------------------------------------------------------------- + private static void RemoveCoreModule(string desktopModuleName, string parentTabName, string tabName, bool removeTab) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveCoreModule:" + desktopModuleName); + + int moduleDefId = Null.NullInteger; + int desktopModuleId = 0; + + //Find and remove the Module from the Tab + switch (parentTabName) + { + case "Host": + var tabController = new TabController(); + var tab = tabController.GetTabByName("Host", Null.NullInteger, Null.NullInteger); + + if (tab != null) + { + moduleDefId = RemoveModule(desktopModuleName, tabName, tab.TabID, removeTab); + } + break; + case "Admin": + var portalController = new PortalController(); + PortalInfo portal; + + var portals = portalController.GetPortals(); + + //Iterate through the Portals to remove the Module from the Tab + for (int intPortal = 0; intPortal <= portals.Count - 1; intPortal++) + { + portal = (PortalInfo) portals[intPortal]; + moduleDefId = RemoveModule(desktopModuleName, tabName, portal.AdminTabId, removeTab); + } + break; + } + + DesktopModuleInfo desktopModule = null; + if (moduleDefId == Null.NullInteger) + { + desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(desktopModuleName, Null.NullInteger); + desktopModuleId = desktopModule.DesktopModuleID; + } + else + { + //Get the Module Definition + ModuleDefinitionInfo moduleDefinition = ModuleDefinitionController.GetModuleDefinitionByID(moduleDefId); + if (moduleDefinition != null) + { + desktopModuleId = moduleDefinition.DesktopModuleID; + desktopModule = DesktopModuleController.GetDesktopModule(desktopModuleId, Null.NullInteger); + } + } + + if (desktopModule != null) + { + //Delete the Desktop Module + var desktopModuleController = new DesktopModuleController(); + desktopModuleController.DeleteDesktopModule(desktopModuleId); + + //Delete the Package + PackageController.DeletePackage(desktopModule.PackageID); + } + } + + private static int RemoveModule(string desktopModuleName, string tabName, int parentId, bool removeTab) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveModule:" + desktopModuleName); + var tabController = new TabController(); + var moduleController = new ModuleController(); + TabInfo tab = tabController.GetTabByName(tabName, Null.NullInteger, parentId); + int moduleDefId = 0; + int count = 0; + + //Get the Modules on the Tab + if (tab != null) + { + foreach (KeyValuePair kvp in moduleController.GetTabModules(tab.TabID)) + { + var module = kvp.Value; + if (module.DesktopModule.FriendlyName == desktopModuleName) + { + //Delete the Module from the Modules list + moduleController.DeleteTabModule(module.TabID, module.ModuleID, false); + moduleDefId = module.ModuleDefID; + } + else + { + count += 1; + } + } + + //If Tab has no modules optionally remove tab + if (count == 0 && removeTab) + { + tabController.DeleteTab(tab.TabID, tab.PortalID); + } + } + + return moduleDefId; + } + + private static void RemoveModuleControl(int moduleDefId, string controlKey) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveModuleControl:" + moduleDefId); + // get Module Control + var moduleControl = ModuleControlController.GetModuleControlByControlKey(controlKey, moduleDefId); + if (moduleControl != null) + { + ModuleControlController.DeleteModuleControl(moduleControl.ModuleControlID); + } + } + + private static void RemoveModuleFromPortals(string friendlyName) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveModuleFromPortals:" + friendlyName); + DesktopModuleInfo desktopModule = DesktopModuleController.GetDesktopModuleByFriendlyName(friendlyName); + if (desktopModule != null) + { + //Module was incorrectly assigned as "IsPremium=False" + if (desktopModule.PackageID > Null.NullInteger) + { + desktopModule.IsPremium = true; + DesktopModuleController.SaveDesktopModule(desktopModule, false, true); + } + + //Remove the module from Portals + DesktopModuleController.RemoveDesktopModuleFromPortals(desktopModule.DesktopModuleID); + } + } + + private static bool TabPermissionExists(TabPermissionInfo tabPermission, int portalID) + { + return TabPermissionController.GetTabPermissions(tabPermission.TabID, portalID).Cast().Any(permission => permission.TabID == tabPermission.TabID && permission.RoleID == tabPermission.RoleID && permission.PermissionID == tabPermission.PermissionID); + } + + private static void FavIconsToPortalSettings() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "FavIconsToPortalSettings"); + const string fileName = "favicon.ico"; + var portals = new PortalController().GetPortals().Cast(); + + foreach (var portalInfo in portals) + { + string localPath = Path.Combine(portalInfo.HomeDirectoryMapPath, fileName); + + if(File.Exists(localPath)) + { + try + { + int fileId; + var folder = FolderManager.Instance.GetFolder(portalInfo.PortalID, ""); + if( ! FileManager.Instance.FileExists(folder, fileName)) + { + using (var stream = File.OpenRead(localPath)) + { + FileManager.Instance.AddFile(folder, fileName, stream, /*overwrite*/ false); + } + } + fileId = FileManager.Instance.GetFile(folder, fileName).FileId; + + new FavIcon(portalInfo.PortalID).Update(fileId); + } + catch (Exception e) + { + string message = string.Format("Unable to setup Favicon for Portal: {0}", portalInfo.PortalName); + var controller = new EventLogController(); + var info = new LogInfo(); + info.LogTypeKey = EventLogController.EventLogType.ADMIN_ALERT.ToString(); + info.AddProperty("Issue", message); + info.AddProperty("ExceptionMessage", e.Message); + info.AddProperty("StackTrace", e.StackTrace); + controller.AddLog(info); + + Logger.Warn(message, e); + } + } + } + } + + private static void AddIconToAllowedFiles() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddIconToAllowedFiles"); + var toAdd = new List { ".ico" }; + HostController.Instance.Update("FileExtensions", Host.AllowedExtensionWhitelist.ToStorageString(toAdd)); + } + + private static void UpgradeToVersion323() + { + //add new SecurityException + var logController = new LogController(); + string configFile = Globals.HostMapPath + "Logs\\LogConfig\\SecurityExceptionTemplate.xml.resources"; + logController.AddLogType(configFile, Null.NullString); + } + + private static void UpgradeToVersion440() + { + // remove module cache files with *.htm extension ( they are now securely named *.resources ) + var portalController = new PortalController(); + var portals = portalController.GetPortals(); + foreach (PortalInfo objPortal in portals) + { + if (Directory.Exists(Globals.ApplicationMapPath + "\\Portals\\" + objPortal.PortalID + "\\Cache\\")) + { + string[] files = Directory.GetFiles(Globals.ApplicationMapPath + "\\Portals\\" + objPortal.PortalID + "\\Cache\\", "*.htm"); + foreach (string file in files) + { + File.Delete(file); + } + } + } + } + + private static void UpgradeToVersion470() + { + string hostTemplateFile = Globals.HostMapPath + "Templates\\Default.page.template"; + if (File.Exists(hostTemplateFile)) + { + var portalController = new PortalController(); + ArrayList portals = portalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + string portalTemplateFolder = portal.HomeDirectoryMapPath + "Templates\\"; + + if (!Directory.Exists(portalTemplateFolder)) + { + //Create Portal Templates folder + Directory.CreateDirectory(portalTemplateFolder); + } + string portalTemplateFile = portalTemplateFolder + "Default.page.template"; + if (!File.Exists(portalTemplateFile)) + { + File.Copy(hostTemplateFile, portalTemplateFile); + + //Synchronize the Templates folder to ensure the templates are accessible + FolderManager.Instance.Synchronize(portal.PortalID, "Templates/", false, true); + } + } + } + } + + private static void UpgradeToVersion482() + { + //checks for the very rare case where the default validationkey prior to 4.08.02 + //is still being used and updates it + Config.UpdateValidationKey(); + } + + private static void UpgradeToVersion500() + { + var portalController = new PortalController(); + ArrayList portals = portalController.GetPortals(); + var tabController = new TabController(); + + //Add Edit Permissions for Admin Tabs to legacy portals + var permissionController = new PermissionController(); + ArrayList permissions = permissionController.GetPermissionByCodeAndKey("SYSTEM_TAB", "EDIT"); + int permissionId = -1; + if (permissions.Count == 1) + { + var permission = permissions[0] as PermissionInfo; + if (permission != null) + { + permissionId = permission.PermissionID; + } + + foreach (PortalInfo portal in portals) + { + var adminTab = tabController.GetTab(portal.AdminTabId, portal.PortalID, true); + if (adminTab != null) + { + var tabPermission = new TabPermissionInfo {TabID = adminTab.TabID, PermissionID = permissionId, AllowAccess = true, RoleID = portal.AdministratorRoleId}; + if (!TabPermissionExists(tabPermission, portal.PortalID)) + { + adminTab.TabPermissions.Add(tabPermission); + } + + //Save Tab Permissions to Data Base + TabPermissionController.SaveTabPermissions(adminTab); + + foreach (var childTab in TabController.GetTabsByParent(portal.AdminTabId, portal.PortalID)) + { + tabPermission = new TabPermissionInfo {TabID = childTab.TabID, PermissionID = permissionId, AllowAccess = true, RoleID = portal.AdministratorRoleId}; + if (!TabPermissionExists(tabPermission, portal.PortalID)) + { + childTab.TabPermissions.Add(tabPermission); + } + //Save Tab Permissions to Data Base + TabPermissionController.SaveTabPermissions(childTab); + } + } + } + } + + //Update Host/Admin modules Visibility setting + bool superTabProcessed = Null.NullBoolean; + var moduleController = new ModuleController(); + foreach (PortalInfo portal in portals) + { + if (!superTabProcessed) + { + //Process Host Tabs + foreach (TabInfo childTab in TabController.GetTabsByParent(portal.SuperTabId, Null.NullInteger)) + { + foreach (ModuleInfo tabModule in moduleController.GetTabModules(childTab.TabID).Values) + { + tabModule.Visibility = VisibilityState.None; + moduleController.UpdateModule(tabModule); + } + } + } + + //Process Portal Tabs + foreach (TabInfo childTab in TabController.GetTabsByParent(portal.AdminTabId, portal.PortalID)) + { + foreach (ModuleInfo tabModule in moduleController.GetTabModules(childTab.TabID).Values) + { + tabModule.Visibility = VisibilityState.None; + moduleController.UpdateModule(tabModule); + } + } + } + + //Upgrade PortalDesktopModules to support new "model" + permissions = permissionController.GetPermissionByCodeAndKey("SYSTEM_DESKTOPMODULE", "DEPLOY"); + if (permissions.Count == 1) + { + var permission = permissions[0] as PermissionInfo; + if (permission != null) + { + permissionId = permission.PermissionID; + } + foreach (PortalInfo portal in portals) + { + foreach (DesktopModuleInfo desktopModule in DesktopModuleController.GetDesktopModules(Null.NullInteger).Values) + { + if (!desktopModule.IsPremium) + { + //Parse the permissions + var deployPermissions = new DesktopModulePermissionCollection(); + DesktopModulePermissionInfo deployPermission; + + // if Not IsAdmin add Registered Users + if (!desktopModule.IsAdmin) + { + deployPermission = new DesktopModulePermissionInfo {PermissionID = permissionId, AllowAccess = true, RoleID = portal.RegisteredRoleId}; + deployPermissions.Add(deployPermission); + } + + // if Not a Host Module add Administrators + const string hostModules = "Portals, SQL, HostSettings, Scheduler, SearchAdmin, Lists, SkinDesigner, Extensions"; + if (!hostModules.Contains(desktopModule.ModuleName)) + { + deployPermission = new DesktopModulePermissionInfo {PermissionID = permissionId, AllowAccess = true, RoleID = portal.AdministratorRoleId}; + deployPermissions.Add(deployPermission); + } + + //Add Portal/Module to PortalDesktopModules + DesktopModuleController.AddDesktopModuleToPortal(portal.PortalID, desktopModule, deployPermissions, false); + } + } + + DataCache.ClearPortalCache(portal.PortalID, true); + } + } + + LegacyUtil.ProcessLegacyModules(); + LegacyUtil.ProcessLegacyLanguages(); + LegacyUtil.ProcessLegacySkins(); + LegacyUtil.ProcessLegacySkinControls(); + } + + private static void UpgradeToVersion501() + { + //add new Cache Error Event Type + var logController = new LogController(); + string configFile = string.Format("{0}Logs\\LogConfig\\CacheErrorTemplate.xml.resources", Globals.HostMapPath); + logController.AddLogType(configFile, Null.NullString); + } + + private static void UpgradeToVersion510() + { + var portalController = new PortalController(); + var tabController = new TabController(); + var moduleController = new ModuleController(); + int moduleDefId; + + //add Dashboard module and tab + if (HostTabExists("Dashboard") == false) + { + moduleDefId = AddModuleDefinition("Dashboard", "Provides a snapshot of your DotNetNuke Application.", "Dashboard", true, true); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Dashboard/Dashboard.ascx", "icon_dashboard_32px.gif", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "Export", "", "DesktopModules/Admin/Dashboard/Export.ascx", "", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "DashboardControls", "", "DesktopModules/Admin/Dashboard/DashboardControls.ascx", "", SecurityAccessLevel.Host, 0); + + //Create New Host Page (or get existing one) + TabInfo dashboardPage = AddHostPage("Dashboard", "Summary view of application and site settings.", "~/images/icon_dashboard_16px.gif", "~/images/icon_dashboard_32px.gif", true); + + //Add Module To Page + AddModuleToPage(dashboardPage, moduleDefId, "Dashboard", "~/images/icon_dashboard_32px.gif"); + } + else + { + //Module was incorrectly assigned as "IsPremium=False" + RemoveModuleFromPortals("Dashboard"); + //fix path for dashboarcontrols + moduleDefId = GetModuleDefinition("Dashboard", "Dashboard"); + RemoveModuleControl(moduleDefId, "DashboardControls"); + AddModuleControl(moduleDefId, "DashboardControls", "", "DesktopModules/Admin/Dashboard/DashboardControls.ascx", "", SecurityAccessLevel.Host, 0); + } + + //Add the Extensions Module + if (CoreModuleExists("Extensions") == false) + { + moduleDefId = AddModuleDefinition("Extensions", "", "Extensions"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Extensions/Extensions.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.View, 0); + AddModuleControl(moduleDefId, "Edit", "Edit Feature", "DesktopModules/Admin/Extensions/EditExtension.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Edit, 0); + AddModuleControl(moduleDefId, "PackageWriter", "Package Writer", "DesktopModules/Admin/Extensions/PackageWriter.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "EditControl", "Edit Control", "DesktopModules/Admin/Extensions/Editors/EditModuleControl.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "ImportModuleDefinition", "Import Module Definition", "DesktopModules/Admin/Extensions/Editors/ImportModuleDefinition.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "BatchInstall", "Batch Install", "DesktopModules/Admin/Extensions/BatchInstall.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "NewExtension", "New Extension Wizard", "DesktopModules/Admin/Extensions/ExtensionWizard.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "UsageDetails", "Usage Information", "DesktopModules/Admin/Extensions/UsageDetails.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0, "", true); + } + else + { + moduleDefId = GetModuleDefinition("Extensions", "Extensions"); + RemoveModuleControl(moduleDefId, "EditLanguage"); + RemoveModuleControl(moduleDefId, "TimeZone"); + RemoveModuleControl(moduleDefId, "Verify"); + RemoveModuleControl(moduleDefId, "LanguageSettings"); + RemoveModuleControl(moduleDefId, "EditResourceKey"); + RemoveModuleControl(moduleDefId, "EditSkins"); + AddModuleControl(moduleDefId, "UsageDetails", "Usage Information", "DesktopModules/Admin/Extensions/UsageDetails.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0, "", true); + + //Module was incorrectly assigned as "IsPremium=False" + RemoveModuleFromPortals("Extensions"); + } + + //Remove Module Definitions Module from Host Page (if present) + RemoveCoreModule("Module Definitions", "Host", "Module Definitions", false); + + //Remove old Module Definition Validator module + DesktopModuleController.DeleteDesktopModule("Module Definition Validator"); + + //Get Module Definitions + TabInfo definitionsPage = tabController.GetTabByName("Module Definitions", Null.NullInteger); + + //Add Module To Page if not present + int moduleId = AddModuleToPage(definitionsPage, moduleDefId, "Module Definitions", "~/images/icon_moduledefinitions_32px.gif"); + moduleController.UpdateModuleSetting(moduleId, "Extensions_Mode", "Module"); + + //Add Extensions Host Page + TabInfo extensionsPage = AddHostPage("Extensions", "Install, add, modify and delete extensions, such as modules, skins and language packs.", "~/images/icon_extensions_16px.gif", "~/images/icon_extensions_32px.png", true); + + moduleId = AddModuleToPage(extensionsPage, moduleDefId, "Extensions", "~/images/icon_extensions_32px.png"); + moduleController.UpdateModuleSetting(moduleId, "Extensions_Mode", "All"); + + //Add Extensions Module to Admin Page for all Portals + AddAdminPages("Extensions", "Install, add, modify and delete extensions, such as modules, skins and language packs.", "~/images/icon_extensions_16px.gif", "~/images/icon_extensions_32px.png", true, moduleDefId, "Extensions", "~/images/icon_extensions_32px.png"); + + //Remove Host Languages Page + RemoveHostPage("Languages"); + + //Remove Admin > Authentication Pages + RemoveAdminPages("//Admin//Authentication"); + + //Remove old Languages module + DesktopModuleController.DeleteDesktopModule("Languages"); + + //Add new Languages module + moduleDefId = AddModuleDefinition("Languages", "", "Languages", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Languages/languageeditor.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.View, 0); + AddModuleControl(moduleDefId, "Edit", "Edit Language", "DesktopModules/Admin/Languages/EditLanguage.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.Edit, 0); + AddModuleControl(moduleDefId, "EditResourceKey", "Full Language Editor", "DesktopModules/Admin/Languages/languageeditorext.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.Edit, 0); + AddModuleControl(moduleDefId, "LanguageSettings", "Language Settings", "DesktopModules/Admin/Languages/LanguageSettings.ascx", "", SecurityAccessLevel.Edit, 0); + AddModuleControl(moduleDefId, "TimeZone", "TimeZone Editor", "DesktopModules/Admin/Languages/timezoneeditor.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "Verify", "Resource File Verifier", "DesktopModules/Admin/Languages/resourceverifier.ascx", "", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "PackageWriter", "Language Pack Writer", "DesktopModules/Admin/Languages/LanguagePackWriter.ascx", "", SecurityAccessLevel.Host, 0); + + //Add Module to Admin Page for all Portals + AddAdminPages("Languages", "Manage Language Resources.", "~/images/icon_language_16px.gif", "~/images/icon_language_32px.gif", true, moduleDefId, "Language Editor", "~/images/icon_language_32px.gif"); + + //Remove Host Skins Page + RemoveHostPage("Skins"); + + //Remove old Skins module + DesktopModuleController.DeleteDesktopModule("Skins"); + + //Add new Skins module + moduleDefId = AddModuleDefinition("Skins", "", "Skins", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Skins/editskins.ascx", "~/images/icon_skins_32px.gif", SecurityAccessLevel.View, 0); + + //Add Module to Admin Page for all Portals + AddAdminPages("Skins", "Manage Skin Resources.", "~/images/icon_skins_16px.gif", "~/images/icon_skins_32px.gif", true, moduleDefId, "Skin Editor", "~/images/icon_skins_32px.gif"); + + //Remove old Skin Designer module + DesktopModuleController.DeleteDesktopModule("Skin Designer"); + DesktopModuleController.DeleteDesktopModule("SkinDesigner"); + + //Add new Skin Designer module + moduleDefId = AddModuleDefinition("Skin Designer", "Allows you to modify skin attributes.", "Skin Designer", true, true); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/SkinDesigner/Attributes.ascx", "~/images/icon_skins_32px.gif", SecurityAccessLevel.Host, 0); + + //Add new Skin Designer to every Admin Skins Tab + AddModuleToPages("//Admin//Skins", moduleDefId, "Skin Designer", "~/images/icon_skins_32px.gif", true); + + //Remove Admin Whats New Page + RemoveAdminPages("//Admin//WhatsNew"); + + //WhatsNew needs to be set to IsPremium and removed from all portals + RemoveModuleFromPortals("WhatsNew"); + + //Create New WhatsNew Host Page (or get existing one) + TabInfo newPage = AddHostPage("What's New", "Provides a summary of the major features for each release.", "~/images/icon_whatsnew_16px.gif", "~/images/icon_whatsnew_32px.gif", true); + + //Add WhatsNew Module To Page + moduleDefId = GetModuleDefinition("WhatsNew", "WhatsNew"); + AddModuleToPage(newPage, moduleDefId, "What's New", "~/images/icon_whatsnew_32px.gif"); + + //add console module + moduleDefId = AddModuleDefinition("Console", "Display children pages as icon links for navigation.", "Console", "DotNetNuke.Modules.Console.Components.ConsoleController", true, false, false); + AddModuleControl(moduleDefId, "", "Console", "DesktopModules/Admin/Console/ViewConsole.ascx", "", SecurityAccessLevel.Anonymous, 0); + AddModuleControl(moduleDefId, "Settings", "Console Settings", "DesktopModules/Admin/Console/Settings.ascx", "", SecurityAccessLevel.Admin, 0); + + //add console module to host page + moduleId = AddModuleToPage("//Host", Null.NullInteger, moduleDefId, "Basic Features", "", true); + int tabId = TabController.GetTabByTabPath(Null.NullInteger, "//Host", Null.NullString); + TabInfo tab; + + //add console settings for host page + if ((tabId != Null.NullInteger)) + { + tab = tabController.GetTab(tabId, Null.NullInteger, true); + if (((tab != null))) + { + AddConsoleModuleSettings(moduleId); + } + } + + //add module to all admin pages + foreach (PortalInfo portal in portalController.GetPortals()) + { + tabId = TabController.GetTabByTabPath(portal.PortalID, "//Admin", Null.NullString); + if ((tabId != Null.NullInteger)) + { + tab = tabController.GetTab(tabId, portal.PortalID, true); + if (((tab != null))) + { + moduleId = AddModuleToPage(tab, moduleDefId, "Basic Features", "", true); + AddConsoleModuleSettings(moduleId); + } + } + } + + //Add Google Analytics module + moduleDefId = AddModuleDefinition("Google Analytics", "Configure Site Google Analytics settings.", "GoogleAnalytics", false, false); + AddModuleControl(moduleDefId, "", "Google Analytics", "DesktopModules/Admin/Analytics/GoogleAnalyticsSettings.ascx", "", SecurityAccessLevel.Admin, 0); + AddAdminPages("Google Analytics", "Configure Site Google Analytics settings.", "~/images/icon_analytics_16px.gif", "~/images/icon_analytics_32px.gif", true, moduleDefId, "Google Analytics", "~/images/icon_analytics_32px.gif"); + } + + private static void UpgradeToVersion511() + { + //New Admin pages may not have administrator permission + //Add Admin role if it does not exist for google analytics or extensions + AddAdminRoleToPage("//Admin//Extensions"); + AddAdminRoleToPage("//Admin//GoogleAnalytics"); + } + + private static void UpgradeToVersion513() + { + //Ensure that default language is present (not neccessarily enabled) + var defaultLanguage = LocaleController.Instance.GetLocale("en-US") ?? new Locale(); + defaultLanguage.Code = "en-US"; + defaultLanguage.Text = "English (United States)"; + Localization.Localization.SaveLanguage(defaultLanguage); + + //Ensure that there is a Default Authorization System + var package = PackageController.GetPackageByName("DefaultAuthentication"); + if (package == null) + { + package = new PackageInfo + { + Name = "DefaultAuthentication", + FriendlyName = "Default Authentication", + Description = "The Default UserName/Password Authentication System for DotNetNuke.", + PackageType = "Auth_System", + Version = new Version(1, 0, 0), + Owner = "DotNetNuke", + License = Localization.Localization.GetString("License", Localization.Localization.GlobalResourceFile), + Organization = "DotNetNuke Corporation", + Url = "www.dotnetnuke.com", + Email = "support@dotnetnuke.com", + ReleaseNotes = "There are no release notes for this version.", + IsSystemPackage = true + }; + PackageController.SavePackage(package); + + //Add Authentication System + var authSystem = AuthenticationController.GetAuthenticationServiceByType("DNN") ?? new AuthenticationInfo(); + authSystem.PackageID = package.PackageID; + authSystem.AuthenticationType = "DNN"; + authSystem.SettingsControlSrc = "DesktopModules/AuthenticationServices/DNN/Settings.ascx"; + authSystem.LoginControlSrc = "DesktopModules/AuthenticationServices/DNN/Login.ascx"; + authSystem.IsEnabled = true; + + if (authSystem.AuthenticationID == Null.NullInteger) + { + AuthenticationController.AddAuthentication(authSystem); + } + else + { + AuthenticationController.UpdateAuthentication(authSystem); + } + } + } + + private static void UpgradeToVersion520() + { + //Add new ViewSource control + AddModuleControl(Null.NullInteger, "ViewSource", "View Module Source", "Admin/Modules/ViewSource.ascx", "~/images/icon_source_32px.gif", SecurityAccessLevel.Host, 0, "", true); + + //Add Marketplace module definition + int moduleDefId = AddModuleDefinition("Marketplace", "Search for DotNetNuke modules, extension and skins.", "Marketplace"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Marketplace/Marketplace.ascx", "~/images/icon_marketplace_32px.gif", SecurityAccessLevel.Host, 0); + + //Add marketplace Module To Page + TabInfo newPage = AddHostPage("Marketplace", "Search for DotNetNuke modules, extension and skins.", "~/images/icon_marketplace_16px.gif", "~/images/icon_marketplace_32px.gif", true); + moduleDefId = GetModuleDefinition("Marketplace", "Marketplace"); + AddModuleToPage(newPage, moduleDefId, "Marketplace", "~/images/icon_marketplace_32px.gif"); + } + + private static void UpgradeToVersion521() + { + // UpgradeDefaultLanguages is a temporary procedure containing code that + // needed to execute after the 5.1.3 application upgrade code above + DataProvider.Instance().ExecuteNonQuery("UpgradeDefaultLanguages"); + + // This procedure is not intended to be part of the database schema + // and is therefore dropped once it has been executed. + DataProvider.Instance().ExecuteSQL("DROP PROCEDURE {databaseOwner}{objectQualifier}UpgradeDefaultLanguages"); + } + + private static void UpgradeToVersion530() + { + //update languages module + int moduleDefId = GetModuleDefinition("Languages", "Languages"); + RemoveModuleControl(moduleDefId, ""); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Languages/languageEnabler.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.View, 0, "", true); + AddModuleControl(moduleDefId, "Editor", "", "DesktopModules/Admin/Languages/languageeditor.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.View, 0); + + //Add new View Profile module + moduleDefId = AddModuleDefinition("ViewProfile", "", "ViewProfile", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/ViewProfile/ViewProfile.ascx", "~/images/icon_profile_32px.gif", SecurityAccessLevel.View, 0); + AddModuleControl(moduleDefId, "Settings", "Settings", "DesktopModules/Admin/ViewProfile/Settings.ascx", "~/images/icon_profile_32px.gif", SecurityAccessLevel.Edit, 0); + + //Add new Sitemap settings module + moduleDefId = AddModuleDefinition("Sitemap", "", "Sitemap", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Sitemap/SitemapSettings.ascx", "~/images/icon_analytics_32px.gif", SecurityAccessLevel.View, 0); + AddAdminPages("Search Engine Sitemap", "Configure the sitemap for submission to common search engines.", "~/images/icon_analytics_16px.gif", "~/images/icon_analytics_32px.gif", true, moduleDefId, "Search Engine Sitemap", "~/images/icon_analytics_32px.gif"); + + + //Add new Photo Profile field to Host + var listController = new ListController(); + Dictionary dataTypes = listController.GetListEntryInfoDictionary("DataType"); + + var properties = ProfileController.GetPropertyDefinitionsByPortal(Null.NullInteger); + ProfileController.AddDefaultDefinition(Null.NullInteger, "Preferences", "Photo", "Image", 0, properties.Count*2 + 2, UserVisibilityMode.AllUsers, dataTypes); + + string installTemplateFile = string.Format("{0}Template\\UserProfile.page.template", Globals.InstallMapPath); + string hostTemplateFile = string.Format("{0}Templates\\UserProfile.page.template", Globals.HostMapPath); + if (File.Exists(installTemplateFile)) + { + if (!File.Exists(hostTemplateFile)) + { + File.Copy(installTemplateFile, hostTemplateFile); + } + } + if (File.Exists(hostTemplateFile)) + { + var tabController = new TabController(); + var portalController = new PortalController(); + ArrayList portals = portalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + properties = ProfileController.GetPropertyDefinitionsByPortal(portal.PortalID); + + //Add new Photo Profile field to Portal + ProfileController.AddDefaultDefinition(portal.PortalID, "Preferences", "Photo", "Image", 0, properties.Count*2 + 2, UserVisibilityMode.AllUsers, dataTypes); + + //Rename old Default Page template + string defaultPageTemplatePath = string.Format("{0}Templates\\Default.page.template", portal.HomeDirectoryMapPath); + if (File.Exists(defaultPageTemplatePath)) + { + File.Move(defaultPageTemplatePath, String.Format("{0}Templates\\Default_old.page.template", portal.HomeDirectoryMapPath)); + } + + //Update Default profile template in every portal + portalController.CopyPageTemplate("Default.page.template", portal.HomeDirectoryMapPath); + + //Add User profile template to every portal + portalController.CopyPageTemplate("UserProfile.page.template", portal.HomeDirectoryMapPath); + + //Synchronize the Templates folder to ensure the templates are accessible + FolderManager.Instance.Synchronize(portal.PortalID, "Templates/", false, true); + + var xmlDoc = new XmlDocument(); + try + { + // open the XML file + xmlDoc.Load(hostTemplateFile); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + + XmlNode userTabNode = xmlDoc.SelectSingleNode("//portal/tabs/tab"); + if (userTabNode != null) + { + string tabName = XmlUtils.GetNodeValue(userTabNode.CreateNavigator(), "name"); + + var userTab = tabController.GetTabByName(tabName, portal.PortalID) ?? TabController.DeserializeTab(userTabNode, null, portal.PortalID, PortalTemplateModuleAction.Merge); + + //Update SiteSettings to point to the new page + if (portal.UserTabId > Null.NullInteger) + { + portal.RegisterTabId = portal.UserTabId; + } + else + { + portal.UserTabId = userTab.TabID; + } + } + portalController.UpdatePortalInfo(portal); + + //Add Users folder to every portal + string usersFolder = string.Format("{0}Users\\", portal.HomeDirectoryMapPath); + + if (!Directory.Exists(usersFolder)) + { + //Create Users folder + Directory.CreateDirectory(usersFolder); + + //Synchronize the Users folder to ensure the user folder is accessible + FolderManager.Instance.Synchronize(portal.PortalID, "Users/", false, true); + } + } + } + AddEventQueueApplicationStartFirstRequest(); + + //Change Key for Module Defintions; + moduleDefId = GetModuleDefinition("Extensions", "Extensions"); + RemoveModuleControl(moduleDefId, "ImportModuleDefinition"); + AddModuleControl(moduleDefId, "EditModuleDefinition", "Edit Module Definition", "DesktopModules/Admin/Extensions/Editors/EditModuleDefinition.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + + //Module was incorrectly assigned as "IsPremium=False" + RemoveModuleFromPortals("Users And Roles"); + } + + private static void UpgradeToVersion540() + { + var configDoc = Config.Load(); + var configNavigator = configDoc.CreateNavigator().SelectSingleNode("/configuration/system.web.extensions"); + if (configNavigator == null) + { + //attempt to remove "System.Web.Extensions" configuration section + string upgradeFile = string.Format("{0}\\Config\\SystemWebExtensions.config", Globals.InstallMapPath); + string message = UpdateConfig(upgradeFile, DotNetNukeContext.Current.Application.Version, "Remove System.Web.Extensions"); + var eventLogController = new EventLogController(); + eventLogController.AddLog("UpgradeConfig", + string.IsNullOrEmpty(message) + ? "Remove System Web Extensions" + : string.Format("Remove System Web Extensions failed. Error reported during attempt to update:{0}", message), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.HOST_ALERT); + } + + //Add Styles Skin Object + AddSkinControl("TAGS", "DotNetNuke.TagsSkinObject", "Admin/Skins/Tags.ascx"); + + //Add Content List module definition + int moduleDefId = AddModuleDefinition("ContentList", "This module displays a list of content by tag.", "Content List"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/ContentList/ContentList.ascx", "", SecurityAccessLevel.View, 0); + + //Update registration page + var portalController = new PortalController(); + ArrayList portals = portalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + //objPortal.RegisterTabId = objPortal.UserTabId; + portalController.UpdatePortalInfo(portal); + + //Add ContentList to Search Results Page + var tabController = new TabController(); + int tabId = TabController.GetTabByTabPath(portal.PortalID, "//SearchResults", Null.NullString); + TabInfo searchPage = tabController.GetTab(tabId, portal.PortalID, false); + AddModuleToPage(searchPage, moduleDefId, "Results", ""); + } + } + + private static void UpgradeToVersion543() + { + // get log file path + string logFilePath = DataProvider.Instance().GetProviderPath(); + if (Directory.Exists(logFilePath)) + { + //get log files + foreach (string fileName in Directory.GetFiles(logFilePath, "*.log")) + { + if (File.Exists(fileName + ".resources")) + { + File.Delete(fileName + ".resources"); + } + //copy requires use of move + File.Move(fileName, fileName + ".resources"); + } + } + } + + private static void UpgradeToVersion550() + { + //update languages module + int moduleDefId = GetModuleDefinition("Languages", "Languages"); + AddModuleControl(moduleDefId, "TranslationStatus", "", "DesktopModules/Admin/Languages/TranslationStatus.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.Edit, 0); + + //due to an error in 5.3.0 we need to recheck and readd Application_Start_FirstRequest + AddEventQueueApplicationStartFirstRequest(); + + // check if UserProfile page template exists in Host folder and if not, copy it from Install folder + string installTemplateFile = string.Format("{0}Templates\\UserProfile.page.template", Globals.InstallMapPath); + if (File.Exists(installTemplateFile)) + { + string hostTemplateFile = string.Format("{0}Templates\\UserProfile.page.template", Globals.HostMapPath); + if (!File.Exists(hostTemplateFile)) + { + File.Copy(installTemplateFile, hostTemplateFile); + } + } + + //Fix the permission for User Folders + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + foreach (FolderInfo folder in FolderManager.Instance.GetFolders(portal.PortalID)) + { + if (folder.FolderPath.StartsWith("Users/")) + { + foreach (PermissionInfo permission in PermissionController.GetPermissionsByFolder()) + { + if (permission.PermissionKey.ToUpper() == "READ") + { + //Add All Users Read Access to the folder + int roleId = Int32.Parse(Globals.glbRoleAllUsers); + if (!folder.FolderPermissions.Contains(permission.PermissionKey, folder.FolderID, roleId, Null.NullInteger)) + { + var folderPermission = new FolderPermissionInfo(permission) {FolderID = folder.FolderID, UserID = Null.NullInteger, RoleID = roleId, AllowAccess = true}; + + folder.FolderPermissions.Add(folderPermission); + } + } + } + + FolderPermissionController.SaveFolderPermissions(folder); + } + } + //Remove user page template from portal if it exists (from 5.3) + if (File.Exists(string.Format("{0}Templates\\UserProfile.page.template", portal.HomeDirectoryMapPath))) + { + File.Delete(string.Format("{0}Templates\\UserProfile.page.template", portal.HomeDirectoryMapPath)); + } + } + + //DNN-12894 - Country Code for "United Kingdom" is incorrect + var listController = new ListController(); + var listItem = listController.GetListEntryInfo("Country", "UK"); + if (listItem != null) + { + listItem.Value = "GB"; + listController.UpdateListEntry(listItem); + } + + + foreach (PortalInfo portal in new PortalController().GetPortals()) + { + //fix issue where portal default language may be disabled + string defaultLanguage = portal.DefaultLanguage; + if (!IsLanguageEnabled(portal.PortalID, defaultLanguage)) + { + Locale language = LocaleController.Instance.GetLocale(defaultLanguage); + Localization.Localization.AddLanguageToPortal(portal.PortalID, language.LanguageId, true); + } + //preemptively create any missing localization records rather than relying on dynamic creation + foreach (Locale locale in LocaleController.Instance.GetLocales(portal.PortalID).Values) + { + DataProvider.Instance().EnsureLocalizationExists(portal.PortalID, locale.Code); + } + } + } + + private static void UpgradeToVersion560() + { + //Add .htmtemplate file extension + var toAdd = new List { ".htmtemplate" }; + HostController.Instance.Update("FileExtensions", Host.AllowedExtensionWhitelist.ToStorageString(toAdd)); + + //Add new Xml Merge module + int moduleDefId = AddModuleDefinition("Configuration Manager", "", "Configuration Manager", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/XmlMerge/XmlMerge.ascx", "~/images/icon_configuration_32px.png", SecurityAccessLevel.Host, 0); + + //Add Module To Page + TabInfo hostPage = AddHostPage("Configuration Manager", "Modify configuration settings for your site", "~/images/icon_configuration_16px.png", "~/images/icon_configuration_32px.png", true); + AddModuleToPage(hostPage, moduleDefId, "Configuration Manager", "~/images/icon_configuration_32px.png"); + + //Update Google Analytics Script in SiteAnalysis.config + var googleAnalyticsController = new GoogleAnalyticsController(); + googleAnalyticsController.UpgradeModule("05.06.00"); + + //Updated LanguageSettings.ascx control to be a Settings control + ModuleDefinitionInfo languageModule = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("Languages"); + ModuleControlInfo moduleControl = ModuleControlController.GetModuleControlsByModuleDefinitionID(languageModule.ModuleDefID)["LanguageSettings"]; + moduleControl.ControlKey = "Settings"; + ModuleControlController.UpdateModuleControl(moduleControl); + } + + private static void UpgradeToVersion562() + { + //Add new Photo Profile field to Host + var listController = new ListController(); + Dictionary dataTypes = listController.GetListEntryInfoDictionary("DataType"); + + var properties = ProfileController.GetPropertyDefinitionsByPortal(Null.NullInteger); + ProfileController.AddDefaultDefinition(Null.NullInteger, "Preferences", "Photo", "Image", 0, properties.Count*2 + 2, UserVisibilityMode.AllUsers, dataTypes); + + HostController.Instance.Update("AutoAddPortalAlias", Globals.Status == Globals.UpgradeStatus.Install ? "Y" : "N"); + + // remove the system message module from the admin tab + // System Messages are now managed through Localization + if (CoreModuleExists("System Messages")) + { + RemoveCoreModule("System Messages", "Admin", "Site Settings", false); + } + + // remove portal alias module + if (CoreModuleExists("PortalAliases")) + { + RemoveCoreModule("PortalAliases", "Admin", "Site Settings", false); + } + + // add the log viewer module to the admin tab + int moduleDefId; + if (CoreModuleExists("LogViewer") == false) + { + moduleDefId = AddModuleDefinition("LogViewer", "Allows you to view log entries for site events.", "Log Viewer"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/LogViewer/LogViewer.ascx", "", SecurityAccessLevel.Admin, 0); + AddModuleControl(moduleDefId, "Edit", "Edit Log Settings", "DesktopModules/Admin/LogViewer/EditLogTypes.ascx", "", SecurityAccessLevel.Host, 0); + + //Add the Module/Page to all configured portals + AddAdminPages("Log Viewer", "View a historical log of database events such as event schedules, exceptions, account logins, module and page changes, user account activities, security role activities, etc.", "icon_viewstats_16px.gif", "icon_viewstats_32px.gif", true, moduleDefId, "Log Viewer", "icon_viewstats_16px.gif"); + } + + // add the schedule module to the host tab + TabInfo newPage; + if (CoreModuleExists("Scheduler") == false) + { + moduleDefId = AddModuleDefinition("Scheduler", "Allows you to schedule tasks to be run at specified intervals.", "Scheduler"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Scheduler/ViewSchedule.ascx", "", SecurityAccessLevel.Admin, 0); + AddModuleControl(moduleDefId, "Edit", "Edit Schedule", "DesktopModules/Admin/Scheduler/EditSchedule.ascx", "", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "History", "Schedule History", "DesktopModules/Admin/Scheduler/ViewScheduleHistory.ascx", "", SecurityAccessLevel.Host, 0); + AddModuleControl(moduleDefId, "Status", "Schedule Status", "DesktopModules/Admin/Scheduler/ViewScheduleStatus.ascx", "", SecurityAccessLevel.Host, 0); + + //Create New Host Page (or get existing one) + newPage = AddHostPage("Schedule", "Add, modify and delete scheduled tasks to be run at specified intervals.", "icon_scheduler_16px.gif", "icon_scheduler_32px.gif", true); + + //Add Module To Page + AddModuleToPage(newPage, moduleDefId, "Schedule", "icon_scheduler_16px.gif"); + } + + // add the Search Admin module to the host tab + if (CoreModuleExists("SearchAdmin") == false) + { + moduleDefId = AddModuleDefinition("SearchAdmin", "The Search Admininstrator provides the ability to manage search settings.", "Search Admin"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/SearchAdmin/SearchAdmin.ascx", "", SecurityAccessLevel.Host, 0); + + //Create New Host Page (or get existing one) + newPage = AddHostPage("Search Admin", "Manage search settings associated with DotNetNuke's search capability.", "icon_search_16px.gif", "icon_search_32px.gif", true); + + //Add Module To Page + AddModuleToPage(newPage, moduleDefId, "Search Admin", "icon_search_16px.gif"); + } + + // add the Search Input module + if (CoreModuleExists("SearchInput") == false) + { + moduleDefId = AddModuleDefinition("SearchInput", "The Search Input module provides the ability to submit a search to a given search results module.", "Search Input", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/SearchInput/SearchInput.ascx", "", SecurityAccessLevel.Anonymous, 0); + AddModuleControl(moduleDefId, "Settings", "Search Input Settings", "DesktopModules/Admin/SearchInput/Settings.ascx", "", SecurityAccessLevel.Edit, 0); + } + + // add the Search Results module + if (CoreModuleExists("SearchResults") == false) + { + moduleDefId = AddModuleDefinition("SearchResults", "The Search Reasults module provides the ability to display search results.", "Search Results", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/SearchResults/SearchResults.ascx", "", SecurityAccessLevel.Anonymous, 0); + AddModuleControl(moduleDefId, "Settings", "Search Results Settings", "DesktopModules/Admin/SearchResults/Settings.ascx", "", SecurityAccessLevel.Edit, 0); + + //Add the Search Module/Page to all configured portals + AddSearchResults(moduleDefId); + } + + // add the site wizard module to the admin tab + if (CoreModuleExists("SiteWizard") == false) + { + moduleDefId = AddModuleDefinition("SiteWizard", "The Administrator can use this user-friendly wizard to set up the common Extensions of the Portal/Site.", "Site Wizard"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/SiteWizard/Sitewizard.ascx", "", SecurityAccessLevel.Admin, 0); + AddAdminPages("Site Wizard", "Configure portal settings, page design and apply a site template using a step-by-step wizard.", "icon_wizard_16px.gif", "icon_wizard_32px.gif", true, moduleDefId, "Site Wizard", "icon_wizard_16px.gif"); + } + + //add Lists module and tab + if (HostTabExists("Lists") == false) + { + moduleDefId = AddModuleDefinition("Lists", "Allows you to edit common lists.", "Lists"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Lists/ListEditor.ascx", "", SecurityAccessLevel.Host, 0); + + //Create New Host Page (or get existing one) + newPage = AddHostPage("Lists", "Manage common lists.", "icon_lists_16px.gif", "icon_lists_32px.gif", true); + + //Add Module To Page + AddModuleToPage(newPage, moduleDefId, "Lists", "icon_lists_16px.gif"); + } + + if (HostTabExists("Superuser Accounts") == false) + { + //add SuperUser Accounts module and tab + DesktopModuleInfo objDesktopModuleInfo = DesktopModuleController.GetDesktopModuleByModuleName("Security", Null.NullInteger); + moduleDefId = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("User Accounts", objDesktopModuleInfo.DesktopModuleID).ModuleDefID; + + //Create New Host Page (or get existing one) + newPage = AddHostPage("Superuser Accounts", "Manage host user accounts.", "icon_users_16px.gif", "icon_users_32px.gif", true); + + //Add Module To Page + AddModuleToPage(newPage, moduleDefId, "SuperUser Accounts", "icon_users_32px.gif"); + } + + //Add Edit Role Groups + moduleDefId = GetModuleDefinition("Security", "Security Roles"); + AddModuleControl(moduleDefId, "EditGroup", "Edit Role Groups", "DesktopModules/Admin/Security/EditGroups.ascx", "icon_securityroles_32px.gif", SecurityAccessLevel.Edit, Null.NullInteger); + AddModuleControl(moduleDefId, "UserSettings", "Manage User Settings", "DesktopModules/Admin/Security/UserSettings.ascx", "~/images/settings.gif", SecurityAccessLevel.Edit, Null.NullInteger); + + //Add User Accounts Controls + moduleDefId = GetModuleDefinition("Security", "User Accounts"); + AddModuleControl(moduleDefId, "ManageProfile", "Manage Profile Definition", "DesktopModules/Admin/Security/ProfileDefinitions.ascx", "icon_users_32px.gif", SecurityAccessLevel.Edit, Null.NullInteger); + AddModuleControl(moduleDefId, "EditProfileProperty", "Edit Profile Property Definition", "DesktopModules/Admin/Security/EditProfileDefinition.ascx", "icon_users_32px.gif", SecurityAccessLevel.Edit, Null.NullInteger); + AddModuleControl(moduleDefId, "UserSettings", "Manage User Settings", "DesktopModules/Admin/Security/UserSettings.ascx", "~/images/settings.gif", SecurityAccessLevel.Edit, Null.NullInteger); + AddModuleControl(Null.NullInteger, "Profile", "Profile", "DesktopModules/Admin/Security/ManageUsers.ascx", "icon_users_32px.gif", SecurityAccessLevel.Anonymous, Null.NullInteger); + AddModuleControl(Null.NullInteger, "SendPassword", "Send Password", "DesktopModules/Admin/Security/SendPassword.ascx", "", SecurityAccessLevel.Anonymous, Null.NullInteger); + AddModuleControl(Null.NullInteger, "ViewProfile", "View Profile", "DesktopModules/Admin/Security/ViewProfile.ascx", "icon_users_32px.gif", SecurityAccessLevel.Anonymous, Null.NullInteger); + + //Update Child Portal subHost.aspx + UpdateChildPortalsDefaultPage(); + + // add the solutions explorer module to the admin tab + if (CoreModuleExists("Solutions") == false) + { + moduleDefId = AddModuleDefinition("Solutions", "Browse additional solutions for your application.", "Solutions", false, false); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/Solutions/Solutions.ascx", "", SecurityAccessLevel.Admin, 0); + AddAdminPages("Solutions", "DotNetNuke Solutions Explorer page provides easy access to locate free and commercial DotNetNuke modules, skin and more.", "icon_solutions_16px.gif", "icon_solutions_32px.gif", true, moduleDefId, "Solutions Explorer", "icon_solutions_32px.gif"); + } + + + //Add Search Skin Object + AddSkinControl("SEARCH", "DotNetNuke.SearchSkinObject", "Admin/Skins/Search.ascx"); + + //Add TreeView Skin Object + AddSkinControl("TREEVIEW", "DotNetNuke.TreeViewSkinObject", "Admin/Skins/TreeViewMenu.ascx"); + + //Add Text Skin Object + AddSkinControl("TEXT", "DotNetNuke.TextSkinObject", "Admin/Skins/Text.ascx"); + + //Add Styles Skin Object + + AddSkinControl("STYLES", "DotNetNuke.StylesSkinObject", "Admin/Skins/Styles.ascx"); + } + + private static void UpgradeToVersion600() + { + var tabController = new TabController(); + + var hostPages = tabController.GetTabsByPortal(Null.NullInteger); + + //This ensures that all host pages have a tab path. + //so they can be found later. (DNNPRO-17129) + foreach (var hostPage in hostPages.Values) + { + hostPage.TabPath = Globals.GenerateTabPath(hostPage.ParentId, hostPage.TabName); + tabController.UpdateTab(hostPage); + } + + var settings = PortalController.GetCurrentPortalSettings(); + + var moduleController = new ModuleController(); + + if (settings != null) + { + var hostTab = tabController.GetTab(settings.SuperTabId, Null.NullInteger, false); + hostTab.IsVisible = false; + tabController.UpdateTab(hostTab); + foreach (var module in moduleController.GetTabModules(settings.SuperTabId).Values) + { + moduleController.UpdateTabModuleSetting(module.TabModuleID, "hideadminborder", "true"); + } + } + + //remove timezone editor + int moduleDefId = GetModuleDefinition("Languages", "Languages"); + RemoveModuleControl(moduleDefId, "TimeZone"); + + //6.0 requires the old TimeZone property to be marked as Deleted - Delete for Host + ProfilePropertyDefinition ppdHostTimeZone = ProfileController.GetPropertyDefinitionByName(Null.NullInteger, "TimeZone"); + if (ppdHostTimeZone != null) + { + ProfileController.DeletePropertyDefinition(ppdHostTimeZone); + } + + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + //update timezoneinfo +#pragma warning disable 612,618 + TimeZoneInfo timeZoneInfo = Localization.Localization.ConvertLegacyTimeZoneOffsetToTimeZoneInfo(portal.TimeZoneOffset); +#pragma warning restore 612,618 + PortalController.UpdatePortalSetting(portal.PortalID, "TimeZone", timeZoneInfo.Id, false); + + //6.0 requires the old TimeZone property to be marked as Deleted - Delete for Portals + ProfilePropertyDefinition ppdTimeZone = ProfileController.GetPropertyDefinitionByName(portal.PortalID, "TimeZone"); + if (ppdTimeZone != null) + { + ProfileController.DeletePropertyDefinition(ppdTimeZone); + } + + var adminTab = tabController.GetTab(portal.AdminTabId, portal.PortalID, false); + + adminTab.IsVisible = false; + tabController.UpdateTab(adminTab); + + foreach (var module in moduleController.GetTabModules(portal.AdminTabId).Values) + { + moduleController.UpdateTabModuleSetting(module.TabModuleID, "hideadminborder", "true"); + } + } + + //Ensure that Display Beta Notice setting is present + var displayBetaNotice = Host.DisplayBetaNotice; + HostController.Instance.Update("DisplayBetaNotice", displayBetaNotice ? "Y": "N"); + + moduleDefId = GetModuleDefinition("Languages", "Languages"); + AddModuleControl(moduleDefId, "EnableContent", "Enable Localized Content", "DesktopModules/Admin/Languages/EnableLocalizedContent.ascx", "", SecurityAccessLevel.Host, 0, null, false); + AddProfessionalPreviewPages(); + + AddDefaultModuleIcons(); + + AddIconToAllowedFiles(); + + FavIconsToPortalSettings(); + + var tab = tabController.GetTabByName("Host", Null.NullInteger, Null.NullInteger); + + if (tab != null) + { + RemoveModule("Extensions", "Module Definitions", tab.TabID, true); + RemoveModule("Marketplace", "Marketplace", tab.TabID, true); + } + } + + private static void UpgradeToVersion601() + { + //List module needs to be available to Portals also + var pkg = PackageController.GetPackageByName("DotNetNuke.Lists"); + if (pkg != null) + { + //List package is no longer a system package + pkg.IsSystemPackage = false; + PackageController.UpdatePackage(pkg); + + //List desktop module is no longer premium or admin module + var desktopModule = DesktopModuleController.GetDesktopModuleByPackageID(pkg.PackageID); + desktopModule.IsAdmin = false; + desktopModule.IsPremium = false; + DesktopModuleController.SaveDesktopModule(desktopModule, false, true); + + var permissionController = new PermissionController(); + ArrayList permissions = permissionController.GetPermissionByCodeAndKey("SYSTEM_DESKTOPMODULE", "DEPLOY"); + if (permissions.Count == 1) + { + var permission = permissions[0] as PermissionInfo; + if (permission != null) + { + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + //ensure desktop module is not present in the portal + var pdmi = DesktopModuleController.GetPortalDesktopModule(portal.PortalID, desktopModule.DesktopModuleID); + if (pdmi == null) + { + //Parse the permissions + var deployPermissions = new DesktopModulePermissionCollection(); + var deployPermission = new DesktopModulePermissionInfo {PermissionID = permission.PermissionID, AllowAccess = true, RoleID = portal.AdministratorRoleId}; + deployPermissions.Add(deployPermission); + + //Add Portal/Module to PortalDesktopModules + DesktopModuleController.AddDesktopModuleToPortal(portal.PortalID, desktopModule, deployPermissions, true); + } + } + } + } + } + } + + private static void UpgradeToVersion602() + { + //Add avi,mpg,mpeg,mp3,wmv,mov,wav extensions + var exts = new List { ".avi", ".mpg", ".mpeg", ".mp3", ".wmv", ".mov", ".wav" }; + HostController.Instance.Update("FileExtensions", Host.AllowedExtensionWhitelist.ToStorageString(exts)); + + //Fix the icons for SiteMap page + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + var tabController = new TabController(); + var siteMap = tabController.GetTabByName("Search Engine SiteMap", portal.PortalID); + + if (siteMap != null) + { + siteMap.IconFile = "~/Icons/Sigma/Sitemap_16X16_Standard.png"; + siteMap.IconFileLarge = "~/Icons/Sigma/Sitemap_32X32_Standard.png"; + tabController.UpdateTab(siteMap); + } + } + } + + private static void UpgradeToVersion610() + { + AddModuleCategories(); + + //update languages module + int moduleDefId = GetModuleDefinition("Languages", "Languages"); + AddModuleControl(moduleDefId, "LocalizePages", "Localize Pages", "DesktopModules/Admin/Languages/LocalizePages.ascx", "~/images/icon_language_32px.gif", SecurityAccessLevel.Edit, 0, Null.NullString, true); + + //add store control + moduleDefId = AddModuleDefinition("Extensions", "", "Extensions"); + AddModuleControl(moduleDefId, "Store", "Store Details", "DesktopModules/Admin/Extensions/Store.ascx", "~/images/icon_extensions_32px.png", SecurityAccessLevel.Host, 0); + + EnableModalPopUps(); + + var tabController = new TabController(); + var tab = tabController.GetTabByName("Portals", Null.NullInteger); + tab.TabName = "Site Management"; + tabController.UpdateTab(tab); + + var moduleController = new ModuleController(); + foreach (var module in moduleController.GetTabModules(tab.TabID).Values) + { + if (module.ModuleTitle == "Portals") + { + module.ModuleTitle = "Site Management"; + moduleController.UpdateModule(module); + } + } + + //Add List module to Admin page of every portal + ModuleDefinitionInfo mDef = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("Lists"); + if (mDef != null) + { + AddAdminPages("Lists", + "Manage common lists", + "~/Icons/Sigma/Lists_16X16_Standard.png", + "~/Icons/Sigma/Lists_32X32_Standard.png", + true, + mDef.ModuleDefID, + "Lists", + "~/Icons/Sigma/Lists_16X16_Standard.png", + true); + } + + //update DotNetNuke.Portals' friend name to 'Sites'. + var portalPackage = PackageController.GetPackageByName("DotNetNuke.Portals"); + if(portalPackage != null) + { + portalPackage.FriendlyName = "Sites"; + PackageController.SavePackage(portalPackage); + } + + //add mobile preview control + AddModuleControl(Null.NullInteger, "MobilePreview", "Mobile Preview", "DesktopModules/Admin/MobilePreview/Preview.ascx", string.Empty, SecurityAccessLevel.Admin, Null.NullInteger); + } + + private static void UpgradeToVersion612() + { + //update DotNetNuke.Portals' friend name to 'Sites'. + var portalPackage = PackageController.GetPackageByName("DotNetNuke.Portals"); + if (portalPackage != null) + { + portalPackage.FriendlyName = "Site Management"; + portalPackage.Description = + "The Super User can manage the various parent and child sites within the install instance. This module allows you to add a new site, modify an existing site, and delete a site."; + PackageController.SavePackage(portalPackage); + } + + //update 'Portal' to 'Sites' in package description. + portalPackage = PackageController.GetPackageByName("DotNetNuke.Tabs"); + if (portalPackage != null) + { + portalPackage.Description = + "Administrators can manage the Pages within the site. This module allows you to create a new page, modify an existing page, delete pages, change the page order, and change the hierarchical page level."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.Vendors"); + if (portalPackage != null) + { + portalPackage.Description = + "Administrators can manage the Vendors and Banners associated to the site. This module allows you to add a new vendor, modify an existing vendor, and delete a vendor."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.SiteLog"); + if (portalPackage != null) + { + portalPackage.Description = + "Administrators can view the details of visitors using their site. There are a variety of reports available to display information regarding site usage, membership, and volumes."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.SiteWizard"); + if (portalPackage != null) + { + portalPackage.Description = + "The Administrator can use this user-friendly wizard to set up the common features of the site."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.Security"); + if (portalPackage != null) + { + portalPackage.Description = + "Administrators can manage the security roles defined for their site. The module allows you to add new security roles, modify existing security roles, delete security roles, and manage the users assigned to security roles."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.LogViewer"); + if (portalPackage != null) + { + portalPackage.Description = + "Allows you to view log entries for site events."; + PackageController.SavePackage(portalPackage); + } + + portalPackage = PackageController.GetPackageByName("DotNetNuke.Google Analytics"); + if (portalPackage != null) + { + portalPackage.Description = + "Configure Site Google Analytics settings."; + PackageController.SavePackage(portalPackage); + } + } + + private static void UpgradeToVersion613() + { + //Rename admin pages page's title to 'Page Management'. + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + var tabController = new TabController(); + var pagesTabId = TabController.GetTabByTabPath(portal.PortalID, "//Admin//Pages", Null.NullString); + + if (pagesTabId != Null.NullInteger) + { + var pagesTab = tabController.GetTab(pagesTabId, portal.PortalID, false); + if (pagesTab != null && pagesTab.Title == "Pages") + { + pagesTab.Title = "Page Management"; + tabController.UpdateTab(pagesTab); + } + } + } + } + + private static void UpgradeToVersion620() + { + //add host (system) profanityfilter list + const string listName = "ProfanityFilter"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + { + entry.DefinitionID = Null.NullInteger; + entry.PortalID = Null.NullInteger; + entry.ListName = listName; + entry.Value = "ReplaceWithNothing"; + entry.Text = "FindThisText"; + entry.SystemList = true; + } + listController.AddListEntry(entry); + + //add same list to each portal + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + entry.PortalID = portal.PortalID; + entry.SystemList = false; + entry.ListName = listName + "-" + portal.PortalID; + listController.AddListEntry(entry); + + //also create default social relationship entries for the portal + RelationshipController.Instance.CreateDefaultRelationshipsForPortal(portal.PortalID); + } + + //Convert old Messages to new schema + ConvertOldMessages(); + + //Replace old Messaging module on User Profile with new + ReplaceMessagingModule(); + + //Move Photo Property to the end of the propert list. + MovePhotoProperty(); + + //Update Child Portal's Default Page + UpdateChildPortalsDefaultPage(); + + //Add core notification types + AddCoreNotificationTypesFor620(); + + //Console module should not be IPortable + var consoleModule = DesktopModuleController.GetDesktopModuleByModuleName("Console", Null.NullInteger); + consoleModule.SupportedFeatures = 0; + consoleModule.BusinessControllerClass = ""; + DesktopModuleController.SaveDesktopModule(consoleModule, false, false); + } + + private static void UpgradeToVersion621() + { + //update administrators' role description. + var portalController = new PortalController(); + var moduleController = new ModuleController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + //update about me's template + var myProfileTabId = TabController.GetTabByTabPath(portal.PortalID, "//ActivityFeed//MyProfile", string.Empty); + if (myProfileTabId != Null.NullInteger) + { + var tabModules = moduleController.GetTabModules(myProfileTabId); + foreach (var module in tabModules.Values) + { + var settings = moduleController.GetTabModuleSettings(module.TabModuleID); + if (settings.ContainsKey("ProfileTemplate") && settings["ProfileTemplate"].ToString().Contains("
    ")) + { + var template = @"
    +

    + +

    +
    +
    +

    + +

    0"">
    + 0"">
    + 0"">
    + +

    +
    +
    +

    + +
      +
    • 0"">:
    • +
    • 0"">:
    • +
    • 0"">:
    • +
    • 0"">:
    • +
    +
    +
    "; + moduleController.UpdateTabModuleSetting(module.TabModuleID, "ProfileTemplate", template); + } + } + } + } + } + + private static void UpgradeToVersion623() + { + if (Host.jQueryUrl == "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js") + { + HostController.Instance.Update("jQueryUrl", jQuery.DefaultHostedUrl); + } + + if (Host.jQueryUIUrl == "http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js") + { + HostController.Instance.Update("jQueryUIUrl", jQuery.DefaultUIHostedUrl); + } + } + + private static void UpgradeToVersion624() + { + UninstallPackage("DotNetNuke.MarketPlace"); + } + + private static void UpgradeToVersion700() + { + // add the site Advanced Settings module to the admin tab + if (CoreModuleExists("AdvancedSettings") == false) + { + var moduleDefId = AddModuleDefinition("AdvancedSettings", "", "Advanced Settings"); + AddModuleControl(moduleDefId, "", "", "DesktopModules/Admin/AdvancedSettings/AdvancedSettings.ascx", "", SecurityAccessLevel.Admin, 0); + AddAdminPages("Advanced Settings", + "", + "~/Icons/Sigma/AdvancedSettings_16X16_Standard.png", + "~/Icons/Sigma/AdvancedSettings_32X32_Standard.png", + true, + moduleDefId, + "Advanced Settings", + "~/Icons/Sigma/AdvancedSettings_16X16_Standard.png"); + } + + ConvertCoreNotificationTypeActionsFor700(); + + //Remove Feed Explorer module + DesktopModuleController.DeleteDesktopModule("FeedExplorer"); + DesktopModuleController.DeleteDesktopModule("Solutions"); + + //Register Newtonsoft assembly + DataProvider.Instance().RegisterAssembly(Null.NullInteger, "Newtonsoft.Json.dll", "4.5.6"); + + //subhost.aspx was updated + UpdateChildPortalsDefaultPage(); + } + + private static void UpgradeToVersion710() + { + //create a placeholder entry - uses the most common 5 character password (seed list is 6 characters and above) + const string listName = "BannedPasswords"; + var listController = new ListController(); + var entry = new ListEntryInfo(); + { + entry.DefinitionID = Null.NullInteger; + entry.PortalID = Null.NullInteger; + entry.ListName = listName; + entry.Value = "12345"; + entry.Text = "Placeholder"; + entry.SystemList = false; + } + + //add list to each portal and update primary alias + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + entry.PortalID = portal.PortalID; + entry.SystemList = false; + entry.ListName = listName + "-" + portal.PortalID; + listController.AddListEntry(entry); + + var defaultAlias = PortalController.GetPortalSetting("DefaultPortalAlias", portal.PortalID, String.Empty); + if (!String.IsNullOrEmpty(defaultAlias)) + { + foreach (var alias in TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portal.PortalID).Where(alias => alias.HTTPAlias == defaultAlias)) + { + alias.IsPrimary = true; + TestablePortalAliasController.Instance.UpdatePortalAlias(alias); + } + } + } + + int advancedFeaturesTabID = TabController.GetTabByTabPath(Null.NullInteger, "//Host//ProfessionalFeatures", Null.NullString); + + //Add Pages under Advanced Features Tab + AddProfessionalPreviewPage(advancedFeaturesTabID, + "//Host//ProfessionalFeatures//AdvancedUrlManagement", + "ProfessionalPreview", + "Advanced URL Management", + "Manage web servers in a web farm.", + "~/Icons/Sigma/AdvancedUrlMngmt_16x16.png", + "~/Icons/Sigma/AdvancedUrlMngmt_32x32.png"); + + // Add File Content Type + var typeController = new ContentTypeController(); + var contentTypeFile = (from t in typeController.GetContentTypes() where t.ContentType == "File" select t).SingleOrDefault(); + + if (contentTypeFile == null) + { + typeController.AddContentType(new ContentType { ContentType = "File" }); + } + + var fileContentType = (from t in typeController.GetContentTypes() where t.ContentType == "File" select t).SingleOrDefault(); + + + //only perform following for an existing installation upgrading + if (Globals.Status == Globals.UpgradeStatus.Upgrade) + { + UpdateFoldersForParentId(); + ImportDocumentLibraryCategories(); + ImportDocumentLibraryCategoryAssoc(fileContentType); + } + + //Add 404 Log + var logController = new LogController(); + var logTypeInfo = new LogTypeInfo + { + LogTypeKey = EventLogController.EventLogType.PAGE_NOT_FOUND_404.ToString(), + LogTypeFriendlyName = "HTTP Error Code 404 Page Not Found", + LogTypeDescription = "", + LogTypeCSSClass = "OperationFailure", + LogTypeOwner = "DotNetNuke.Logging.EventLogType" + }; + logController.AddLogType(logTypeInfo); + + //Add LogType + var logTypeConf = new LogTypeConfigInfo + { + LoggingIsActive = true, + LogTypeKey = EventLogController.EventLogType.PAGE_NOT_FOUND_404.ToString(), + KeepMostRecent = "100", + NotificationThreshold = 1, + NotificationThresholdTime = 1, + NotificationThresholdTimeType = LogTypeConfigInfo.NotificationThresholdTimeTypes.Seconds, + MailFromAddress = Null.NullString, + MailToAddress = Null.NullString, + LogTypePortalID = "*" + }; + logController.AddLogTypeConfigInfo(logTypeConf); + + UninstallPackage("DotNetNuke.SearchInput"); + + //enable password strength meter for new installs only + HostController.Instance.Update("EnableStrengthMeter", Globals.Status == Globals.UpgradeStatus.Install ? "Y" : "N"); + + //Add IP filter log type + var logTypeFilterInfo = new LogTypeInfo + { + LogTypeKey = EventLogController.EventLogType.IP_LOGIN_BANNED.ToString(), + LogTypeFriendlyName = "HTTP Error Code 403.6 forbidden ip address rejected", + LogTypeDescription = "", + LogTypeCSSClass = "OperationFailure", + LogTypeOwner = "DotNetNuke.Logging.EventLogType" + }; + logController.AddLogType(logTypeFilterInfo); + + //Add LogType + var logTypeFilterConf = new LogTypeConfigInfo + { + LoggingIsActive = true, + LogTypeKey = EventLogController.EventLogType.IP_LOGIN_BANNED.ToString(), + KeepMostRecent = "100", + NotificationThreshold = 1, + NotificationThresholdTime = 1, + NotificationThresholdTimeType = LogTypeConfigInfo.NotificationThresholdTimeTypes.Seconds, + MailFromAddress = Null.NullString, + MailToAddress = Null.NullString, + LogTypePortalID = "*" + }; + logController.AddLogTypeConfigInfo(logTypeFilterConf); + + var tabController = new TabController(); + + int tabID = TabController.GetTabByTabPath(Null.NullInteger, "//Host//SearchAdmin", Null.NullString); + if (tabID > Null.NullInteger) + tabController.DeleteTab(tabID, Null.NullInteger); + + var modDef = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("Search Admin"); + + if (modDef != null) + AddAdminPages("Search Admin", "Manage search settings associated with DotNetNuke's search capability.", "~/Icons/Sigma/Search_16x16_Standard.png", "~/Icons/Sigma/Search_32x32_Standard.png", true, modDef.ModuleDefID, "Search Admin", ""); + + CopyGettingStartedStyles(); + } + + private static void UpgradeToVersion711() + { + DesktopModuleController.DeleteDesktopModule("FileManager"); + + //Add TabUrl Logtypes + var logController = new LogController(); + var logTypeInfo = new LogTypeInfo + { + LogTypeKey = EventLogController.EventLogType.TABURL_CREATED.ToString(), + LogTypeFriendlyName = "TabURL created", + LogTypeDescription = "", + LogTypeCSSClass = "OperationSuccess", + LogTypeOwner = "DotNetNuke.Logging.EventLogType" + }; + logController.AddLogType(logTypeInfo); + + logTypeInfo.LogTypeKey = EventLogController.EventLogType.TABURL_UPDATED.ToString(); + logTypeInfo.LogTypeFriendlyName = "TabURL updated"; + logController.AddLogType(logTypeInfo); + + logTypeInfo.LogTypeKey = EventLogController.EventLogType.TABURL_DELETED.ToString(); + logTypeInfo.LogTypeFriendlyName = "TabURL deleted"; + logController.AddLogType(logTypeInfo); + + } + + private static void UpgradeToVersion712() + { + //update console module in Admin/Host page to set OrderTabsByHierarchy setting to true. + var portalController = new PortalController(); + var moduleController = new ModuleController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + var tabId = TabController.GetTabByTabPath(portal.PortalID, "//Admin", Null.NullString); + if (tabId != Null.NullInteger) + { + foreach (var module in new ModuleController().GetTabModules(tabId).Where(m => m.Value.ModuleDefinition.FriendlyName == "Console")) + { + moduleController.UpdateModuleSetting(module.Key, "OrderTabsByHierarchy", "True"); + } + } + } + + var hostTabId = TabController.GetTabByTabPath(Null.NullInteger, "//Host", Null.NullString); + if (hostTabId != Null.NullInteger) + { + foreach (var module in new ModuleController().GetTabModules(hostTabId).Where(m => m.Value.ModuleDefinition.FriendlyName == "Console")) + { + moduleController.UpdateModuleSetting(module.Key, "OrderTabsByHierarchy", "True"); + } + } + } + + private static ContentItem CreateFileContentItem() + { + var typeController = new ContentTypeController(); + var contentTypeFile = (from t in typeController.GetContentTypes() where t.ContentType == "File" select t).SingleOrDefault(); + + if (contentTypeFile == null) + { + contentTypeFile = new ContentType { ContentType = "File" }; + contentTypeFile.ContentTypeId = typeController.AddContentType(contentTypeFile); + } + + var objContent = new ContentItem + { + ContentTypeId = contentTypeFile.ContentTypeId, + Indexed = false, + }; + + objContent.ContentItemId = DotNetNuke.Entities.Content.Common.Util.GetContentController().AddContentItem(objContent); + + return objContent; + } + + private static void ImportDocumentLibraryCategoryAssoc(ContentType fileContentType) + { + DataProvider dataProvider = DataProvider.Instance(); + IDataReader dr; + try + { + dr = dataProvider.ExecuteReader("ImportDocumentLibraryCategoryAssoc"); + var termController = new TermController(); + var vocabulary = new VocabularyController().GetVocabularies().Single(v => v.Name == "Tags"); + var terms = termController.GetTermsByVocabulary(vocabulary.VocabularyId); + + while (dr.Read()) + { + var file = FileManager.Instance.GetFile((int)dr["FileId"]); + ContentItem attachContentItem; + if (file.ContentItemID == Null.NullInteger) + { + attachContentItem = CreateFileContentItem(); + file.ContentItemID = attachContentItem.ContentItemId; + FileManager.Instance.UpdateFile(file); + } + else + { + attachContentItem=Util.GetContentController().GetContentItem(file.ContentItemID); + } + + var term = terms.SingleOrDefault(t => t.Name == dr["CategoryName"].ToString()); + if (term == null) + { + term = new Term(dr["CategoryName"].ToString(), null, vocabulary.VocabularyId); + termController.AddTerm(term); + } + termController.AddTermToContent(term, attachContentItem); + } + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + + private static void ImportDocumentLibraryCategories() + { + VocabularyController vocabularyController = new VocabularyController(); + var defaultTags= (from v in vocabularyController.GetVocabularies() where v.IsSystem && v.Name == "Tags" select v).SingleOrDefault(); + + DataProvider dataProvider = DataProvider.Instance(); + dataProvider.ExecuteNonQuery("ImportDocumentLibraryCategories", defaultTags.VocabularyId); + } + + private static void UpdateFoldersForParentId() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpgradeFolders"); + //Move old messages to new format. Do this in smaller batches so we can send feedback to browser and don't time out + var foldersToConvert = DataProvider.Instance().GetLegacyFolderCount(); + var foldersRemaining = foldersToConvert; + + if (foldersRemaining > 0) + { + //Create an empty line + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "
    ", false); + } + + while (foldersRemaining > 0) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, string.Format("Converting old Folders to new format. Total: {0} [Remaining: {1}]
    ", foldersToConvert, foldersRemaining)); + try + { + DataProvider.Instance().UpdateLegacyFolders(); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + + foldersRemaining = DataProvider.Instance().GetLegacyFolderCount(); + } + + if (foldersToConvert > 0) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, string.Format("Conversion of old Folders Completed. Total Converted: {0}
    ", foldersToConvert)); + } + } + + + private static void UninstallPackage(string packageName) + { + var searchInput = PackageController.GetPackageByName(packageName); + if (searchInput != null) + { + var searchInputInstaller = new Installer.Installer(searchInput, Globals.ApplicationMapPath); + searchInputInstaller.UnInstall(true); + } + } + + private static void ConvertCoreNotificationTypeActionsFor700() + { + var notificationTypeNames = new[] { "FriendRequest", "FollowerRequest", "FollowBackRequest", "TranslationSubmitted" }; + + foreach (var name in notificationTypeNames) + { + var nt = NotificationsController.Instance.GetNotificationType(name); + + var actions = NotificationsController.Instance.GetNotificationTypeActions(nt.NotificationTypeId).ToList(); + + if (actions.Any()) + { + + foreach (var action in actions) + { + action.APICall = action.APICall.Replace(".ashx", ""); + NotificationsController.Instance.DeleteNotificationTypeAction(action.NotificationTypeActionId); + } + + NotificationsController.Instance.SetNotificationTypeActions(actions, nt.NotificationTypeId); + } + } + } + + private static void AddCoreNotificationTypesFor620() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddCoreNotificationTypesFor620"); + var actions = new List(); + + //Friend request + var type = new NotificationType { Name = "FriendRequest", Description = "Friend Request" }; + actions.Add(new NotificationTypeAction + { + NameResourceKey = "Accept", + DescriptionResourceKey = "AcceptFriend", + APICall = "DesktopModules/InternalServices/API/RelationshipService/AcceptFriend" + }); + NotificationsController.Instance.CreateNotificationType(type); + NotificationsController.Instance.SetNotificationTypeActions(actions, type.NotificationTypeId); + + //Follower + type = new NotificationType { Name = "FollowerRequest", Description = "Follower Request" }; + NotificationsController.Instance.CreateNotificationType(type); + + //Follow Back + type = new NotificationType { Name = "FollowBackRequest", Description = "Follow Back Request" }; + actions.Clear(); + actions.Add(new NotificationTypeAction + { + NameResourceKey = "FollowBack", + DescriptionResourceKey = "FollowBack", + ConfirmResourceKey = "", + APICall = "DesktopModules/InternalServices/API/RelationshipService/FollowBack" + }); + NotificationsController.Instance.CreateNotificationType(type); + NotificationsController.Instance.SetNotificationTypeActions(actions, type.NotificationTypeId); + + //Translation submitted + type = new NotificationType { Name = "TranslationSubmitted", Description = "Translation Submitted" }; + NotificationsController.Instance.CreateNotificationType(type); + } + + private static void ConvertOldMessages() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "ConvertOldMessages"); + //Move old messages to new format. Do this in smaller batches so we can send feedback to browser and don't time out + var messagesToConvert = InternalMessagingController.Instance.CountLegacyMessages(); + var messagesRemaining = messagesToConvert; + const int batchSize = 500; + + if (messagesRemaining > 0) + { + //Create an empty line + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "
    ", false); + } + + while (messagesRemaining > 0) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, string.Format("Converting old Messages to new format. Total: {0} [Remaining: {1}]
    ", messagesToConvert, messagesRemaining)); + try + { + InternalMessagingController.Instance.ConvertLegacyMessages(0, batchSize); + } + catch (Exception ex) + { + Exceptions.Exceptions.LogException(ex); + } + + messagesRemaining -= batchSize; + } + + if (messagesToConvert > 0) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, string.Format("Conversion of old Messages Completed. Total Converted: {0}
    ", messagesToConvert)); + } + } + + private static void ReplaceMessagingModule() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "ReplaceMessagingModule"); + var portalController = new PortalController(); + var moduleController = new ModuleController(); + var tabController = new TabController(); + + var moduleDefinition = ModuleDefinitionController.GetModuleDefinitionByFriendlyName("Message Center"); + if (moduleDefinition == null) return; + + var portals = portalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + if (portal.UserTabId > Null.NullInteger) + { + //Find TabInfo + TabInfo tab = tabController.GetTab(portal.UserTabId, portal.PortalID, true); + if (tab != null) + { + //Add new module to the page + AddModuleToPage(tab, moduleDefinition.ModuleDefID, "Message Center", "", true); + } + + foreach (KeyValuePair kvp in moduleController.GetTabModules(portal.UserTabId)) + { + var module = kvp.Value; + if (module.DesktopModule.FriendlyName == "Messaging") + { + //Delete the Module from the Modules list + moduleController.DeleteTabModule(module.TabID, module.ModuleID, false); + break; + } + } + } + } + } + + private static void MovePhotoProperty() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "MovePhotoProperty"); + var portalController = new PortalController(); + foreach (PortalInfo portal in portalController.GetPortals()) + { + var properties = ProfileController.GetPropertyDefinitionsByPortal(portal.PortalID).Cast(); + var propPhoto = properties.FirstOrDefault(p => p.PropertyName == "Photo"); + if (propPhoto != null) + { + var maxOrder = properties.Max(p => p.ViewOrder); + if (propPhoto.ViewOrder != maxOrder) + { + properties.Where(p => p.ViewOrder > propPhoto.ViewOrder).ToList().ForEach(p => + { + p.ViewOrder -= 2; + ProfileController.UpdatePropertyDefinition(p); + }); + propPhoto.ViewOrder = maxOrder; + ProfileController.UpdatePropertyDefinition(propPhoto); + } + } + } + } + + private static void UpdateChildPortalsDefaultPage() + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateChildPortalsDefaultPage"); + //Update Child Portal subHost.aspx + foreach (PortalAliasInfo aliasInfo in TestablePortalAliasController.Instance.GetPortalAliases().Values) + { + //For the alias to be for a child it must be of the form ...../child + int intChild = aliasInfo.HTTPAlias.IndexOf("/"); + if (intChild != -1 && intChild != (aliasInfo.HTTPAlias.Length - 1)) + { + var childPath = Globals.ApplicationMapPath + "\\" + aliasInfo.HTTPAlias.Substring(intChild + 1); + if (!string.IsNullOrEmpty(Globals.ApplicationPath)) + { + childPath = childPath.Replace("\\", "/"); + childPath = childPath.Replace(Globals.ApplicationPath, ""); + } + childPath = childPath.Replace("/", "\\"); + // check if File exists and make sure it's not the site's main default.aspx page + string childDefaultPage = childPath + "\\" + Globals.glbDefaultPage; + if (childPath != Globals.ApplicationMapPath && File.Exists(childDefaultPage)) + { + var objDefault = new System.IO.FileInfo(childDefaultPage); + var objSubHost = new System.IO.FileInfo(Globals.HostMapPath + "subhost.aspx"); + // check if upgrade is necessary + if (objDefault.Length != objSubHost.Length) + { + //check file is readonly + bool wasReadonly = false; + FileAttributes attributes = File.GetAttributes(childDefaultPage); + if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) + { + wasReadonly = true; + //remove readonly attribute + File.SetAttributes(childDefaultPage, FileAttributes.Normal); + } + + //Rename existing file + File.Copy(childDefaultPage, childPath + "\\old_" + Globals.glbDefaultPage, true); + + //copy file + File.Copy(Globals.HostMapPath + "subhost.aspx", childDefaultPage, true); + + //set back the readonly attribute + if (wasReadonly) + { + File.SetAttributes(childDefaultPage, FileAttributes.ReadOnly); + } + } + } + } + } + } + + private static void CopyGettingStartedStyles() + { + //copy getting started css to portals folder. + var hostGettingStartedFile = string.Format("{0}GettingStarted.css", Globals.HostMapPath); + var tabController = new TabController(); + foreach (PortalInfo portal in new PortalController().GetPortals()) + { + + if (File.Exists(hostGettingStartedFile)) + { + var portalFile = portal.HomeDirectoryMapPath + "GettingStarted.css"; + if (!File.Exists(portalFile)) + { + File.Copy(hostGettingStartedFile, portalFile); + } + } + + //update the getting started page to have this custom style sheet. + var gettingStartedTabId = PortalController.GetPortalSettingAsInteger("GettingStartedTabId", portal.PortalID, Null.NullInteger); + if (gettingStartedTabId > Null.NullInteger) + { + // check if tab exists + if (tabController.GetTab(gettingStartedTabId, portal.PortalID, true) != null) + { + tabController.UpdateTabSetting(gettingStartedTabId, "CustomStylesheet", "GettingStarted.css"); + } + } + } + } + + #endregion + + #region Public Methods + + ///----------------------------------------------------------------------------- + /// + /// AddAdminPages adds an Admin Page and an associated Module to all configured Portals + /// + ///The Name to give this new Tab + /// + ///The Icon for this new Tab + /// + ///A flag indicating whether the tab is visible + ///The Module Deinition Id for the module to be aded to this tab + ///The Module's title + ///The Module's icon + ///Modules Inherit the Pages View Permisions + /// + /// [cnurse] 11/11/2004 created + /// + ///----------------------------------------------------------------------------- + public static void AddAdminPages(string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible, int moduleDefId, string moduleTitle, string moduleIconFile, bool inheritPermissions) + { + var portalController = new PortalController(); + ArrayList portals = portalController.GetPortals(); + + //Add Page to Admin Menu of all configured Portals + for (int intPortal = 0; intPortal <= portals.Count - 1; intPortal++) + { + var portal = (PortalInfo) portals[intPortal]; + + //Create New Admin Page (or get existing one) + TabInfo newPage = AddAdminPage(portal, tabName, description, tabIconFile, tabIconFileLarge, isVisible); + + //Add Module To Page + AddModuleToPage(newPage, moduleDefId, moduleTitle, moduleIconFile, inheritPermissions); + } + } + + ///----------------------------------------------------------------------------- + /// + /// AddAdminPage adds an Admin Tab Page + /// + ///The Portal + ///The Name to give this new Tab + /// + ///The Icon for this new Tab + /// + ///A flag indicating whether the tab is visible + /// + /// [cnurse] 11/11/2004 created + /// + ///----------------------------------------------------------------------------- + public static TabInfo AddAdminPage(PortalInfo portal, string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddAdminPage:" + tabName); + var tabController = new TabController(); + TabInfo adminPage = tabController.GetTab(portal.AdminTabId, portal.PortalID, false); + + if ((adminPage != null)) + { + var tabPermissionCollection = new TabPermissionCollection(); + AddPagePermission(tabPermissionCollection, "View", Convert.ToInt32(portal.AdministratorRoleId)); + AddPagePermission(tabPermissionCollection, "Edit", Convert.ToInt32(portal.AdministratorRoleId)); + return AddPage(adminPage, tabName, description, tabIconFile, tabIconFileLarge, isVisible, tabPermissionCollection, true); + } + return null; + } + + ///----------------------------------------------------------------------------- + /// + /// AddHostPage adds a Host Tab Page + /// + ///The Name to give this new Tab + /// + ///The Icon for this new Tab + /// + ///A flag indicating whether the tab is visible + /// + /// [cnurse] 11/11/2004 created + /// + ///----------------------------------------------------------------------------- + public static TabInfo AddHostPage(string tabName, string description, string tabIconFile, string tabIconFileLarge, bool isVisible) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddHostPage:" + tabName); + var tabController = new TabController(); + TabInfo hostPage = tabController.GetTabByName("Host", Null.NullInteger); + + if ((hostPage != null)) + { + return AddPage(hostPage, tabName, description, tabIconFile, tabIconFileLarge, isVisible, new TabPermissionCollection(), true); + } + return null; + } + + ///----------------------------------------------------------------------------- + /// + /// AddModuleControl adds a new Module Control to the system + /// + /// + /// + ///The Module Definition Id + ///The key for this control in the Definition + ///The title of this control + ///Te source of ths control + ///The icon file + ///The type of control + ///The vieworder for this module + /// + /// [cnurse] 11/08/2004 documented + /// + ///----------------------------------------------------------------------------- + public static void AddModuleControl(int moduleDefId, string controlKey, string controlTitle, string controlSrc, string iconFile, SecurityAccessLevel controlType, int viewOrder) + { + //Call Overload with HelpUrl = Null.NullString + AddModuleControl(moduleDefId, controlKey, controlTitle, controlSrc, iconFile, controlType, viewOrder, Null.NullString); + } + + ///----------------------------------------------------------------------------- + /// + /// AddModuleDefinition adds a new Core Module Definition to the system + /// + /// + /// This overload asumes the module is an Admin module and not a Premium Module + /// + ///The Friendly Name of the Module to Add + ///Description of the Module + ///The Module Definition Name + ///The Module Definition Id of the new Module + /// + /// [cnurse] 10/14/2004 documented + /// + ///----------------------------------------------------------------------------- + public static int AddModuleDefinition(string desktopModuleName, string description, string moduleDefinitionName) + { + //Call overload with Premium=False and Admin=True + return AddModuleDefinition(desktopModuleName, description, moduleDefinitionName, false, true); + } + + ///----------------------------------------------------------------------------- + /// + /// AddModuleToPage adds a module to a Page + /// + /// + /// + ///The Page to add the Module to + ///The Module Deinition Id for the module to be aded to this tab + ///The Module's title + ///The Module's icon + ///Inherit the Pages View Permisions + /// + /// [cnurse] 11/16/2004 created + /// + ///----------------------------------------------------------------------------- + public static int AddModuleToPage(TabInfo page, int moduleDefId, string moduleTitle, string moduleIconFile, bool inheritPermissions) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddModuleToPage:" + moduleDefId); + var moduleController = new ModuleController(); + ModuleInfo moduleInfo; + int moduleId = Null.NullInteger; + + if ((page != null)) + { + bool isDuplicate = false; + foreach (var kvp in moduleController.GetTabModules(page.TabID)) + { + moduleInfo = kvp.Value; + if (moduleInfo.ModuleDefID == moduleDefId) + { + isDuplicate = true; + moduleId = moduleInfo.ModuleID; + } + } + + if (!isDuplicate) + { + moduleInfo = new ModuleInfo + { + ModuleID = Null.NullInteger, + PortalID = page.PortalID, + TabID = page.TabID, + ModuleOrder = -1, + ModuleTitle = moduleTitle, + PaneName = Globals.glbDefaultPane, + ModuleDefID = moduleDefId, + CacheTime = 0, + IconFile = moduleIconFile, + AllTabs = false, + Visibility = VisibilityState.None, + InheritViewPermissions = inheritPermissions + }; + + try + { + moduleId = moduleController.AddModule(moduleInfo); + } + catch (Exception exc) + { + Logger.Error(exc); + DnnInstallLogger.InstallLogError(exc); + } + } + } + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "AddModuleToPage:" + moduleDefId); + return moduleId; + } + + public static int AddModuleToPage(string tabPath, int portalId, int moduleDefId, string moduleTitle, string moduleIconFile, bool inheritPermissions) + { + var tabController = new TabController(); + int moduleId = Null.NullInteger; + + int tabID = TabController.GetTabByTabPath(portalId, tabPath, Null.NullString); + if ((tabID != Null.NullInteger)) + { + TabInfo tab = tabController.GetTab(tabID, portalId, true); + if ((tab != null)) + { + moduleId = AddModuleToPage(tab, moduleDefId, moduleTitle, moduleIconFile, inheritPermissions); + } + } + return moduleId; + } + + public static void AddModuleToPages(string tabPath, int moduleDefId, string moduleTitle, string moduleIconFile, bool inheritPermissions) + { + var objPortalController = new PortalController(); + var objTabController = new TabController(); + + ArrayList portals = objPortalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + int tabID = TabController.GetTabByTabPath(portal.PortalID, tabPath, Null.NullString); + if ((tabID != Null.NullInteger)) + { + TabInfo tab = objTabController.GetTab(tabID, portal.PortalID, true); + if ((tab != null)) + { + AddModuleToPage(tab, moduleDefId, moduleTitle, moduleIconFile, inheritPermissions); + } + } + } + } + /// ----------------------------------------------------------------------------- + /// + /// AddPortal manages the Installation of a new DotNetNuke Portal + /// + /// + /// + /// + /// [cnurse] 11/06/2004 created + /// + /// ----------------------------------------------------------------------------- + public static int AddPortal(XmlNode node, bool status, int indent) + { + + int portalId = -1; + try + { + string hostMapPath = Globals.HostMapPath; + string childPath = ""; + string domain = ""; + + if ((HttpContext.Current != null)) + { + domain = Globals.GetDomainName(HttpContext.Current.Request, true).ToLowerInvariant().Replace("/install", ""); + } + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "AddPortal:" + domain); + string portalName = XmlUtils.GetNodeValue(node.CreateNavigator(), "portalname"); + if (status) + { + if (HttpContext.Current != null) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, indent, "Creating Site: " + portalName + "
    "); + } + } + + var portalController = new PortalController(); + XmlNode adminNode = node.SelectSingleNode("administrator"); + if (adminNode != null) + { + string firstName = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "firstname"); + string lastName = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "lastname"); + string username = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "username"); + string password = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "password"); + string email = XmlUtils.GetNodeValue(adminNode.CreateNavigator(), "email"); + string description = XmlUtils.GetNodeValue(node.CreateNavigator(), "description"); + string keyWords = XmlUtils.GetNodeValue(node.CreateNavigator(), "keywords"); + string templateFileName = XmlUtils.GetNodeValue(node.CreateNavigator(), "templatefile"); + string serverPath = Globals.ApplicationMapPath + "\\"; + bool isChild = bool.Parse(XmlUtils.GetNodeValue(node.CreateNavigator(), "ischild")); + string homeDirectory = XmlUtils.GetNodeValue(node.CreateNavigator(), "homedirectory"); + + //Get the Portal Alias + XmlNodeList portalAliases = node.SelectNodes("portalaliases/portalalias"); + string strPortalAlias = domain; + if (portalAliases != null) + { + if (portalAliases.Count > 0) + { + if (!string.IsNullOrEmpty(portalAliases[0].InnerText)) + { + strPortalAlias = portalAliases[0].InnerText; + } + } + } + + //Create default email + if (string.IsNullOrEmpty(email)) + { + email = "admin@" + domain.Replace("www.", ""); + //Remove any domain subfolder information ( if it exists ) + if (email.IndexOf("/") != -1) + { + email = email.Substring(0, email.IndexOf("/")); + } + } + + if (isChild) + { + childPath = PortalController.GetPortalFolder(strPortalAlias); + } + + var template = FindBestTemplate(templateFileName); + var userInfo = CreateUserInfo(firstName, lastName, username, password, email); + + //Create Portal + portalId = portalController.CreatePortal(portalName, + userInfo, + description, + keyWords, + template, + homeDirectory, + strPortalAlias, + serverPath, + serverPath + childPath, + isChild); + + if (portalId > -1) + { + //Add Extra Aliases + if (portalAliases != null) + { + foreach (XmlNode portalAlias in portalAliases) + { + if (!string.IsNullOrEmpty(portalAlias.InnerText)) + { + if (status) + { + if (HttpContext.Current != null) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, indent, "Creating Site Alias: " + portalAlias.InnerText + "
    "); + } + } + portalController.AddPortalAlias(portalId, portalAlias.InnerText); + } + } + } + + //Force Administrator to Update Password on first log in + PortalInfo portal = portalController.GetPortal(portalId); + UserInfo adminUser = UserController.GetUserById(portalId, portal.AdministratorId); + adminUser.Membership.UpdatePassword = true; + UserController.UpdateUser(portalId, adminUser); + } + + + return portalId; + } + } + catch (Exception ex) + { + Logger.Error(ex); + + if (HttpContext.Current != null) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, indent, "Error: " + ex.Message + ex.StackTrace + "
    "); + DnnInstallLogger.InstallLogError(ex); + } + // failure + portalId = - 1; + } + return portalId; + } + + internal static UserInfo CreateUserInfo(string firstName, string lastName, string userName, string password, string email) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "CreateUserInfo:" + userName); + var adminUser = new UserInfo + { + FirstName = firstName, + LastName = lastName, + Username = userName, + DisplayName = firstName + " " + lastName, + Membership = {Password = password}, + Email = email, + IsSuperUser = false + }; + adminUser.Membership.Approved = true; + adminUser.Profile.FirstName = firstName; + adminUser.Profile.LastName = lastName; + adminUser.Membership.UpdatePassword = true; + return adminUser; + } + + internal static PortalController.PortalTemplateInfo FindBestTemplate(string templateFileName) + { + var templates = TestablePortalController.Instance.GetAvailablePortalTemplates(); + + //Load Template + var installTemplate = new XmlDocument(); + Upgrade.GetInstallTemplate(installTemplate); + //Parse the root node + XmlNode rootNode = installTemplate.SelectSingleNode("//dotnetnuke"); + String currentCulture = ""; + if (rootNode != null) + { + currentCulture = XmlUtils.GetNodeValue(rootNode.CreateNavigator(), "installCulture"); + } + + if(String.IsNullOrEmpty(currentCulture)) + { + currentCulture = Localization.Localization.SystemLocale; + } + currentCulture = currentCulture.ToLower(); + var defaultTemplates = + templates.Where(x => Path.GetFileName(x.TemplateFilePath) == templateFileName).ToList(); + + var match = defaultTemplates.FirstOrDefault(x => x.CultureCode.ToLower() == currentCulture); + if (match == null) + { + match = defaultTemplates.FirstOrDefault(x => x.CultureCode.ToLower().StartsWith(currentCulture.Substring(0, 2))); + } + if (match == null) + { + match = defaultTemplates.FirstOrDefault(x => string.IsNullOrEmpty(x.CultureCode)); + } + + if (match == null) + { + throw new Exception("Unable to locate specified portal template: " + templateFileName); + } + + return match; + } + + public static string BuildUserTable(IDataReader dr, string header, string message) + { + string warnings = Null.NullString; + var stringBuilder = new StringBuilder(); + bool hasRows = false; + + stringBuilder.Append("

    " + header + "

    "); + stringBuilder.Append("

    " + message + "

    "); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + while (dr.Read()) + { + hasRows = true; + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + stringBuilder.Append(""); + } + + stringBuilder.Append("
    IDUserNameFirst NameLast NameEmail
    " + dr.GetInt32(0) + "" + dr.GetString(1) + "" + dr.GetString(2) + "" + dr.GetString(3) + "" + dr.GetString(4) + "
    "); + + if (hasRows) + { + warnings = stringBuilder.ToString(); + } + + + return warnings; + } + + /// ----------------------------------------------------------------------------- + /// + /// CheckUpgrade checks whether there are any possible upgrade issues + /// + /// + /// [cnurse] 04/11/2006 created + /// + /// ----------------------------------------------------------------------------- + public static string CheckUpgrade() + { + DataProvider dataProvider = DataProvider.Instance(); + IDataReader dr; + string warnings = Null.NullString; + + try + { + dr = dataProvider.ExecuteReader("CheckUpgrade"); + + warnings = BuildUserTable(dr, "Duplicate SuperUsers", "We have detected that the following SuperUsers have duplicate entries as Portal Users. Although, no longer supported, these users may have been created in early Betas of DNN v3.0. You need to be aware that after the upgrade, these users will only be able to log in using the Super User Account's password."); + + if (dr.NextResult()) + { + warnings += BuildUserTable(dr, "Duplicate Portal Users", "We have detected that the following Users have duplicate entries (they exist in more than one portal). You need to be aware that after the upgrade, the password for some of these users may have been automatically changed (as the system now only uses one password per user, rather than one password per user per portal). It is important to remember that your Users can always retrieve their password using the Password Reminder feature, which will be sent to the Email addess shown in the table."); + } + } + catch (SqlException ex) + { + Logger.Error(ex); + warnings += ex.Message; + } + catch (Exception ex) + { + Logger.Error(ex); + warnings += ex.Message; + } + + try + { + dr = dataProvider.ExecuteReader("GetUserCount"); + dr.Read(); + int userCount = dr.GetInt32(0); +// ReSharper disable PossibleLossOfFraction + double time = userCount/10834; +// ReSharper restore PossibleLossOfFraction + if (userCount > 1000) + { + warnings += "

    More than 1000 Users

    This DotNetNuke Database has " + userCount + + " users. As the users and their profiles are transferred to a new format, it is estimated that the script will take ~" + time.ToString("F2") + + " minutes to execute.

    "; + } + } + catch (Exception ex) + { + Logger.Error(ex); + warnings += Environment.NewLine + Environment.NewLine + ex.Message; + } + + + return warnings; + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteInstallerFiles - clean up install config + /// If installwizard is ran again this will be recreated via the dotnetnuke.install.config.resources file + /// + /// + /// uses FileSystemUtils.DeleteFile as it checks for readonly attribute status + /// and changes it if required, as well as verifying file exists. + /// + /// ----------------------------------------------------------------------------- + public static void DeleteInstallerFiles() + { + FileSystemUtils.DeleteFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Install", "DotNetNuke.install.config")); + } + + /// ----------------------------------------------------------------------------- + /// + /// DeleteFiles - clean up deprecated files and folders + /// + /// + /// + /// Path to provider + /// The Version being Upgraded + /// Display status in UI? + /// + /// [swalker] 11/09/2004 created + /// + /// ----------------------------------------------------------------------------- + public static string DeleteFiles(string providerPath, Version version, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "DeleteFiles:" + Globals.FormatVersion(version)); + string exceptions = ""; + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "Cleaning Up Files: " + Globals.FormatVersion(version)); + } + + try + { + string listFile = Globals.InstallMapPath + "Cleanup\\" + GetStringVersion(version) + ".txt"; + + if (File.Exists(listFile)) + { + exceptions = FileSystemUtils.DeleteFiles(FileSystemUtils.ReadFile(listFile).Split('\r', '\n')); + } + } + catch (Exception ex) + { + Logger.Error(ex); + + exceptions += string.Format("Error: {0}{1}", ex.Message + ex.StackTrace, Environment.NewLine); + // log the results + DnnInstallLogger.InstallLogError(exceptions); + try + { + using (StreamWriter streamWriter = File.CreateText(providerPath + Globals.FormatVersion(version) + "_Config.log")) + { + streamWriter.WriteLine(exceptions); + streamWriter.Close(); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + if (writeFeedback) + { + HtmlUtils.WriteSuccessError(HttpContext.Current.Response, (string.IsNullOrEmpty(exceptions))); + } + + return exceptions; + } + + ///----------------------------------------------------------------------------- + /// + /// ExecuteScripts manages the Execution of Scripts from the Install/Scripts folder. + /// It is also triggered by InstallDNN and UpgradeDNN + /// + /// + /// + ///The path to the Data Provider + /// + /// [cnurse] 05/04/2005 created + /// + ///----------------------------------------------------------------------------- + public static void ExecuteScripts(string strProviderPath) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "ExecuteScripts:" + strProviderPath); + string scriptPath = Globals.ApplicationMapPath + "\\Install\\Scripts\\"; + if (Directory.Exists(scriptPath)) + { + string[] files = Directory.GetFiles(scriptPath); + foreach (string file in files) + { + //Execute if script is a provider script + if (file.IndexOf("." + DefaultProvider) != -1) + { + ExecuteScript(file, true); + // delete the file + try + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + } + } + } + + ///----------------------------------------------------------------------------- + /// + /// ExecuteScript executes a special script + /// + /// + /// + ///The script file to execute + /// + /// [cnurse] 04/11/2006 created + /// + ///----------------------------------------------------------------------------- + public static void ExecuteScript(string file) + { + //Execute if script is a provider script + if (file.IndexOf("." + DefaultProvider) != -1) + { + ExecuteScript(file, true); + } + } + + ///----------------------------------------------------------------------------- + /// + /// GetInstallTemplate retrieves the Installation Template as specifeid in web.config + /// + /// + /// + ///The Xml Document to load + ///A string which contains the error message - if appropriate + /// + /// [cnurse] 02/13/2007 created + /// + ///----------------------------------------------------------------------------- + public static string GetInstallTemplate(XmlDocument xmlDoc) + { + string errorMessage = Null.NullString; + string installTemplate = Config.GetSetting("InstallTemplate"); + try + { + xmlDoc.Load(Globals.ApplicationMapPath + "\\Install\\" + installTemplate); + } + catch + { + // error + errorMessage = "Failed to load Install template.

    "; + } + + return errorMessage; + } + + /// + /// SetInstalltemplate saves the XmlDocument back to Installation Template specified in web.config + /// + /// The Xml Document to save + /// A string which contains the error massage - if appropriate + public static string SetInstallTemplate(XmlDocument xmlDoc) + { + string errorMessage = Null.NullString; + string installTemplate = Config.GetSetting("InstallTemplate"); + string filePath = Globals.ApplicationMapPath + "\\Install\\" + installTemplate; + try + { + //ensure the file is not read-only + var attributes = File.GetAttributes(filePath); + if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) + { + // file is readonly, then remove it + attributes = attributes & ~FileAttributes.ReadOnly; + File.SetAttributes(filePath, attributes); + } + + xmlDoc.Save(filePath); + } + catch + { + // error + errorMessage = "Failed to save Install template.

    "; + } + + return errorMessage; + } + + ///----------------------------------------------------------------------------- + /// + /// GetInstallVersion retrieves the Base Instal Version as specifeid in the install + /// template + /// + /// + /// + ///The Install Template + /// + /// [cnurse] 02/13/2007 created + /// + ///----------------------------------------------------------------------------- + public static Version GetInstallVersion(XmlDocument xmlDoc) + { + string version = Null.NullString; + + //get base version + XmlNode node = xmlDoc.SelectSingleNode("//dotnetnuke"); + if ((node != null)) + { + version = XmlUtils.GetNodeValue(node.CreateNavigator(), "version"); + } + + return new Version(version); + } + + ///----------------------------------------------------------------------------- + /// + /// GetLogFile gets the filename for the version's log file + /// + /// + /// + ///The path to the Data Provider + ///The Version + /// + /// [cnurse] 02/16/2007 created + /// + ///----------------------------------------------------------------------------- + public static string GetLogFile(string providerPath, Version version) + { + return providerPath + GetStringVersion(version) + ".log.resources"; + } + + ///----------------------------------------------------------------------------- + /// + /// GetScriptFile gets the filename for the version + /// + /// + /// + ///The path to the Data Provider + ///The Version + /// + /// [cnurse] 02/16/2007 created + /// + ///----------------------------------------------------------------------------- + public static string GetScriptFile(string providerPath, Version version) + { + return providerPath + GetStringVersion(version) + "." + DefaultProvider; + } + + ///----------------------------------------------------------------------------- + /// + /// GetStringVersion gets the Version String (xx.xx.xx) from the Version + /// + /// + /// + ///The Version + /// + /// [cnurse] 02/15/2007 created + /// + ///----------------------------------------------------------------------------- + public static string GetStringVersion(Version version) + { + var versionArray = new int[3]; + versionArray[0] = version.Major; + versionArray[1] = version.Minor; + versionArray[2] = version.Build; + string stringVersion = Null.NullString; + for (int i = 0; i <= 2; i++) + { + if (versionArray[i] == 0) + { + stringVersion += "00"; + } + else if (versionArray[i] >= 1 && versionArray[i] <= 9) + { + stringVersion += "0" + versionArray[i]; + } + else + { + stringVersion += versionArray[i].ToString(); + } + if (i < 2) + { + stringVersion += "."; + } + } + return stringVersion; + } + + ///----------------------------------------------------------------------------- + /// + /// GetSuperUser gets the superuser from the Install Template + /// + /// + /// + ///The install Templae + ///a flag to determine whether to output feedback + /// + /// [cnurse] 02/16/2007 created + /// + ///----------------------------------------------------------------------------- + public static UserInfo GetSuperUser(XmlDocument xmlTemplate, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "GetSuperUser"); + XmlNode node = xmlTemplate.SelectSingleNode("//dotnetnuke/superuser"); + UserInfo superUser = null; + if ((node != null)) + { + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Configuring SuperUser:
    "); + } + + //Parse the SuperUsers nodes + string firstName = XmlUtils.GetNodeValue(node.CreateNavigator(), "firstname"); + string lastName = XmlUtils.GetNodeValue(node.CreateNavigator(), "lastname"); + string username = XmlUtils.GetNodeValue(node.CreateNavigator(), "username"); + string password = XmlUtils.GetNodeValue(node.CreateNavigator(), "password"); + string email = XmlUtils.GetNodeValue(node.CreateNavigator(), "email"); + string locale = XmlUtils.GetNodeValue(node.CreateNavigator(), "locale"); + string updatePassword = XmlUtils.GetNodeValue(node.CreateNavigator(), "updatepassword"); + + superUser = new UserInfo + { + PortalID = -1, + FirstName = firstName, + LastName = lastName, + Username = username, + DisplayName = firstName + " " + lastName, + Membership = {Password = password}, + Email = email, + IsSuperUser = true + }; + superUser.Membership.Approved = true; + + superUser.Profile.FirstName = firstName; + superUser.Profile.LastName = lastName; + superUser.Profile.PreferredLocale = locale; + superUser.Profile.PreferredTimeZone = TimeZoneInfo.Local; + + if(updatePassword.ToLowerInvariant() == "true") + { + superUser.Membership.UpdatePassword = true; + } + } + return superUser; + } + + ///----------------------------------------------------------------------------- + /// + /// GetUpgradeScripts gets an ArrayList of the Scripts required to Upgrade to the + /// current Assembly Version + /// + /// + /// + ///The path to the Data Provider + ///The current Database Version + /// + /// [cnurse] 02/14/2007 created + /// + ///----------------------------------------------------------------------------- + public static ArrayList GetUpgradeScripts(string providerPath, Version databaseVersion) + { + var scriptFiles = new ArrayList(); + string[] files = Directory.GetFiles(providerPath, "*." + DefaultProvider); + + Logger.TraceFormat("GetUpgradedScripts databaseVersion:{0} applicationVersion:{1}", databaseVersion, DotNetNukeContext.Current.Application.Version); + + foreach (string file in files) + { + // script file name must conform to ##.##.##.DefaultProviderName + if (file != null) + { + if (GetFileName(file).Length == 9 + DefaultProvider.Length) + { + var version = new Version(GetFileNameWithoutExtension(file)); + // check if script file is relevant for upgrade + if (version > databaseVersion && version <= DotNetNukeContext.Current.Application.Version) + { + scriptFiles.Add(file); + Logger.TraceFormat("GetUpgradedScripts including {0}", file); + } + else + { + Logger.TraceFormat("GetUpgradedScripts excluding {0}", file); + } + } + } + } + scriptFiles.Sort(); + + return scriptFiles; + } + + private static string GetFileName(string file) + { + return Path.GetFileName(file); + } + + ///----------------------------------------------------------------------------- + /// + /// InitialiseHostSettings gets the Host Settings from the Install Template + /// + /// + /// + ///The install Templae + ///a flag to determine whether to output feedback + /// + /// [cnurse] 02/16/2007 created + /// + ///----------------------------------------------------------------------------- + public static void InitialiseHostSettings(XmlDocument xmlTemplate, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InitialiseHostSettings"); + XmlNode node = xmlTemplate.SelectSingleNode("//dotnetnuke/settings"); + if ((node != null)) + { + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Loading Host Settings:
    "); + } + + //Need to clear the cache to pick up new HostSettings from the SQLDataProvider script + DataCache.RemoveCache(DataCache.HostSettingsCacheKey); + + //Parse the Settings nodes + foreach (XmlNode settingNode in node.ChildNodes) + { + string settingName = settingNode.Name; + string settingValue = settingNode.InnerText; + if (settingNode.Attributes != null) + { + XmlAttribute secureAttrib = settingNode.Attributes["Secure"]; + bool settingIsSecure = false; + if ((secureAttrib != null)) + { + if (secureAttrib.Value.ToLower() == "true") + { + settingIsSecure = true; + } + } + + string domainName = Globals.GetDomainName(HttpContext.Current.Request); + + switch (settingName) + { + case "HostURL": + if (string.IsNullOrEmpty(settingValue)) + { + settingValue = domainName; + } + break; + case "HostEmail": + if (string.IsNullOrEmpty(settingValue)) + { + settingValue = "support@" + domainName; + + //Remove any folders + settingValue = settingValue.Substring(0, settingValue.IndexOf("/")); + + //Remove port number + if (settingValue.IndexOf(":") != -1) + { + settingValue = settingValue.Substring(0, settingValue.IndexOf(":")); + } + } + + break; + } + + + HostController.Instance.Update(settingName, settingValue, settingIsSecure); + } + } + } + } + + ///----------------------------------------------------------------------------- + /// + /// InstallDatabase runs all the "scripts" identifed in the Install Template to + /// install the base version + /// + /// + /// + /// + ///The Xml Document to load + ///A flag that determines whether to output feedback to the Response Stream + /// + ///A string which contains the error message - if appropriate + /// + /// [cnurse] 02/13/2007 created + /// + ///----------------------------------------------------------------------------- + public static string InstallDatabase(Version version, string providerPath, XmlDocument xmlDoc, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallDatabase:" + Globals.FormatVersion(version)); + string defaultProvider = Config.GetDefaultProvider("data").Name; + string message = Null.NullString; + + //Output feedback line + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Installing Version: " + Globals.FormatVersion(version) + "
    "); + } + + //Parse the script nodes + XmlNode node = xmlDoc.SelectSingleNode("//dotnetnuke/scripts"); + if ((node != null)) + { + // Loop through the available scripts + message = (from XmlNode scriptNode in node.SelectNodes("script") select scriptNode.InnerText + "." + defaultProvider).Aggregate(message, (current, script) => current + ExecuteScript(providerPath + script, writeFeedback)); + } + + // update the version + Globals.UpdateDataBaseVersion(version); + + //Optionally Install the memberRoleProvider + message += InstallMemberRoleProvider(providerPath, writeFeedback); + + return message; + } + + ///----------------------------------------------------------------------------- + /// + /// InstallDNN manages the Installation of a new DotNetNuke Application + /// + /// + /// + ///The path to the Data Provider + /// + /// [cnurse] 11/06/2004 created + /// + ///----------------------------------------------------------------------------- + public static void InstallDNN(string strProviderPath) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallDNN:" + strProviderPath); + var xmlDoc = new XmlDocument(); + + // open the Install Template XML file + string errorMessage = GetInstallTemplate(xmlDoc); + + if (string.IsNullOrEmpty(errorMessage)) + { + //get base version + Version baseVersion = GetInstallVersion(xmlDoc); + + //Install Base Version + InstallDatabase(baseVersion, strProviderPath, xmlDoc, true); + + //Call Upgrade with the current DB Version to carry out any incremental upgrades + UpgradeDNN(strProviderPath, baseVersion); + + // parse Host Settings if available + InitialiseHostSettings(xmlDoc, true); + + // parse SuperUser if Available + UserInfo superUser = GetSuperUser(xmlDoc, true); + UserController.CreateUser(ref superUser); + + // parse File List if available + InstallFiles(xmlDoc, true); + + //Run any addition scripts in the Scripts folder + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Executing Additional Scripts:
    "); + ExecuteScripts(strProviderPath); + + //Install optional resources if present + InstallPackages("Module", true); + InstallPackages("Skin", true); + InstallPackages("Container", true); + InstallPackages("Language", true); + InstallPackages("Provider", true); + InstallPackages("AuthSystem", true); + InstallPackages("Package", true); + + //Set Status to None + Globals.SetStatus(Globals.UpgradeStatus.None); + + //download LP (and templates) if not using en-us + IInstallationStep ensureLpAndTemplate = new UpdateLanguagePackStep(); + ensureLpAndTemplate.Execute(); + + //install LP that contains templates if installing in a different language + var installConfig = InstallController.Instance.GetInstallConfig(); + string culture = installConfig.InstallCulture; + if (!culture.Equals("en-us", StringComparison.InvariantCultureIgnoreCase)) + { + string installFolder = HttpContext.Current.Server.MapPath("~/Install/language"); + string lpAndTemplates = installFolder + "\\installlanguage.resources"; + + if (File.Exists(lpAndTemplates)) + { + InstallPackage(lpAndTemplates, "Language", false); + } + } + + + + // parse portal(s) if available + XmlNodeList nodes = xmlDoc.SelectNodes("//dotnetnuke/portals/portal"); + if (nodes != null) + { + foreach (XmlNode node in nodes) + { + if ((node != null)) + { + int portalId = AddPortal(node, true, 2); + if (portalId > -1) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "Successfully Installed Site " + portalId + ":
    "); + } + else + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "Site failed to install:Error!
    "); + } + } + } + } + } + else + { + //500 Error - Redirect to ErrorPage + if ((HttpContext.Current != null)) + { + string url = "~/ErrorPage.aspx?status=500&error=" + errorMessage; + HttpContext.Current.Response.Clear(); + HttpContext.Current.Server.Transfer(url); + } + } + } + + ///----------------------------------------------------------------------------- + /// + /// InstallFiles intsalls any files listed in the Host Install Configuration file + /// + /// + /// + ///The Xml Document to load + ///A flag that determines whether to output feedback to the Response Stream + /// + /// [cnurse] 02/19/2007 created + /// + ///----------------------------------------------------------------------------- + public static void InstallFiles(XmlDocument xmlDoc, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallFiles"); + //Parse the file nodes + XmlNode node = xmlDoc.SelectSingleNode("//dotnetnuke/files"); + if ((node != null)) + { + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Loading Host Files:
    "); + } + ParseFiles(node, Null.NullInteger); + } + + //Synchronise Host Folder + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Synchronizing Host Files:
    "); + } + + FolderManager.Instance.Synchronize(Null.NullInteger, "", true, true); + } + + public static bool InstallPackage(string file, string packageType, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallPackage:" + file); + bool success = Null.NullBoolean; + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, "Installing Package File " + Path.GetFileNameWithoutExtension(file) + ": "); + } + + bool deleteTempFolder = true; + if (packageType == "Skin" || packageType == "Container") + { + deleteTempFolder = Null.NullBoolean; + } + + var installer = new Installer.Installer(new FileStream(file, FileMode.Open, FileAccess.Read), Globals.ApplicationMapPath, true, deleteTempFolder); + + //Check if manifest is valid + if (installer.IsValid) + { + installer.InstallerInfo.RepairInstall = true; + success = installer.Install(); + } + else + { + if (installer.InstallerInfo.ManifestFile == null) + { + //Missing manifest + if (packageType == "Skin" || packageType == "Container") + { + //Legacy Skin/Container + string tempInstallFolder = installer.TempInstallFolder; + string manifestFile = Path.Combine(tempInstallFolder, Path.GetFileNameWithoutExtension(file) + ".dnn"); + var manifestWriter = new StreamWriter(manifestFile); + manifestWriter.Write(LegacyUtil.CreateSkinManifest(file, packageType, tempInstallFolder)); + manifestWriter.Close(); + + installer = new Installer.Installer(tempInstallFolder, manifestFile, HttpContext.Current.Request.MapPath("."), true); + + //Set the Repair flag to true for Batch Install + installer.InstallerInfo.RepairInstall = true; + + success = installer.Install(); + } + else if(Globals.Status != Globals.UpgradeStatus.None) + { + var message = string.Format(Localization.Localization.GetString("InstallPackageError", Localization.Localization.ExceptionsResourceFile), file, "Manifest file missing"); + DnnInstallLogger.InstallLogError(message); + } + } + else + { + //log the failure log when installer is invalid and not caught by mainfest file missing. + foreach (var log in installer.InstallerInfo.Log.Logs + .Where(l => l.Type == LogType.Failure)) + { + Logger.Error(log.Description); + DnnInstallLogger.InstallLogError(log.Description); + } + + success = false; + } + } + + if (writeFeedback) + { + HtmlUtils.WriteSuccessError(HttpContext.Current.Response, success); + } + if (success) + { + // delete file + try + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + return success; + } + + public static void InstallPackages(string packageType, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "InstallPackages:" + packageType); + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Installing Optional " + packageType + "s:
    "); + } + string installPackagePath = Globals.ApplicationMapPath + "\\Install\\" + packageType; + if (Directory.Exists(installPackagePath)) + { + foreach (string file in Directory.GetFiles(installPackagePath)) + { + + if (Path.GetExtension(file.ToLower()) == ".zip" /*|| installLanguage */) + { + + InstallPackage(file, packageType, writeFeedback); + } + } + } + } + + public static bool IsNETFrameworkCurrent(string version) + { + bool isCurrent = Null.NullBoolean; + switch (version) + { + case "3.5": + //Try and instantiate a 3.5 Class + if (Reflection.CreateType("System.Data.Linq.DataContext", true) != null) + { + isCurrent = true; + } + break; + case "4.0": + //Look for requestValidationMode attribute + XmlDocument configFile = Config.Load(); + XPathNavigator configNavigator = configFile.CreateNavigator().SelectSingleNode("//configuration/system.web/httpRuntime|//configuration/location/system.web/httpRuntime"); + if (configNavigator != null && !string.IsNullOrEmpty(configNavigator.GetAttribute("requestValidationMode", ""))) + { + isCurrent = true; + } + break; + } + return isCurrent; + } + + public static void RemoveAdminPages(string tabPath) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveAdminPages:" + tabPath); + var portalController = new PortalController(); + var tabController = new TabController(); + + ArrayList portals = portalController.GetPortals(); + foreach (PortalInfo portal in portals) + { + int tabID = TabController.GetTabByTabPath(portal.PortalID, tabPath, Null.NullString); + if ((tabID != Null.NullInteger)) + { + tabController.DeleteTab(tabID, portal.PortalID); + } + } + } + + public static void RemoveHostPage(string pageName) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "RemoveHostPage:" + pageName); + var controller = new TabController(); + TabInfo skinsTab = controller.GetTabByName(pageName, Null.NullInteger); + if (skinsTab != null) + { + controller.DeleteTab(skinsTab.TabID, Null.NullInteger); + } + } + + public static void StartTimer() + { + //Start Upgrade Timer + + _startTime = DateTime.Now; + } + + public static void TryUpgradeNETFramework() + { + var eventLogController = new EventLogController(); + switch (Globals.NETFrameworkVersion.ToString(2)) + { + case "3.5": + if (!IsNETFrameworkCurrent("3.5")) + { + //Upgrade to .NET 3.5 + string upgradeFile = string.Format("{0}\\Config\\Net35.config", Globals.InstallMapPath); + string message = UpdateConfig(upgradeFile, DotNetNukeContext.Current.Application.Version, ".NET 3.5 Upgrade"); + if (string.IsNullOrEmpty(message)) + { + //Remove old AJAX file + FileSystemUtils.DeleteFile(Path.Combine(Globals.ApplicationMapPath, "bin\\System.Web.Extensions.dll")); + + //Log Upgrade + + eventLogController.AddLog("UpgradeNet", "Upgraded Site to .NET 3.5", PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.HOST_ALERT); + } + else + { + //Log Failed Upgrade + eventLogController.AddLog("UpgradeNet", string.Format("Upgrade to .NET 3.5 failed. Error reported during attempt to update:{0}", message), PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, EventLogController.EventLogType.HOST_ALERT); + } + } + break; + case "4.0": + if (!IsNETFrameworkCurrent("4.0")) + { + //Upgrade to .NET 4.0 + string upgradeFile = string.Format("{0}\\Config\\Net40.config", Globals.InstallMapPath); + string strMessage = UpdateConfig(upgradeFile, DotNetNukeContext.Current.Application.Version, ".NET 4.0 Upgrade"); + eventLogController.AddLog("UpgradeNet", + string.IsNullOrEmpty(strMessage) + ? "Upgraded Site to .NET 4.0" + : string.Format("Upgrade to .NET 4.0 failed. Error reported during attempt to update:{0}", strMessage), + PortalController.GetCurrentPortalSettings(), + UserController.GetCurrentUserInfo().UserID, + EventLogController.EventLogType.HOST_ALERT); + } + break; + } + } + + ///----------------------------------------------------------------------------- + /// + /// UpgradeApplication - This overload is used for general application upgrade operations. + /// + /// + /// Since it is not version specific and is invoked whenever the application is + /// restarted, the operations must be re-executable. + /// + /// + /// [cnurse] 11/6/2004 documented + /// [cnurse] 02/27/2007 made public so it can be called from Wizard + /// + ///----------------------------------------------------------------------------- + public static void UpgradeApplication() + { + try + { + //Remove UpdatePanel from Login Control - not neccessary in popup. + var loginControl = ModuleControlController.GetModuleControlByControlKey("Login", -1); + loginControl.SupportsPartialRendering = false; + + ModuleControlController.SaveModuleControl(loginControl, true); + + //Upgrade to .NET 3.5/4.0 + TryUpgradeNETFramework(); + + //Update the version of the client resources - so the cache is cleared + DataCache.ClearHostCache(false); + HostController.Instance.IncrementCrmVersion(true); + } + catch (Exception ex) + { + Logger.Error(ex); + var objEventLog = new EventLogController(); + var objEventLogInfo = new LogInfo(); + objEventLogInfo.AddProperty("Upgraded DotNetNuke", "General"); + objEventLogInfo.AddProperty("Warnings", "Error: " + ex.Message + Environment.NewLine); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLogInfo.BypassBuffering = true; + objEventLog.AddLog(objEventLogInfo); + try + { + Exceptions.Exceptions.LogException(ex); + } + catch (Exception exc) + { + Logger.Error(exc); + } + + } + + //Remove any .txt and .config files that may exist in the Install folder + foreach (string file in Directory.GetFiles(Globals.InstallMapPath + "Cleanup\\", "??.??.??.txt")) + { + FileSystemUtils.DeleteFile(file); + } + foreach (string file in Directory.GetFiles(Globals.InstallMapPath + "Config\\", "??.??.??.config")) + { + FileSystemUtils.DeleteFile(file); + } + } + + ///----------------------------------------------------------------------------- + /// + /// UpgradeApplication - This overload is used for version specific application upgrade operations. + /// + /// + /// This should be used for file system modifications or upgrade operations which + /// should only happen once. Database references are not recommended because future + /// versions of the application may result in code incompatibilties. + /// + /// + /// [cnurse] 11/6/2004 documented + /// + ///----------------------------------------------------------------------------- + public static string UpgradeApplication(string providerPath, Version version, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + Localization.Localization.GetString("ApplicationUpgrades", Localization.Localization.GlobalResourceFile) + ": " + version.ToString(3)); + string exceptions = ""; + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, Localization.Localization.GetString("ApplicationUpgrades", Localization.Localization.GlobalResourceFile) + " : " + Globals.FormatVersion(version)); + } + try + { + switch (version.ToString(3)) + { + case "3.2.3": + UpgradeToVersion323(); + break; + case "4.4.0": + UpgradeToVersion440(); + break; + case "4.7.0": + UpgradeToVersion470(); + break; + case "4.8.2": + UpgradeToVersion482(); + break; + case "5.0.0": + UpgradeToVersion500(); + break; + case "5.0.1": + UpgradeToVersion501(); + break; + case "5.1.0": + UpgradeToVersion510(); + break; + case "5.1.1": + UpgradeToVersion511(); + break; + case "5.1.3": + UpgradeToVersion513(); + break; + case "5.2.0": + UpgradeToVersion520(); + break; + case "5.2.1": + UpgradeToVersion521(); + break; + case "5.3.0": + UpgradeToVersion530(); + break; + case "5.4.0": + UpgradeToVersion540(); + break; + case "5.4.3": + UpgradeToVersion543(); + break; + case "5.5.0": + UpgradeToVersion550(); + break; + case "5.6.0": + UpgradeToVersion560(); + break; + case "5.6.2": + UpgradeToVersion562(); + break; + case "6.0.0": + UpgradeToVersion600(); + break; + case "6.0.1": + UpgradeToVersion601(); + break; + case "6.0.2": + UpgradeToVersion602(); + break; + case "6.1.0": + UpgradeToVersion610(); + break; + case "6.1.2": + UpgradeToVersion612(); + break; + case "6.1.3": + UpgradeToVersion613(); + break; + case "6.2.0": + UpgradeToVersion620(); + break; + case "6.2.1": + UpgradeToVersion621(); + break; + case "6.2.3": + UpgradeToVersion623(); + break; + case "6.2.4": + UpgradeToVersion624(); + break; + case "7.0.0": + UpgradeToVersion700(); + break; + case "7.1.0": + UpgradeToVersion710(); + break; + case "7.1.1": + UpgradeToVersion711(); + break; + case "7.1.2": + UpgradeToVersion712(); + break; + } + } + catch (Exception ex) + { + Logger.Error(ex); + exceptions += string.Format("Error: {0}{1}", ex.Message + ex.StackTrace, Environment.NewLine); + // log the results + if (string.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + Localization.Localization.GetString("ApplicationUpgrades", Localization.Localization.GlobalResourceFile) + ": " + version.ToString(3)); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + + try + { + using (StreamWriter streamWriter = File.CreateText(providerPath + Globals.FormatVersion(version) + "_Application.log.resources")) + { + streamWriter.WriteLine(exceptions); + streamWriter.Close(); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + + if (writeFeedback) + { + HtmlUtils.WriteSuccessError(HttpContext.Current.Response, (string.IsNullOrEmpty(exceptions))); + } + + return exceptions; + } + + public static string UpdateConfig(string providerPath, Version version, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + Globals.FormatVersion(version)); + if (writeFeedback) + { + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, string.Format("Updating Config Files: {0}", Globals.FormatVersion(version))); + } + string strExceptions = UpdateConfig(providerPath, Globals.InstallMapPath + "Config\\" + GetStringVersion(version) + ".config", version, "Core Upgrade"); + if (string.IsNullOrEmpty(strExceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + Globals.FormatVersion(version)); + } + else + { + DnnInstallLogger.InstallLogError(strExceptions); + } + + if (writeFeedback) + { + HtmlUtils.WriteSuccessError(HttpContext.Current.Response, (string.IsNullOrEmpty(strExceptions))); + } + + return strExceptions; + } + + public static string UpdateConfig(string configFile, Version version, string reason) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + version.ToString(3)); + string exceptions = ""; + if (File.Exists(configFile)) + { + //Create XmlMerge instance from config file source + StreamReader stream = File.OpenText(configFile); + try + { + var merge = new XmlMerge(stream, version.ToString(3), reason); + + //Process merge + merge.UpdateConfigs(); + } + catch (Exception ex) + { + exceptions += String.Format("Error: {0}{1}", ex.Message + ex.StackTrace, Environment.NewLine); + Exceptions.Exceptions.LogException(ex); + } + finally + { + //Close stream + stream.Close(); + } + } + if (string.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + version.ToString(3)); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + return exceptions; + } + + public static string UpdateConfig(string providerPath, string configFile, Version version, string reason) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + version.ToString(3)); + string exceptions = ""; + if (File.Exists(configFile)) + { + //Create XmlMerge instance from config file source + StreamReader stream = File.OpenText(configFile); + try + { + var merge = new XmlMerge(stream, version.ToString(3), reason); + + //Process merge + merge.UpdateConfigs(); + } + catch (Exception ex) + { + Logger.Error(ex); + exceptions += string.Format("Error: {0}{1}", ex.Message + ex.StackTrace, Environment.NewLine); + // log the results + try + { + using (StreamWriter streamWriter = File.CreateText(providerPath + Globals.FormatVersion(version) + "_Config.log")) + { + streamWriter.WriteLine(exceptions); + streamWriter.Close(); + } + } + catch (Exception exc) + { + Logger.Error(exc); + } + } + finally + { + //Close stream + stream.Close(); + } + } + if (string.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogEnd", Localization.Localization.GlobalResourceFile) + "UpdateConfig:" + version.ToString(3)); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + return exceptions; + } + + + ///----------------------------------------------------------------------------- + /// + /// UpgradeDNN manages the Upgrade of an exisiting DotNetNuke Application + /// + /// + /// + ///The path to the Data Provider + ///The current Database Version + /// + /// [cnurse] 11/06/2004 created (Upgrade code extracted from AutoUpgrade) + /// [cnurse] 11/10/2004 version specific upgrades extracted to ExecuteScript + /// [cnurse] 01/20/2005 changed to Public so Upgrade can be manually controlled + /// + ///----------------------------------------------------------------------------- + public static void UpgradeDNN(string providerPath, Version dataBaseVersion) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpgradeDNN:" + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version)); + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Upgrading to Version: " + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version) + "
    "); + + //Process the Upgrade Script files + var versions = new List(); + foreach (string scriptFile in GetUpgradeScripts(providerPath, dataBaseVersion)) + { + versions.Add(new Version(GetFileNameWithoutExtension(scriptFile))); + UpgradeVersion(scriptFile, true); + } + + foreach (Version ver in versions) + { + //' perform version specific application upgrades + UpgradeApplication(providerPath, ver, true); + } + + foreach (Version ver in versions) + { + // delete files which are no longer used + DeleteFiles(providerPath, ver, true); + } + foreach (Version ver in versions) + { + //execute config file updates + UpdateConfig(providerPath, ver, true); + } + + // perform general application upgrades + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, "Performing General Upgrades
    "); + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("GeneralUpgrades", Localization.Localization.GlobalResourceFile)); + UpgradeApplication(); + + DataCache.ClearHostCache(true); + } + + internal static string GetFileNameWithoutExtension(string scriptFile) + { + return Path.GetFileNameWithoutExtension(scriptFile); + } + + public static string UpgradeIndicator(Version version, bool isLocal, bool isSecureConnection) + { + return UpgradeIndicator(version, DotNetNukeContext.Current.Application.Type, DotNetNukeContext.Current.Application.Name, "", isLocal, isSecureConnection); + } + + public static string UpgradeIndicator(Version version, string packageType, string packageName, string culture, bool isLocal, bool isSecureConnection) + { + string url = ""; + if (Host.CheckUpgrade && version != new Version(0, 0, 0)) + { + url = DotNetNukeContext.Current.Application.UpgradeUrl + "/update.aspx"; + if (UrlUtils.IsSecureConnectionOrSslOffload(HttpContext.Current.Request)) + { + url = url.Replace("http://", "https://"); + } + url += "?core=" + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, "00", 3, ""); + url += "&version=" + Globals.FormatVersion(version, "00", 3, ""); + url += "&type=" + packageType; + url += "&name=" + packageName; + if (packageType.ToLowerInvariant() == "module") + { + var moduleType = (from m in ModulesController.GetInstalledModules() where m.ModuleName == packageName select m).SingleOrDefault(); + if (moduleType != null) + { + url += "&no=" + moduleType.Instances; + } + } + url += "&id=" + Host.GUID; + if (packageType.ToUpper() == DotNetNukeContext.Current.Application.Type.ToUpper()) + { + var portals = new PortalController().GetPortals(); + url += "&no=" + portals.Count; + url += "&os=" + Globals.FormatVersion(Globals.OperatingSystemVersion, "00", 2, ""); + url += "&net=" + Globals.FormatVersion(Globals.NETFrameworkVersion, "00", 2, ""); + url += "&db=" + Globals.FormatVersion(Globals.DatabaseEngineVersion, "00", 2, ""); + var source = Config.GetSetting("Source"); + if (!string.IsNullOrEmpty(source)) + { + url += "&src=" + source; + } + } + if (!string.IsNullOrEmpty(culture)) + { + url += "&culture=" + culture; + } + } + return url; + } + + public static string UpgradeRedirect() + { + return UpgradeRedirect(DotNetNukeContext.Current.Application.Version, DotNetNukeContext.Current.Application.Type, DotNetNukeContext.Current.Application.Name, ""); + } + + public static string UpgradeRedirect(Version version, string packageType, string packageName, string culture) + { + string url; + if (!string.IsNullOrEmpty(Config.GetSetting("UpdateServiceRedirect"))) + { + url = Config.GetSetting("UpdateServiceRedirect"); + } + else + { + url = DotNetNukeContext.Current.Application.UpgradeUrl + "/redirect.aspx"; + url += "?core=" + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, "00", 3, ""); + url += "&version=" + Globals.FormatVersion(version, "00", 3, ""); + url += "&type=" + packageType; + url += "&name=" + packageName; + if (!string.IsNullOrEmpty(culture)) + { + url += "&culture=" + culture; + } + } + return url; + } + + ///----------------------------------------------------------------------------- + /// + /// UpgradeVersion upgrades a single version + /// + /// + /// + ///The upgrade script file + ///Write status to Response Stream? + /// + /// [cnurse] 02/14/2007 created + /// + ///----------------------------------------------------------------------------- + public static string UpgradeVersion(string scriptFile, bool writeFeedback) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpgradeVersion:" + scriptFile); + var version = new Version(GetFileNameWithoutExtension(scriptFile)); + string exceptions = Null.NullString; + + // verify script has not already been run + if (!Globals.FindDatabaseVersion(version.Major, version.Minor, version.Build)) + { + // execute script file (and version upgrades) for version + exceptions = ExecuteScript(scriptFile, writeFeedback); + + // update the version + Globals.UpdateDataBaseVersion(version); + + var eventLogController = new EventLogController(); + var eventLogInfo = new LogInfo(); + eventLogInfo.AddProperty("Upgraded DotNetNuke", "Version: " + Globals.FormatVersion(version)); + if (exceptions.Length > 0) + { + eventLogInfo.AddProperty("Warnings", exceptions); + } + else + { + eventLogInfo.AddProperty("No Warnings", ""); + } + eventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + eventLogInfo.BypassBuffering = true; + eventLogController.AddLog(eventLogInfo); + } + if (string.IsNullOrEmpty(exceptions)) + { + DnnInstallLogger.InstallLogInfo(Localization.Localization.GetString("LogStart", Localization.Localization.GlobalResourceFile) + "UpgradeVersion:" + scriptFile); + } + else + { + DnnInstallLogger.InstallLogError(exceptions); + } + return exceptions; + } + + protected static bool IsLanguageEnabled(int portalid, string code) + { + Locale enabledLanguage; + return LocaleController.Instance.GetLocales(portalid).TryGetValue(code, out enabledLanguage); + } + + public static string ActivateLicense() + { + var isLicensable = (File.Exists(HttpContext.Current.Server.MapPath("~\\bin\\DotNetNuke.Professional.dll")) || File.Exists(HttpContext.Current.Server.MapPath("~\\bin\\DotNetNuke.Enterprise.dll"))); + var activationResult = ""; + + if (isLicensable) + { + var sku = File.Exists(HttpContext.Current.Server.MapPath("~\\bin\\DotNetNuke.Enterprise.dll")) ? "DNNENT" : "DNNPRO"; + HtmlUtils.WriteFeedback(HttpContext.Current.Response, 2, Localization.Localization.GetString("ActivatingLicense", Localization.Localization.GlobalResourceFile)); + + var installConfig = InstallController.Instance.GetInstallConfig(); + var licenseConfig = (installConfig != null) ? installConfig.License : null; + + if (licenseConfig != null) + { + dynamic licenseActivation = Reflection.CreateObject(Reflection.CreateType("DotNetNuke.Professional.LicenseActivation.ViewLicx")); + licenseActivation.AutoActivation(licenseConfig.AccountEmail, licenseConfig.InvoiceNumber, licenseConfig.WebServer, licenseConfig.LicenseType, sku); + activationResult = licenseActivation.LicenseResult; + + //Log Event to Event Log + var objEventLog = new EventLogController(); + objEventLog.AddLog("License Activation", + "License Activated during install for: " + licenseConfig.AccountEmail + " | invoice: " + licenseConfig.InvoiceNumber, + EventLogController.EventLogType.HOST_ALERT); + } + } + + return activationResult; + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Url/FriendlyUrl/FriendlyUrlProvider.cs b/DNN Platform/Library/Services/Url/FriendlyUrl/FriendlyUrlProvider.cs new file mode 100644 index 00000000000..c94c7b07190 --- /dev/null +++ b/DNN Platform/Library/Services/Url/FriendlyUrl/FriendlyUrlProvider.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.ComponentModel; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Services.Url.FriendlyUrl +{ + public abstract class FriendlyUrlProvider + { + #region "Shared/Static Methods" + + //return the provider + public static FriendlyUrlProvider Instance() + { + return ComponentFactory.GetComponent(); + } + + #endregion + + #region "Abstract Methods" + + public abstract string FriendlyUrl(TabInfo tab, string path); + + public abstract string FriendlyUrl(TabInfo tab, string path, string pageName); + + public abstract string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings settings); + + public abstract string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias); + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/UserProfile/UserProfilePageHandler.cs b/DNN Platform/Library/Services/UserProfile/UserProfilePageHandler.cs new file mode 100644 index 00000000000..ced982a3ba6 --- /dev/null +++ b/DNN Platform/Library/Services/UserProfile/UserProfilePageHandler.cs @@ -0,0 +1,148 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; + +#endregion + +namespace DotNetNuke.Services.UserProfile +{ + public class UserProfilePageHandler : IHttpHandler + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (UserProfilePageHandler)); + #region IHttpHandler Members + + /// ----------------------------------------------------------------------------- + /// + /// This handler handles requests for LinkClick.aspx, but only those specifc + /// to file serving + /// + /// System.Web.HttpContext) + /// + /// + /// + /// [cpaterra] 4/19/2006 Created + /// + /// ----------------------------------------------------------------------------- + public void ProcessRequest(HttpContext context) + { + PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings(); + int UserId = Null.NullInteger; + int PortalId = _portalSettings.PortalId; + + try + { + //try UserId + if (!string.IsNullOrEmpty(context.Request.QueryString["UserId"])) + { + UserId = Int32.Parse(context.Request.QueryString["UserId"]); + if (UserController.GetUserById(PortalId, UserId) == null) + { + //The user cannot be found (potential DOS) + Exceptions.Exceptions.ProcessHttpException(context.Request); + + } + } + + if (UserId == Null.NullInteger) + { + //try userName + if (!string.IsNullOrEmpty(context.Request.QueryString["UserName"])) + { + UserId = GetUserId(context.Request.QueryString["UserName"], PortalId); + } + } + + if (UserId == Null.NullInteger) + { + //try user + string user = context.Request.QueryString["User"]; + if (!string.IsNullOrEmpty(user)) + { + if (!Int32.TryParse(user, out UserId)) + { + //User is not an integer, so try it as a name + UserId = GetUserId(user, PortalId); + } + else + { + if (UserController.GetUserById(PortalId, UserId) == null) + { + //The user cannot be found (potential DOS) + Exceptions.Exceptions.ProcessHttpException(context.Request); + + } + } + } + } + + if (UserId == Null.NullInteger) + { + //The user cannot be found (potential DOS) + Exceptions.Exceptions.ProcessHttpException(context.Request); + } + } + catch (Exception exc) + { + Logger.Debug(exc); + //The user cannot be found (potential DOS) + Exceptions.Exceptions.ProcessHttpException(context.Request); + } + + //Redirect to Userprofile Page + context.Response.Redirect(Globals.UserProfileURL(UserId), true); + } + + public bool IsReusable + { + get + { + return true; + } + } + + #endregion + + private static int GetUserId(string username, int PortalId) + { + int _UserId = Null.NullInteger; + UserInfo userInfo = UserController.GetUserByName(PortalId, username); + if (userInfo != null) + { + _UserId = userInfo.UserID; + } + else + { + //The user cannot be found (potential DOS) + Exceptions.Exceptions.ProcessHttpException(); + } + return _UserId; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/UserProfile/UserProfilePicHandler.cs b/DNN Platform/Library/Services/UserProfile/UserProfilePicHandler.cs new file mode 100644 index 00000000000..5d322d0349e --- /dev/null +++ b/DNN Platform/Library/Services/UserProfile/UserProfilePicHandler.cs @@ -0,0 +1,206 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion + +#region Usings + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using System.IO; +using DotNetNuke.Services.Localization.Internal; + +#endregion + +namespace DotNetNuke.Services.UserProfile +{ + public class UserProfilePicHandler : IHttpHandler + { + #region IHttpHandler Members + + public void ProcessRequest(HttpContext context) + { + SetupCulture(); + + var userId = -1; + var width = 55; + var height = 55; + var size = ""; + try + { + if (!String.IsNullOrEmpty(context.Request.QueryString["userid"])) + { + userId = Convert.ToInt32(context.Request.QueryString["userid"]); + } + + if (!String.IsNullOrEmpty(context.Request.QueryString["w"])) + { + width = Convert.ToInt32(context.Request.QueryString["w"]); + } + + if (!String.IsNullOrEmpty(context.Request.QueryString["h"])) + { + height = Convert.ToInt32(context.Request.QueryString["h"]); + } + if (!String.IsNullOrEmpty(context.Request.QueryString["size"])) + { + size = context.Request.QueryString["size"]; + } + + } + catch (Exception) + { + Exceptions.Exceptions.ProcessHttpException(context.Request); + } + + if (height > 64) {height = 64;} + if (width > 64) { width = 64; } + + + CalculateSize(ref height, ref width, ref size); + + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + var userController = new UserController(); + var user = userController.GetUser(settings.PortalId, userId); + + FileInfo fileInfo ; + string ext; + if (user == null) + { + fileInfo = new FileInfo(context.Request.MapPath("~/images/no_avatar.gif")); + ext = ".gif"; + } + else + { + fileInfo = new FileInfo(context.Request.MapPath(user.Profile.PhotoURLFile)); + + if (fileInfo.Exists) + { + ext = fileInfo.Extension; + } + else + { + fileInfo = new FileInfo(context.Request.MapPath("~/images/no_avatar.gif")); + ext = ".gif"; + } + } + + string sizedPhoto = fileInfo.FullName.Replace(ext, "_" + size + ext); + + if (IsImageExtension(ext) != true) + { + context.Response.End(); + } + + if (!File.Exists(sizedPhoto)) + { + //need to create the photo + File.Copy(fileInfo.FullName, sizedPhoto); + sizedPhoto = ImageUtils.CreateImage(sizedPhoto, height, width); + } + + switch (ext) + { + case ".png": + context.Response.ContentType = "image/png"; + break; + case ".jpeg": + case ".jpg": + context.Response.ContentType = "image/jpeg"; + break; + case ".gif": + context.Response.ContentType = "image/gif"; + break; + + } + context.Response.WriteFile(sizedPhoto); + context.Response.Cache.SetCacheability(HttpCacheability.Public); + context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(1)); + context.Response.Cache.SetMaxAge(new TimeSpan(0, 1, 0)); + context.Response.AddHeader("Last-Modified", DateTime.Now.ToString("r")); + context.Response.End(); + + } + + private void CalculateSize(ref int height, ref int width, ref string size) + { + if (height > 0 && height <= 32) + { + height = 32; + width = 32; + size = "xs"; + } + else if (height > 32 && height <= 50) + { + height = 50; + width = 50; + size = "s"; + } + else if (height > 50 && height <= 64) + { + height = 64; + width = 64; + size = "l"; + } + //set a default if unprocessed + if (String.IsNullOrEmpty(size)) + { + height = 32; + width = 32; + size = "xs"; + } + } + + + private bool IsImageExtension(string extension) + { + List imageExtensions = new List { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG", ".JPEG", ".ICO" }; + return imageExtensions.Contains(extension.ToUpper()); + } + + private void SetupCulture() + { + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + if (settings == null) return; + + CultureInfo pageLocale = TestableLocalization.Instance.GetPageLocale(settings); + if (pageLocale != null) + { + TestableLocalization.Instance.SetThreadCultures(pageLocale, settings); + } + } + + public bool IsReusable + { + get + { + return false; + } + } + + #endregion + + } +} diff --git a/DNN Platform/Library/Services/Vendors/AffiliateController.cs b/DNN Platform/Library/Services/Vendors/AffiliateController.cs new file mode 100644 index 00000000000..3203f59cb23 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/AffiliateController.cs @@ -0,0 +1,64 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + public class AffiliateController + { + public ArrayList GetAffiliates(int VendorId) + { + return CBO.FillCollection(DataProvider.Instance().GetAffiliates(VendorId), typeof (AffiliateInfo)); + } + + public AffiliateInfo GetAffiliate(int AffiliateId, int VendorId, int PortalID) + { + return (AffiliateInfo) CBO.FillObject(DataProvider.Instance().GetAffiliate(AffiliateId, VendorId, PortalID), typeof (AffiliateInfo)); + } + + public void DeleteAffiliate(int AffiliateId) + { + DataProvider.Instance().DeleteAffiliate(AffiliateId); + } + + public void AddAffiliate(AffiliateInfo objAffiliate) + { + DataProvider.Instance().AddAffiliate(objAffiliate.VendorId, objAffiliate.StartDate, objAffiliate.EndDate, objAffiliate.CPC, objAffiliate.CPA); + } + + public void UpdateAffiliate(AffiliateInfo objAffiliate) + { + DataProvider.Instance().UpdateAffiliate(objAffiliate.AffiliateId, objAffiliate.StartDate, objAffiliate.EndDate, objAffiliate.CPC, objAffiliate.CPA); + } + + public void UpdateAffiliateStats(int AffiliateId, int Clicks, int Acquisitions) + { + DataProvider.Instance().UpdateAffiliateStats(AffiliateId, Clicks, Acquisitions); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/AffiliateInfo.cs b/DNN Platform/Library/Services/Vendors/AffiliateInfo.cs new file mode 100644 index 00000000000..4cdbd7db79a --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/AffiliateInfo.cs @@ -0,0 +1,163 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + [Serializable] + public class AffiliateInfo + { + private int _Acquisitions; + private int _AffiliateId; + private double _CPA; + private double _CPATotal; + private double _CPC; + private double _CPCTotal; + private int _Clicks; + private DateTime _EndDate; + private DateTime _StartDate; + private int _VendorId; + + public int AffiliateId + { + get + { + return _AffiliateId; + } + set + { + _AffiliateId = value; + } + } + + public int VendorId + { + get + { + return _VendorId; + } + set + { + _VendorId = value; + } + } + + public DateTime StartDate + { + get + { + return _StartDate; + } + set + { + _StartDate = value; + } + } + + public DateTime EndDate + { + get + { + return _EndDate; + } + set + { + _EndDate = value; + } + } + + public double CPC + { + get + { + return _CPC; + } + set + { + _CPC = value; + } + } + + public int Clicks + { + get + { + return _Clicks; + } + set + { + _Clicks = value; + } + } + + public double CPCTotal + { + get + { + return _CPCTotal; + } + set + { + _CPCTotal = value; + } + } + + public double CPA + { + get + { + return _CPA; + } + set + { + _CPA = value; + } + } + + public int Acquisitions + { + get + { + return _Acquisitions; + } + set + { + _Acquisitions = value; + } + } + + public double CPATotal + { + get + { + return _CPATotal; + } + set + { + _CPATotal = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/BannerController.cs b/DNN Platform/Library/Services/Vendors/BannerController.cs new file mode 100644 index 00000000000..e4631a7749e --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/BannerController.cs @@ -0,0 +1,394 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Tabs; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + public class BannerController + { + #region "Private Members" + + private string BannerClickThroughPage = "/DesktopModules/Admin/Banners/BannerClickThrough.aspx"; + + #endregion + + #region "Private Methods" + + private string FormatImage(string File, int Width, int Height, string BannerName, string Description) + { + var Image = new StringBuilder(); + Image.Append("\"" 0) + { + Image.Append(" width=\"" + Width + "\""); + } + if (Height > 0) + { + Image.Append(" height=\"" + Height + "\""); + } + Image.Append("/>"); + return Image.ToString(); + } + + private string FormatFlash(string File, int Width, int Height) + { + string Flash = ""; + + Flash += ""; + Flash += ""; + Flash += ""; + Flash += ""; + Flash += ""; + Flash += ""; + + return Flash; + } + + #endregion + + #region "Public Methods" + + public bool IsBannerActive(BannerInfo objBanner) + { + bool blnValid = true; + + if (Null.IsNull(objBanner.StartDate) == false && DateTime.Now < objBanner.StartDate) + { + blnValid = false; + } + if (blnValid) + { + switch (objBanner.Criteria) + { + case 0: //AND = cancel the banner when the Impressions expire + if (objBanner.Impressions < objBanner.Views && objBanner.Impressions != 0) + { + blnValid = false; + } + break; + case 1: //OR = cancel the banner if either the EndDate OR Impressions expire + if ((objBanner.Impressions < objBanner.Views && objBanner.Impressions != 0) || (DateTime.Now > objBanner.EndDate && Null.IsNull(objBanner.EndDate) == false)) + { + blnValid = false; + } + break; + } + } + return blnValid; + } + + private object LoadBannersCallback(CacheItemArgs cacheItemArgs) + { + var PortalId = (int) cacheItemArgs.ParamList[0]; + var BannerTypeId = (int) cacheItemArgs.ParamList[1]; + var GroupName = (string) cacheItemArgs.ParamList[2]; + + //get list of all banners + List FullBannerList = CBO.FillCollection(DataProvider.Instance().FindBanners(PortalId, BannerTypeId, GroupName)); + + //create list of active banners + var ActiveBannerList = new List(); + foreach (BannerInfo objBanner in FullBannerList) + { + if (IsBannerActive(objBanner)) + { + ActiveBannerList.Add(objBanner); + } + } + return ActiveBannerList; + } + + public void AddBanner(BannerInfo objBannerInfo) + { + DataProvider.Instance().AddBanner(objBannerInfo.BannerName, + objBannerInfo.VendorId, + objBannerInfo.ImageFile, + objBannerInfo.URL, + objBannerInfo.Impressions, + objBannerInfo.CPM, + objBannerInfo.StartDate, + objBannerInfo.EndDate, + objBannerInfo.CreatedByUser, + objBannerInfo.BannerTypeId, + objBannerInfo.Description, + objBannerInfo.GroupName, + objBannerInfo.Criteria, + objBannerInfo.Width, + objBannerInfo.Height); + ClearBannerCache(); + } + + public void ClearBannerCache() + { + //Clear all cached Banners collections + DataCache.ClearCache("Banners:"); + } + + public void DeleteBanner(int BannerId) + { + DataProvider.Instance().DeleteBanner(BannerId); + ClearBannerCache(); + } + + public string FormatBanner(int VendorId, int BannerId, int BannerTypeId, string BannerName, string ImageFile, string Description, string URL, int Width, int Height, string BannerSource, + string HomeDirectory, string BannerClickthroughUrl) + { + string strBanner = ""; + string strWindow = "_new"; + if (Globals.GetURLType(URL) == TabType.Tab) + { + strWindow = "_self"; + } + string strURL = ""; + if (BannerId != -1) + { + if (string.IsNullOrEmpty(BannerClickthroughUrl)) + { + strURL = Globals.ApplicationPath + BannerClickThroughPage + "?BannerId=" + BannerId + "&VendorId=" + VendorId + "&PortalId=" + Globals.GetPortalSettings().PortalId; + } + else + { + strURL = BannerClickthroughUrl + "?BannerId=" + BannerId + "&VendorId=" + VendorId + "&PortalId=" + Globals.GetPortalSettings().PortalId; + } + } + else + { + strURL = URL; + } + strURL = HttpUtility.HtmlEncode(strURL); + + switch (BannerTypeId) + { + case (int) BannerType.Text: + strBanner += "" + BannerName + "
    "; + strBanner += "" + Description + "
    "; + if (!String.IsNullOrEmpty(ImageFile)) + { + URL = ImageFile; + } + if (URL.IndexOf("://") != -1) + { + URL = URL.Substring(URL.IndexOf("://") + 3); + } + strBanner += "" + URL + ""; + break; + case (int) BannerType.Script: + strBanner += Description; + break; + default: + if (ImageFile.IndexOf("://") == -1 && ImageFile.StartsWith("/") == false) + { + if (ImageFile.ToLowerInvariant().IndexOf(".swf") == -1) + { + strBanner += ""; + switch (BannerSource) + { + case "L": //local + strBanner += FormatImage(HomeDirectory + ImageFile, Width, Height, BannerName, Description); + break; + case "G": //global + strBanner += FormatImage(Globals.HostPath + ImageFile, Width, Height, BannerName, Description); + break; + } + strBanner += ""; + } + else //flash + { + switch (BannerSource) + { + case "L": //local + strBanner += FormatFlash(HomeDirectory + ImageFile, Width, Height); + break; + case "G": //global + strBanner += FormatFlash(Globals.HostPath + ImageFile, Width, Height); + break; + } + } + } + else + { + if (ImageFile.ToLowerInvariant().IndexOf(".swf") == -1) + { + strBanner += ""; + strBanner += FormatImage(ImageFile, Width, Height, BannerName, Description); + strBanner += ""; + } + else //flash + { + strBanner += FormatFlash(ImageFile, Width, Height); + } + } + break; + } + return strBanner; + } + + public string FormatBanner(int VendorId, int BannerId, int BannerTypeId, string BannerName, string ImageFile, string Description, string URL, int Width, int Height, string BannerSource, + string HomeDirectory) + { + return FormatBanner(VendorId, BannerId, BannerTypeId, BannerName, ImageFile, Description, URL, Width, Height, BannerSource, HomeDirectory, string.Empty); + } + + public BannerInfo GetBanner(int BannerId) + { + return (BannerInfo) CBO.FillObject(DataProvider.Instance().GetBanner(BannerId), typeof (BannerInfo)); + } + + public DataTable GetBannerGroups(int PortalId) + { + return DataProvider.Instance().GetBannerGroups(PortalId); + } + + public ArrayList GetBanners(int VendorId) + { + return CBO.FillCollection(DataProvider.Instance().GetBanners(VendorId), typeof (BannerInfo)); + } + + public ArrayList LoadBanners(int PortalId, int ModuleId, int BannerTypeId, string GroupName, int Banners) + { + if (GroupName == null) + { + GroupName = Null.NullString; + } + + //set cache key + string cacheKey = string.Format(DataCache.BannersCacheKey, PortalId, BannerTypeId, GroupName); + + //get list of active banners + var bannersList = CBO.GetCachedObject>(new CacheItemArgs(cacheKey, DataCache.BannersCacheTimeOut, DataCache.BannersCachePriority, PortalId, BannerTypeId, GroupName), + LoadBannersCallback); + + //create return collection + var arReturnBanners = new ArrayList(Banners); + + if (bannersList.Count > 0) + { + if (Banners > bannersList.Count) + { + Banners = bannersList.Count; + } + + //set Random start index based on the list of banners + int intIndex = new Random().Next(0, bannersList.Count); + //set counter + int intCounter = 1; + + while (intCounter <= bannersList.Count && arReturnBanners.Count != Banners) + { + //manage the rotation for the circular collection + intIndex += 1; + if (intIndex > (bannersList.Count - 1)) + { + intIndex = 0; + } + + //get the banner object + BannerInfo objBanner = bannersList[intIndex]; + + //add to return collection + arReturnBanners.Add(objBanner); + + //update banner attributes + objBanner.Views += 1; + if (Null.IsNull(objBanner.StartDate)) + { + objBanner.StartDate = DateTime.Now; + } + if (Null.IsNull(objBanner.EndDate) && objBanner.Views >= objBanner.Impressions && objBanner.Impressions != 0) + { + objBanner.EndDate = DateTime.Now; + } + DataProvider.Instance().UpdateBannerViews(objBanner.BannerId, objBanner.StartDate, objBanner.EndDate); + + //expire cached collection of banners if a banner is no longer active + if (!IsBannerActive(objBanner)) + { + DataCache.RemoveCache(cacheKey); + } + intCounter += 1; + } + } + return arReturnBanners; + } + + public void UpdateBanner(BannerInfo objBannerInfo) + { + DataProvider.Instance().UpdateBanner(objBannerInfo.BannerId, + objBannerInfo.BannerName, + objBannerInfo.ImageFile, + objBannerInfo.URL, + objBannerInfo.Impressions, + objBannerInfo.CPM, + objBannerInfo.StartDate, + objBannerInfo.EndDate, + objBannerInfo.CreatedByUser, + objBannerInfo.BannerTypeId, + objBannerInfo.Description, + objBannerInfo.GroupName, + objBannerInfo.Criteria, + objBannerInfo.Width, + objBannerInfo.Height); + ClearBannerCache(); + } + + public void UpdateBannerClickThrough(int BannerId, int VendorId) + { + DataProvider.Instance().UpdateBannerClickThrough(BannerId, VendorId); + } + + #endregion + + #region "Obsolete methods" + + [Obsolete("Deprecated in DNN 5.6.2. Use BannerController.GetBanner(Int32)")] + public BannerInfo GetBanner(int BannerId, int VendorId, int PortalId) + { + return GetBanner(BannerId); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/BannerInfo.cs b/DNN Platform/Library/Services/Vendors/BannerInfo.cs new file mode 100644 index 00000000000..38256cecc29 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/BannerInfo.cs @@ -0,0 +1,69 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Services.FileSystem; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + [Serializable] + public class BannerInfo + { + public int BannerId { get; set; } + public int VendorId { get; set; } + public string ImageFile { get; set; } + public string BannerName { get; set; } + public string URL { get; set; } + public int Impressions { get; set; } + // ReSharper disable InconsistentNaming + // Existing public API + public double CPM { get; set; } + // ReSharper restore InconsistentNaming + public int Views { get; set; } + public int ClickThroughs { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public string CreatedByUser { get; set; } + public DateTime CreatedDate { get; set; } + public int BannerTypeId { get; set; } + public string Description { get; set; } + public string GroupName { get; set; } + public int Criteria { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public string ImageFileRaw { get; set; } + public string ImageFileUrl { get + { + if(ImageFileRaw.StartsWith("FileID=")) + { + int fileId = int.Parse(ImageFileRaw.Substring("FileID=".Length)); + var file = FileManager.Instance.GetFile(fileId); + return file != null ? FileManager.Instance.GetUrl(file) : ""; + } + + return ImageFileRaw; + } } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/BannerTypeController.cs b/DNN Platform/Library/Services/Vendors/BannerTypeController.cs new file mode 100644 index 00000000000..e80c6b70704 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/BannerTypeController.cs @@ -0,0 +1,44 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Collections; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + public class BannerTypeController + { + public ArrayList GetBannerTypes() + { + var arrBannerTypes = new ArrayList(); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Banner, Localization.Localization.GetString("BannerType.Banner.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.MicroButton, Localization.Localization.GetString("BannerType.MicroButton.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Button, Localization.Localization.GetString("BannerType.Button.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Block, Localization.Localization.GetString("BannerType.Block.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Skyscraper, Localization.Localization.GetString("BannerType.Skyscraper.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Text, Localization.Localization.GetString("BannerType.Text.String", Localization.Localization.GlobalResourceFile))); + arrBannerTypes.Add(new BannerTypeInfo((int) BannerType.Script, Localization.Localization.GetString("BannerType.Script.String", Localization.Localization.GlobalResourceFile))); + return arrBannerTypes; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/BannerTypeInfo.cs b/DNN Platform/Library/Services/Vendors/BannerTypeInfo.cs new file mode 100644 index 00000000000..ce1904eb27f --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/BannerTypeInfo.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + public enum BannerType + { + Banner = 1, + MicroButton = 2, + Button = 3, + Block = 4, + Skyscraper = 5, + Text = 6, + Script = 7 + } + + [Serializable] + public class BannerTypeInfo + { + private int _BannerTypeId; + private string _BannerTypeName; + + public BannerTypeInfo() + { + } + + public BannerTypeInfo(int BannerTypeId, string BannerTypeName) + { + _BannerTypeId = BannerTypeId; + _BannerTypeName = BannerTypeName; + } + + public int BannerTypeId + { + get + { + return _BannerTypeId; + } + set + { + _BannerTypeId = value; + } + } + + public string BannerTypeName + { + get + { + return _BannerTypeName; + } + set + { + _BannerTypeName = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/ClassificationController.cs b/DNN Platform/Library/Services/Vendors/ClassificationController.cs new file mode 100644 index 00000000000..beca0857650 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/ClassificationController.cs @@ -0,0 +1,51 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + [Obsolete("Obsoleted in 6.0.0, the Vendor Classifications feature was never fully implemented and will be removed from the API")] + public class ClassificationController + { + public ArrayList GetVendorClassifications(int VendorId) + { + return CBO.FillCollection(DataProvider.Instance().GetVendorClassifications(VendorId), typeof (ClassificationInfo)); + } + + public void DeleteVendorClassifications(int VendorId) + { + DataProvider.Instance().DeleteVendorClassifications(VendorId); + } + + public void AddVendorClassification(int VendorId, int ClassificationId) + { + DataProvider.Instance().AddVendorClassification(VendorId, ClassificationId); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/ClassificationInfo.cs b/DNN Platform/Library/Services/Vendors/ClassificationInfo.cs new file mode 100644 index 00000000000..3ae5a761332 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/ClassificationInfo.cs @@ -0,0 +1,85 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + [Serializable] + public class ClassificationInfo + { + private int _ClassificationId; + private string _ClassificationName; + private bool _IsAssociated; + private int _ParentId; + + public int ClassificationId + { + get + { + return _ClassificationId; + } + set + { + _ClassificationId = value; + } + } + + public string ClassificationName + { + get + { + return _ClassificationName; + } + set + { + _ClassificationName = value; + } + } + + public int ParentId + { + get + { + return _ParentId; + } + set + { + _ParentId = value; + } + } + + public bool IsAssociated + { + get + { + return _IsAssociated; + } + set + { + _IsAssociated = value; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/VendorController.cs b/DNN Platform/Library/Services/Vendors/VendorController.cs new file mode 100644 index 00000000000..cc9b0f5afe5 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/VendorController.cs @@ -0,0 +1,175 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Data; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + public class VendorController + { + public int AddVendor(VendorInfo objVendor) + { + return DataProvider.Instance().AddVendor(objVendor.PortalId, + objVendor.VendorName, + objVendor.Unit, + objVendor.Street, + objVendor.City, + objVendor.Region, + objVendor.Country, + objVendor.PostalCode, + objVendor.Telephone, + objVendor.Fax, + objVendor.Cell, + objVendor.Email, + objVendor.Website, + objVendor.FirstName, + objVendor.LastName, + objVendor.UserName, + objVendor.LogoFile, + objVendor.KeyWords, + objVendor.Authorized.ToString()); + } + + public void DeleteVendor(int VendorID) + { + DataProvider.Instance().DeleteVendor(VendorID); + var objBanners = new BannerController(); + objBanners.ClearBannerCache(); + } + + public void DeleteVendors() + { + DeleteVendors(Null.NullInteger); + } + + public void DeleteVendors(int PortalID) + { + int TotalRecords = 0; + foreach (VendorInfo vendor in GetVendors(PortalID, true, Null.NullInteger, Null.NullInteger, ref TotalRecords)) + { + if (vendor.Authorized == false) + { + DeleteVendor(vendor.VendorId); + } + } + var objBanners = new BannerController(); + objBanners.ClearBannerCache(); + } + + public void UpdateVendor(VendorInfo objVendor) + { + DataProvider.Instance().UpdateVendor(objVendor.VendorId, + objVendor.VendorName, + objVendor.Unit, + objVendor.Street, + objVendor.City, + objVendor.Region, + objVendor.Country, + objVendor.PostalCode, + objVendor.Telephone, + objVendor.Fax, + objVendor.Cell, + objVendor.Email, + objVendor.Website, + objVendor.FirstName, + objVendor.LastName, + objVendor.UserName, + objVendor.LogoFile, + objVendor.KeyWords, + objVendor.Authorized.ToString()); + } + + public VendorInfo GetVendor(int VendorID, int PortalId) + { + return (VendorInfo) CBO.FillObject(DataProvider.Instance().GetVendor(VendorID, PortalId), typeof (VendorInfo)); + } + + public ArrayList GetVendors(int PortalId, string Filter) + { + int TotalRecords = 0; + return GetVendorsByName(Filter, PortalId, 0, 100000, ref TotalRecords); + } + + public ArrayList GetVendors(int PortalId, bool UnAuthorized, int PageIndex, int PageSize, ref int TotalRecords) + { + IDataReader dr = DataProvider.Instance().GetVendors(PortalId, UnAuthorized, PageIndex, PageSize); + ArrayList retValue = null; + try + { + while (dr.Read()) + { + TotalRecords = Convert.ToInt32(dr["TotalRecords"]); + } + dr.NextResult(); + retValue = CBO.FillCollection(dr, typeof (VendorInfo)); + } + finally + { + CBO.CloseDataReader(dr, true); + } + return retValue; + } + + public ArrayList GetVendorsByEmail(string Filter, int PortalId, int Page, int PageSize, ref int TotalRecords) + { + IDataReader dr = DataProvider.Instance().GetVendorsByEmail(Filter, PortalId, Page, PageSize); + try + { + while (dr.Read()) + { + TotalRecords = Convert.ToInt32(dr["TotalRecords"]); + } + dr.NextResult(); + return CBO.FillCollection(dr, typeof (VendorInfo)); + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + + public ArrayList GetVendorsByName(string Filter, int PortalId, int Page, int PageSize, ref int TotalRecords) + { + IDataReader dr = DataProvider.Instance().GetVendorsByName(Filter, PortalId, Page, PageSize); + try + { + while (dr.Read()) + { + TotalRecords = Convert.ToInt32(dr["TotalRecords"]); + } + dr.NextResult(); + return CBO.FillCollection(dr, typeof (VendorInfo)); + } + finally + { + CBO.CloseDataReader(dr, true); + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Services/Vendors/VendorInfo.cs b/DNN Platform/Library/Services/Vendors/VendorInfo.cs new file mode 100644 index 00000000000..4656b5eb0e0 --- /dev/null +++ b/DNN Platform/Library/Services/Vendors/VendorInfo.cs @@ -0,0 +1,82 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.Services.Vendors +{ + [Serializable] + public class VendorInfo + { + public int VendorId { get; set; } + + public string VendorName { get; set; } + + public string Street { get; set; } + + public string City { get; set; } + + public string Region { get; set; } + + public string Country { get; set; } + + public string PostalCode { get; set; } + + public string Telephone { get; set; } + + public int PortalId { get; set; } + + public string Fax { get; set; } + + public string Cell { get; set; } + + public string Email { get; set; } + + public string Website { get; set; } + + public int ClickThroughs { get; set; } + + public int Views { get; set; } + + public string CreatedByUser { get; set; } + + public DateTime CreatedDate { get; set; } + + public string LogoFile { get; set; } + + public string KeyWords { get; set; } + + public string Unit { get; set; } + + public bool Authorized { get; set; } + + public string FirstName { get; set; } + + public string LastName { get; set; } + + public int Banners { get; set; } + + public string UserName { get; set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Blank Website.template b/DNN Platform/Library/Templates/Blank Website.template new file mode 100644 index 00000000000..ea01004c818 --- /dev/null +++ b/DNN Platform/Library/Templates/Blank Website.template @@ -0,0 +1,5185 @@ + + + [PortalDescription.Text] + + Logo.png + [Setting.FooterText.Text] + 1 + 0 + [Setting.DefaultLanguage.Text] + [G]Skins/Gravity/2-Col.ascx + [G]Skins/Gravity/2-Col.ascx + [G]Containers/Gravity/Title_h2.ascx + [G]Containers/Gravity/Title_h2.ascx + True + Pacific Standard Time + + + + Basic + Prefix + Text + 50 + 0 + + + Basic + FirstName + Text + 50 + 0 + + + Basic + MiddleName + Text + 50 + 0 + + + Basic + LastName + Text + 50 + 0 + + + Basic + Biography + RichText + 0 + 2 + + + Basic + Photo + Image + 0 + 0 + + + Contact + Telephone + Text + 50 + 2 + + + Contact + Cell + Text + 50 + 2 + + + Contact + Fax + Text + 50 + 2 + + + Contact + Website + Text + 50 + 2 + + + Contact + IM + Text + 50 + 2 + + + Contact + Twitter + Text + 50 + 2 + + + Contact + Skype + Text + 50 + 2 + + + Contact + LinkedIn + Text + 50 + 2 + + + Contact + Facebook + Text + 50 + 2 + + + Location + Unit + Text + 50 + 2 + + + Location + Street + Text + 50 + 2 + + + Location + City + Text + 50 + 2 + + + Location + Region + Region + 0 + 2 + + + Location + Country + Country + 0 + 2 + + + Location + PostalCode + Text + 50 + 2 + + + Location + PreferredTimeZone + TimeZoneInfo + 0 + 2 + + + Location + TimeZone + TimeZone + 0 + 2 + + + Location + PreferredLocale + Locale + 0 + 2 + + + + + + Pages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Vendors + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Banners + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Lists + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + File Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Log + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Newletters + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Recycle Bin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Log Viewer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Input + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Results + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Wizard + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Login + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Registration + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Feed Explorer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Extensions + + + + Solutions + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + WhatsNew + + + + Dashboard + + + + Languages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Skins + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Console + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Marketplace + + + + View Profile + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Sitemap + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + ContentList + + + + Configuration Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Professional Preview + + + + DDR Menu + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + HTML + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Taxonomy Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + RadEditor Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + Google Analytics + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Admin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + GlobalRoles + [RoleGroup.Description.Text] + + + Administrators + Administrators of this Website + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + adminrole + true + + + Registered Users + Registered Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + true + + + registeredrole + true + + + Subscribers + A public role for site subscriptions + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + true + true + + + subscriberrole + true + + + Translator (en-US) + A role for English (United States) translators + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + none + false + + + Unverified Users + Unverified Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + unverifiedrole + true + + + + + + + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + [G]Skins/Gravity/2-Col.ascx + 0001-01-01T00:00:00 + Getting Started + [Tab.GettingStarted.Title.Text] + + gettingStartedTab + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + IncludeVaryBy + + + + + CacheDuration + + + + + CacheIncludeExclude + + + + + ExcludeVaryBy + + + + + MaxVaryByCount + + + + + CacheProvider + + + + + CustomStylesheet + GettingStarted.css + + + + + ContentPane + + + 514 + [Tab.GettingStarted.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/Title_h2.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + [Tab.Home.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Home.Keywords.Text] + [Tab.Home.PageHeadText.Text] + false + -1 + 0.5 + 0001-01-01T00:00:00 + Home + [Tab.Home.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + IncludeVaryBy + + + + + CacheDuration + + + + + CacheIncludeExclude + + + + + ExcludeVaryBy + + + + + MaxVaryByCount + + + + + CacheProvider + + + + + + + + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Activity Feed + Activity Feed + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + usertab + + + LeftPaneProfile + + + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + ViewProfile + ViewProfile + + + + + HeaderPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + + ViewProfile + ViewProfile + + + + + RightPaneProfile + + + Member Directory + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + FilterBy + User + + + FilterPropertyValue + + + + + + + DisplaySearch + False + + + SearchField4 + Country + + + SearchField3 + City + + + EnablePopUp + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + SearchField2 + Email + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField1 + DisplayName + + + hideadminborder + False + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + Menu + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + ShowTooltip + False + + + DefaultSize + IconNone + + + TabVisibility-ActivityFeed-Messages + User + + + DefaultView + Hide + + + TabVisibility-ActivityFeed-Friends + Friends + + + IncludeParent + False + + + AllowViewChange + False + + + + + hideadminborder + False + + + Console + Console + + + + + ContentPaneProfile + + + Journal + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + Journal_AllowPhotos + True + + + Journal_PageSize + 20 + + + Journal_AllowFiles + True + + + Journal_MaxCharacters + 250 + + + Journal_Filters + + + + + + + hideadminborder + False + + + Journal + Journal + + + + + + + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + My Profile + My Profile + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + LeftPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + ViewProfile + ViewProfile + + + + + HeaderPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME] - <em>Network Aministrator</em></h2> + </div> + + + + ViewProfile + ViewProfile + + + + + RightPaneProfile + + + Member Directory + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + FilterBy + User + + + FilterPropertyValue + + + + + + + DisplaySearch + False + + + SearchField4 + Country + + + SearchField3 + City + + + EnablePopUp + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + SearchField2 + Email + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField1 + DisplayName + + + hideadminborder + False + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + Menu + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + ShowTooltip + False + + + DefaultSize + IconNone + + + TabVisibility-ActivityFeed-Messages + User + + + DefaultView + Hide + + + TabVisibility-ActivityFeed-Friends + Friends + + + IncludeParent + False + + + AllowViewChange + False + + + + + hideadminborder + False + + + Console + Console + + + + + ContentPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div class="pBio"> + <h3 data-bind="text: AboutMeText"></h3> + <span data-bind="text: EmptyAboutMeText, visible: Biography().length==0"></span> + <p data-bind="html: Biography"></p> + </div> + <div class="pAddress"> + <h3 data-bind="text: LocationText"></h3> + <span data-bind="text: EmptyLocationText, visible: Street().length=0 && Location().length==0 && Country().length==0 && PostalCode().length==0"></span> + <p><span data-bind="text: Street()"></span><span data-bind="visible: Street().length > 0"><br/></span> + <span data-bind="text: Location()"></span><span data-bind="visible: Location().length > 0"><br/></span> + <span data-bind="text: Country()"></span><span data-bind="visible: Country().length > 0"><br/></span> + <span data-bind="text: PostalCode()"></span> + </p> + </div> + <div class="pContact"> + <h3 data-bind="text: GetInTouchText"></h3> + <span data-bind="text: EmptyGetInTouchText, visible: Telephone().length==0 && Email().length==0 && Website().length==0 && IM().length==0"></span> + <ul> + <li data-bind="visible: Telephone().length > 0"><strong><span data-bind="text: TelephoneText">:</span></strong> <span data-bind="text: Telephone()"></span></li> + <li data-bind="visible: Email().length > 0"><strong><span data-bind="text: EmailText">:</span></strong> <span data-bind="text: Email()"></span></li> + <li data-bind="visible: Website().length > 0"><strong><span data-bind="text: WebsiteText">:</span></strong> <span data-bind="text: Website()"></span></li> + <li data-bind="visible: IM().length > 0"><strong><span data-bind="text: IMText">:</span></strong> <span data-bind="text: IM()"></span></li> + </ul> + </div> + <div class="dnnClear"></div> + + + + ViewProfile + ViewProfile + + + + + + + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Friends + My Friends + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + LeftPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + ViewProfile + ViewProfile + + + + + HeaderPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + ViewProfile + ViewProfile + + + + + RightPaneProfile + + + Member Directory + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + FilterBy + User + + + FilterPropertyValue + + + + + + + DisplaySearch + False + + + SearchField4 + Country + + + SearchField3 + City + + + EnablePopUp + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + SearchField2 + Email + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField1 + DisplayName + + + hideadminborder + False + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + Menu + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + ShowTooltip + False + + + DefaultSize + IconNone + + + TabVisibility-ActivityFeed-Messages + User + + + DefaultView + Hide + + + TabVisibility-ActivityFeed-Friends + Friends + + + IncludeParent + False + + + AllowViewChange + False + + + + + hideadminborder + False + + + Console + Console + + + + + ContentPaneProfile + + + Member Directory + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + FilterPropertyValue + + + + + FilterValue + 1 + + + FilterBy + Relationship + + + + + SearchField1 + DisplayName + + + DisplaySearch + False + + + hideadminborder + False + + + SearchField2 + Email + + + SearchField3 + City + + + SearchField4 + Country + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + + + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Messages + My Messages + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + LeftPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + ViewProfile + ViewProfile + + + + + HeaderPaneProfile + + + ViewProfile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + IncludeButton + False + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + ViewProfile + ViewProfile + + + + + RightPaneProfile + + + Member Directory + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + FilterBy + User + + + FilterPropertyValue + + + + + + + DisplaySearch + False + + + SearchField4 + Country + + + SearchField3 + City + + + EnablePopUp + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + SearchField2 + Email + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField1 + DisplayName + + + hideadminborder + False + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + Menu + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + ShowTooltip + False + + + DefaultSize + IconNone + + + TabVisibility-ActivityFeed-Messages + User + + + DefaultView + Hide + + + TabVisibility-ActivityFeed-Friends + Friends + + + IncludeParent + False + + + AllowViewChange + False + + + + + hideadminborder + False + + + Console + Console + + + + + ContentPaneProfile + + + Message Center + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + False + + + DotNetNuke.Modules.CoreMessaging + Message Center + + + + + + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Admin + Website Administration + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + 481 + Basic Features + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + AllowViewChange + False + + + ShowTooltip + True + + + OrderTabsByHierarchy + True + + + AllowSizeChange + False + + + DefaultSize + IconFileLarge + + + DefaultView + Hide + + + ConsoleWidth + + + + + + + hideadminborder + True + + + Console + Console +
    +
    +
    +
    +
    + + + [Tab.AdvancedSettings.Description.Text] + false + 0001-01-01T00:00:00 + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Advanced Settings + [Tab.AdvancedSettings.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + [Tab.AdvancedSettings.ContentPane.Module.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + AdvancedSettings + Advanced Settings +
    +
    +
    +
    +
    + + + Manage configuration settings for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteSettings_16X16_Standard.png + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Settings + Site Settings + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 461 + Site Settings + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Portals + Site Settings +
    +
    +
    +
    +
    + + + Manage pages within the site. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tabs_16X16_Standard.png + ~/Icons/Sigma/Tabs_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Pages + Page Management + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 462 + Page Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Tabs_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Tabs + Tabs +
    +
    +
    +
    +
    + + + Install, add, modify and delete extensions, such as modules, skins and language packs. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Extensions_16X16_Standard.png + ~/Icons/Sigma/Extensions_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Extensions + Extensions + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 463 + Extensions + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Extensions_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Extensions + Extensions +
    +
    +
    +
    +
    + + + Manage Language Resources. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Languages_16X16_Standard.png + ~/Icons/Sigma/Languages_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Languages + Languages + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 464 + Language Management + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Languages_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Languages + Languages + + + + + + + + Manage Skin Resources. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Skins_16X16_Standard.png + ~/Icons/Sigma/Skins_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Skins + Skins + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 465 + Skin Editor + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Skins_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Skins + Skins +
    + + 466 + Skin Designer + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Skins_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SkinDesigner + Skin Designer +
    +
    +
    +
    +
    + + + Manage security roles for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SecurityRoles_16X16_Standard.png + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Security Roles + Security Roles + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 467 + Security Roles + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + Security Roles +
    +
    +
    +
    +
    + + + Manage user accounts for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Users_16X16_Standard.png + ~/Icons/Sigma/Users_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + User Accounts + User Accounts + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 468 + User Accounts + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Users_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + User Accounts +
    +
    +
    +
    +
    + + + Manage vendor accounts, banner advertising and affiliate referrals within the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Vendors_16X16_Standard.png + ~/Icons/Sigma/Vendors_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Vendors + Vendors + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 469 + Vendors + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Vendors_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Vendors + Vendors +
    +
    +
    +
    +
    + + + View statistical reports on site activity for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteLog_16X16_Standard.png + ~/Icons/Sigma/SiteLog_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Log + Site Log + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 470 + Site Log + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SiteLog_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteLog + Site Log +
    +
    +
    +
    +
    + + + Send email messages to users, security roles and specific email addresses. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/BulkMail_16X16_Standard.png + ~/Icons/Sigma/BulkMail_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Newsletters + Newsletters + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 471 + Newsletters + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/BulkMail_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Newsletters + Newsletters +
    +
    +
    +
    +
    + + + [Tab.DigitalAssetsManagement.Content.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Files_16X16_Standard.png + ~/Icons/Sigma/Files_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + File Management + [Tab.DigitalAssetsManagement.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 472 + File Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Files_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + DotNetNuke.Modules.DigitalAssets + Digital Asset Management +
    +
    +
    +
    +
    + + + View, restore or permanently recycle pages and modules that have been deleted from the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Trash_16X16_Standard.png + ~/Icons/Sigma/Trash_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Recycle Bin + Recycle Bin + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 473 + Recycle Bin + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Trash_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + RecycleBin + Recycle Bin +
    +
    +
    +
    +
    + + + View a historical log of database events such as event schedules, exceptions, account logins, module and page changes, user account activities, security role activities, etc. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/ViewStats_16X16_Standard.png + ~/Icons/Sigma/ViewStats_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Log Viewer + Log Viewer + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 474 + Log Viewer + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/ViewStats_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + LogViewer + Log Viewer +
    +
    +
    +
    +
    + + + Configure portal settings, page design and apply a site template using a step-by-step wizard. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Wizard_16X16_Standard.png + ~/Icons/Sigma/Wizard_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Wizard + Site Wizard + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 475 + Site Wizard + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Wizard_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteWizard + Site Wizard +
    +
    +
    +
    +
    + + + Manage the Taxonomy for your Site. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tag_16X16_Standard.png + ~/Icons/Sigma/Tag_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Taxonomy + Taxonomy + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 418 + Taxonomy Manager + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Tag_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + DotNetNuke.Taxonomy + Taxonomy Manager + + + + + + + + Configure the sitemap for submission to common search engines. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Sitemap_16X16_Standard.png + ~/Icons/Sigma/Sitemap_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Engine SiteMap + Search Engine SiteMap + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 419 + Search Engine SiteMap + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Sitemap_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Sitemap + Sitemap + + + + + + + + Manage common lists + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Lists_16X16_Standard.png + ~/Icons/Sigma/Lists_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Lists + Lists + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 342 + Lists + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Lists_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Lists + Lists +
    +
    +
    +
    +
    + + + Site Redirection Management. + false + 0001-01-01T00:00:00 + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_16x16.png + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Redirection Management + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 479 + Site Redirection Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + DotNetNuke.MobileManagement + DNN Site Redirection Management +
    +
    +
    +
    +
    + + + Device Preview Management. + false + 0001-01-01T00:00:00 + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_16X16.png + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Device Preview Management + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 480 + Device Preview Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + DotNetNuke.Modules.PreviewProfileManagement + DNN Device Preview Management +
    +
    +
    +
    +
    + + + + + Configure Site Google Analytics settings. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/GoogleAnalytics_16X16_Standard.png + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Google Analytics + Google Analytics + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 417 + Google Analytics + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + GoogleAnalytics + GoogleAnalytics +
    +
    +
    +
    +
    + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Results + Search Results + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + 368 + Search Results + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + SearchResults + Search Results +
    + + 369 + Results + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ContentList + Content List +
    +
    +
    +
    +
    + + + + Search Admin + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Search_16x16_Standard.png + ~/Icons/Sigma/Search_32x32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Admin + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + [Tab.SearchAdmin.ContentPane.Module.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Search_16x16_Standard.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + SearchAdmin + Search Admin +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Blank Website.template.en-US.resx b/DNN Platform/Library/Templates/Blank Website.template.en-US.resx new file mode 100644 index 00000000000..14b2601e930 --- /dev/null +++ b/DNN Platform/Library/Templates/Blank Website.template.en-US.resx @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Blank Website + + + en-US + + + Copyright [year] by DNN Corp + + + Blank Template + + + + + + + + + Home + + + + + + + + + A dummy role group that represents the Global roles + + + Watch the Getting Started Video + + + Let me at it + + + The video below will <strong> help get you started </strong> building your new DotNetNuke site. Using DotNetNuke is fast and easy and you can have your new site up and running with real content in just a matter of minutes. + + + Watch the Video + + + What's new with 7.0 + + + Getting Started + + + Already an expert? + + + Setup your email, install languages, and other advanced configuration settings + + + Set Advanced Configuration Settings + + + Looking for answers? + + + Do you have any questions, ideas for improvement or just want to meet some other DotNetNuke members? + + + Find an Answer + + + Submit you Ideas + + + We always appreciate your feedback + + + We would love to hear how we're doing + + + Welcome to Your Installation + + + Learn the basics of working with DNN + + + <strong>Way to go!</strong> you just completed your installation of DotNetNuke; <strong>what whould you like to do next?</strong> + + + Find out what improvements and additions we've made to DotNetNuke 7.0. + + + Watch the Video + + + Add New Functionality + + + Enhance your site with capabilities such as e-commerce. + + + Visit the DotNetNuke Store + + + Sponsors + + + Personalize your DotNetNuke + + + Are you ready to make DotNetNuke your own? + + + We have the resources and tools to do just about anything you can imagine. + + + I want to... + + + Change the look of my site + + + Find new skin designs for your website on the DotNetNuke Store. + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Share your feedback + + + Search Admin + + + Search Admin + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Blank Website.template.resources b/DNN Platform/Library/Templates/Blank Website.template.resources new file mode 100644 index 00000000000..cdf491c4086 Binary files /dev/null and b/DNN Platform/Library/Templates/Blank Website.template.resources differ diff --git a/DNN Platform/Library/Templates/Default Website.template b/DNN Platform/Library/Templates/Default Website.template new file mode 100644 index 00000000000..42da3af8a0a --- /dev/null +++ b/DNN Platform/Library/Templates/Default Website.template @@ -0,0 +1,9747 @@ + + + [PortalDescription.Text] + + + + + Awesome-Cycles-Logo.png + [Setting.FooterText.Text] + 1 + 0 + [Setting.DefaultLanguage.Text] + [G]Skins/Gravity/2-Col.ascx + [G]Skins/Gravity/2-Col.ascx + [G]Containers/Gravity/Title_h2.ascx + [G]Containers/Gravity/Title_h2.ascx + True + Pacific Standard Time + + + + Basic + Prefix + Text + 50 + 0 + + + Basic + FirstName + Text + 50 + 0 + + + Basic + MiddleName + Text + 50 + 0 + + + Basic + LastName + Text + 50 + 0 + + + Basic + Biography + RichText + 0 + 2 + + + Basic + Photo + Image + 0 + 0 + + + Contact + Telephone + Text + 50 + 2 + + + Contact + Cell + Text + 50 + 2 + + + Contact + Fax + Text + 50 + 2 + + + Contact + Website + Text + 50 + 2 + + + Contact + IM + Text + 50 + 2 + + + Contact + Twitter + Text + 50 + 2 + + + Contact + Skype + Text + 50 + 2 + + + Contact + LinkedIn + Text + 50 + 2 + + + Contact + Facebook + Text + 50 + 2 + + + Location + Unit + Text + 50 + 2 + + + Location + Street + Text + 50 + 2 + + + Location + City + Text + 50 + 2 + + + Location + Region + Region + 0 + 2 + + + Location + Country + Country + 0 + 2 + + + Location + PostalCode + Text + 50 + 2 + + + Location + PreferredTimeZone + TimeZoneInfo + 0 + 2 + + + Location + TimeZone + TimeZone + 0 + 2 + + + Location + PreferredLocale + Locale + 0 + 2 + + + + + + Pages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Vendors + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Banners + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Lists + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + File Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Log + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Newletters + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Recycle Bin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Log Viewer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Results + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Wizard + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Login + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Registration + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Feed Explorer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Extensions + + + + Solutions + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + WhatsNew + + + + Dashboard + + + + Languages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Skins + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Console + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Marketplace + + + + View Profile + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Sitemap + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + ContentList + + + + Configuration Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Professional Preview + + + + DDR Menu + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + HTML + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Taxonomy Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + RadEditor Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + Google Analytics + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Admin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + GlobalRoles + [RoleGroup.Description.Text] + + + Administrators + Administrators of this Website + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + adminrole + true + + + Registered Users + Registered Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + true + + + registeredrole + true + + + Subscribers + A public role for site subscriptions + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + true + true + + + subscriberrole + true + + + Translator (en-US) + A role for English (United States) translators + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + none + false + + + Unverified Users + Unverified Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + unverifiedrole + true + + + + + + + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + [G]Skins/Gravity/2-Col.ascx + 0001-01-01T00:00:00 + Getting Started + [Tab.GettingStarted.Title.Text] + + gettingStartedTab + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + IncludeVaryBy + + + + + CacheDuration + + + + + CacheIncludeExclude + + + + + ExcludeVaryBy + + + + + MaxVaryByCount + + + + + CacheProvider + + + + + CustomStylesheet + GettingStarted.css + + + + + ContentPane + + + [Tab.GettingStarted.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Gravity/Banner.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + true + + + + + false + -1 + 0.5 + [G]Skins/Gravity/Home.ascx + 0001-01-01T00:00:00 + Home + + + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + IncludeVaryBy + + + + + CacheDuration + + + + + CacheIncludeExclude + + + + + ExcludeVaryBy + + + + + MaxVaryByCount + + + + + CacheProvider + + + + + hometab + + + sidebarPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Banner.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Sidebar + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerRightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Contact Us + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + leftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h2.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Awesome Cycles News + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Products + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + contentpaneLower + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Header Images + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + contentpane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Text/HTML + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Welcome to Awesome Cycles + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Customer Support + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Company + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Connect + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + + + [Tab.About.Content.Text] + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/2-Col.ascx + 0001-01-01T00:00:00 + About Us + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>All Users</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings> + <tabsetting> + <settingname>CacheDuration</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>ExcludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheProvider</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>IncludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>MaxVaryByCount</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheIncludeExclude</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + </tabsettings> + <panes> + <pane> + <name>footerRightPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod>FileModuleCachingProvider</cachemethod> + <cachetime>1200</cachetime> + <color /> + <containersrc>[G]Containers/Gravity/Title_h4.ascx</containersrc> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile /> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <title>[Tab.About.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + contentpane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h2.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.ContentPane.AboutUsModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.About.ContentPane.OurTeamModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + + + [Tab.Products.Content.Text] + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/2-Col.ascx + 0001-01-01T00:00:00 + Our Products + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>All Users</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings> + <tabsetting> + <settingname>CacheDuration</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>ExcludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheProvider</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>IncludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>MaxVaryByCount</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheIncludeExclude</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + </tabsettings> + <panes> + <pane> + <name>footerRightPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod>FileModuleCachingProvider</cachemethod> + <cachetime>1200</cachetime> + <color /> + <containersrc>[G]Containers/Gravity/Title_h4.ascx</containersrc> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile /> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <title>[Tab.Products.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Products.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + ContentPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h2.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Products.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Products.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Products.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Products.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + + + [Tab.ContactUs.Content.Text] + + [G]Containers/Gravity/Title_h2.ascx + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col.ascx + 0001-01-01T00:00:00 + Contact Us + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>All Users</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings> + <tabsetting> + <settingname>CacheDuration</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>ExcludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheProvider</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>IncludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>MaxVaryByCount</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheIncludeExclude</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + </tabsettings> + <panes> + <pane> + <name>footerRightPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod>FileModuleCachingProvider</cachemethod> + <cachetime>1200</cachetime> + <color /> + <containersrc>[G]Containers/Gravity/Title_h4.ascx</containersrc> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile /> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <title>[Tab.ContactUs.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + centerPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.CenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + rightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.RightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + leftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ContactUs.LeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + + + [Tab.StyleGuide.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/2-Col.ascx + 0001-01-01T00:00:00 + StyleGuide + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>All Users</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings> + <tabsetting> + <settingname>CacheDuration</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>ExcludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheProvider</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>IncludeVaryBy</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>MaxVaryByCount</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheIncludeExclude</settingname> + <settingvalue> + </settingvalue> + </tabsetting> + </tabsettings> + <parent>About Us</parent> + <panes> + <pane> + <name>LeftPaneLowerLeft</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod>FileModuleCachingProvider</cachemethod> + <cachetime>1200</cachetime> + <color /> + <containersrc>[G]Containers/Gravity/Title_h3.ascx</containersrc> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile /> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <title>[Tab.StyleGuide.LeftPaneLowerLeft.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + LeftPaneLowerRight + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.StyleGuide.LeftPaneLowerRight.ButtonsModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.StyleGuide.LeftPaneLowerRight.ListsModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + leftPaneBottom + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.StyleGuide.LeftPaneBottom.TableModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h3.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.StyleGuide.LeftPaneBottom.ImageAlignmentModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + RightPane + + + + + false + + + 1200 + + + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.StyleGuide.RightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + DNN_HTML + Text/HTML + + + + + + + + [Tab.ActivityFeed.Content.Text] + + [G]Containers/Gravity/Title_h3.ascx + + + false + 0001-01-01T00:00:00 + false + false + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Activity Feed + [Tab.ActivityFeed.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + + + + + usertab + + + footerRightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + LeftPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + <startdate>0001-01-01T00:00:00</startdate> + <visibility>Maximized</visibility> + <websliceexpirydate>0001-01-01T00:00:00</websliceexpirydate> + <webslicettl>0</webslicettl> + <modulesettings /> + <tabmodulesettings> + <tabmodulesetting> + <settingname>ProfileTemplate</settingname> + <settingvalue> + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + </settingvalue> + </tabmodulesetting> + <tabmodulesetting> + <settingname>hideadminborder</settingname> + <settingvalue>False</settingvalue> + </tabmodulesetting> + <tabmodulesetting> + <settingname>IncludeButton</settingname> + <settingvalue>False</settingvalue> + </tabmodulesetting> + </tabmodulesettings> + <definition>ViewProfile</definition> + <moduledefinition>ViewProfile</moduledefinition> + </module> + </modules> + </pane> + <pane> + <name>RightPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod>FileModuleCachingProvider</cachemethod> + <cachetime>0</cachetime> + <color /> + <containersrc>[G]Containers/Gravity/NoTitle.ascx</containersrc> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile /> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <title>[Tab.ActivityFeed.RightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + FilterBy + User + + + FilterPropertyValue + + + + + + + SearchField2 + Email + + + SearchField3 + City + + + EnablePopUp + False + + + SortField + DisplayName + + + DisplaySearch + False + + + SortOrder + ASC + + + hideadminborder + False + + + PageSize + 20 + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField4 + Country + + + PopUpTemplate + + + + + DisablePaging + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField1 + DisplayName + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + Navigation + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + Mode + Profile + + + ConsoleWidth + 250px + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + DefaultSize + IconNone + + + ShowTooltip + False + + + DefaultView + Hide + + + IncludeParent + False + + + TabVisibility-ActivityFeed-Friends + Friends + + + AllowViewChange + False + + + TabVisibility-ActivityFeed-Messages + User + + + + + hideadminborder + False + + + Console + Console + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + CenterPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.CenterPane.ProfileModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.ActivityFeed.CenterPane.JournalModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + Journal_PageSize + 20 + + + Journal_MaxCharacters + 250 + + + Journal_Filters + + + + + Journal_AllowPhotos + True + + + Journal_AllowFiles + True + + + + + hideadminborder + False + + + Journal + Journal + + + + + + + [Tab.MyProfile.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + My Profile + [Tab.MyProfile.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + footerRightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + LeftPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.LeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + RightPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.RightPane.MemberDirectoryModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + FilterBy + User + + + FilterPropertyValue + + + + + + + SearchField2 + Email + + + SearchField3 + City + + + EnablePopUp + False + + + DisplaySearch + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField4 + Country + + + hideadminborder + False + + + SearchField1 + DisplayName + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.RightPane.NavigationModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + DefaultSize + IconNone + + + ShowTooltip + False + + + DefaultView + Hide + + + IncludeParent + False + + + TabVisibility-ActivityFeed-Friends + Friends + + + AllowViewChange + False + + + TabVisibility-ActivityFeed-Messages + User + + + + + hideadminborder + False + + + Console + Console + + + + + CenterPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.CenterPane.ViewProfileModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.CenterPane.ViewProfileModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div class="pBio"> + <h3 data-bind="text: AboutMeText"></h3> + <span data-bind="text: EmptyAboutMeText, visible: Biography().length==0"></span> + <p data-bind="html: Biography"></p> + </div> + <div class="pAddress"> + <h3 data-bind="text: LocationText"></h3> + <span data-bind="text: EmptyLocationText, visible: Street().length==0 && Location().length==0 && Country().length==0 && PostalCode().length==0"></span> + <p><span data-bind="text: Street()"></span><span data-bind="visible: Street().length > 0"><br/></span> + <span data-bind="text: Location()"></span><span data-bind="visible: Location().length > 0"><br/></span> + <span data-bind="text: Country()"></span><span data-bind="visible: Country().length > 0"><br/></span> + <span data-bind="text: PostalCode()"></span> + </p> + </div> + <div class="pContact"> + <h3 data-bind="text: GetInTouchText"></h3> + <span data-bind="text: EmptyGetInTouchText, visible: Telephone().length==0 && Email().length==0 && Website().length==0 && IM().length==0"></span> + <ul> + <li data-bind="visible: Telephone().length > 0"><strong><span data-bind="text: TelephoneText">:</span></strong> <span data-bind="text: Telephone()"></span></li> + <li data-bind="visible: Email().length > 0"><strong><span data-bind="text: EmailText">:</span></strong> <span data-bind="text: Email()"></span></li> + <li data-bind="visible: Website().length > 0"><strong><span data-bind="text: WebsiteText">:</span></strong> <span data-bind="text: Website()"></span></li> + <li data-bind="visible: IM().length > 0"><strong><span data-bind="text: IMText">:</span></strong> <span data-bind="text: IM()"></span></li> + </ul> + </div> + <div class="dnnClear"></div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyProfile.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + + + [Tab.MyFriends.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Friends + [Tab.MyFriends.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + footerRightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + LeftPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.LeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + RightPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.RightPane.MemberDirectoryModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + FilterBy + User + + + FilterPropertyValue + + + + + + + SearchField2 + Email + + + SearchField3 + City + + + EnablePopUp + False + + + DisplaySearch + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField4 + Country + + + hideadminborder + False + + + SearchField1 + DisplayName + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.RightPane.NavigationModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + DefaultSize + IconNone + + + ShowTooltip + False + + + DefaultView + Hide + + + IncludeParent + False + + + TabVisibility-ActivityFeed-Friends + Friends + + + AllowViewChange + False + + + TabVisibility-ActivityFeed-Messages + User + + + + + hideadminborder + False + + + Console + Console + + + + + CenterPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.CenterPane.ViewProfileModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.CenterPane.MemberDirectoryModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + FilterPropertyValue + + + + + FilterValue + 1 + + + FilterBy + Relationship + + + + + SearchField2 + Email + + + DisplaySearch + False + + + SearchField3 + City + + + SearchField4 + Country + + + hideadminborder + False + + + SearchField1 + DisplayName + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyFriends.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + + + [Tab.MyMessages.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + true + + + false + -1 + 0.5 + [G]Skins/Gravity/3-Col-Social.ascx + 0001-01-01T00:00:00 + Messages + [Tab.MyMessages.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Activity Feed + + + footerRightPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.FooterRightPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerLeftOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.FooterLeftOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + LeftPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.LeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserProfileImg"> + <span><img alt="Profile Avatar" class="ProfilePhoto" width="120" height="120" src="[PROFILE:PHOTO]" /></span> + </div> + <div class="UserProfileControls"> + <ul> + <li>[HYPERLINK:EDITPROFILE]</li> + <li>[HYPERLINK:MYACCOUNT]</li> + </ul> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + RightPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.RightPane.MemberDirectoryModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + FilterBy + User + + + FilterPropertyValue + + + + + + + SearchField2 + Email + + + SearchField3 + City + + + EnablePopUp + False + + + DisplaySearch + False + + + ItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + PopUpTemplate + + + + + AlternateItemTemplate + + <div class="friendProfileActions" data-bind="visible: !IsUser() && IsAuthenticated"> + <ul> + <li><a href="" title="" class="ComposeMessage"><span data-bind="text: SendMessageText"></span></a></li> + <li> + <span> + <a href="" data-bind="click: addFriend, visible: FriendStatus() == 0"><span data-bind="text: AddFriendText"></span></a> + <span data-bind="click: addFriend, visible: IsPending()"><span data-bind="text: FriendPendingText"></span></span> + <a href="" data-bind="click: acceptFriend, visible: HasPendingRequest()"><span data-bind="text: AcceptFriendText"></span></a> + <a href="" data-bind="click: removeFriend, visible: IsFriend()"><span data-bind="text: RemoveFriendText"></span></a> + </span> + </li> + <li> + <span> + <a href="" data-bind="click: follow, visible: !IsFollowing()"><span data-bind="text: FollowText"></span></a> + <a href="" data-bind="click: unFollow, visible: IsFollowing()"><span data-bind="text: UnFollowText"></span></a> + </span> + </li> + </ul> + </div> + + + + SearchField4 + Country + + + hideadminborder + False + + + SearchField1 + DisplayName + + + DotNetNuke.Modules.MemberDirectory + Member Directory + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.RightPane.NavigationModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + Mode + Profile + + + ConsoleWidth + + + + + TabVisibility-ActivityFeed-MyProfile + AllUsers + + + AllowSizeChange + False + + + DefaultSize + IconNone + + + ShowTooltip + False + + + DefaultView + Hide + + + IncludeParent + False + + + TabVisibility-ActivityFeed-Friends + Friends + + + AllowViewChange + False + + + TabVisibility-ActivityFeed-Messages + User + + + + + hideadminborder + False + + + Console + Console + + + + + CenterPane + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.CenterPane.ViewProfileModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + ProfileTemplate + + <div id="UserDisplayNameHeader"> + <h2>[USER:DISPLAYNAME]</h2> + </div> + + + + hideadminborder + False + + + IncludeButton + False + + + ViewProfile + ViewProfile + + + + + false + + FileModuleCachingProvider + 0 + + [G]Containers/Gravity/NoTitle.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + false + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Registered Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Unverified Users + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.CenterPane.MessageCenterModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + False + + + DotNetNuke.Modules.CoreMessaging + Message Center + + + + + footerLeftPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.FooterLeftPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerCenterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.FooterCenterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + footerRightOuterPane + + + + + false + + FileModuleCachingProvider + 1200 + + [G]Containers/Gravity/Title_h4.ascx + false + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.MyMessages.FooterRightOuterPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + DNN_HTML + Text/HTML + + + + + + + + [Tab.PortalAdministration.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + false + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Admin + [Tab.PortalAdministration.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.PortalAdministration.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + ConsoleWidth + + + + + AllowSizeChange + False + + + DefaultSize + IconFileLarge + + + ShowTooltip + True + + + OrderTabsByHierarchy + True + + + DefaultView + Hide + + + AllowViewChange + False + + + + + hideadminborder + True + + + Console + Console + + + + + + + + [Tab.AdvancedSettings.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/AdvancedSettings_16X16_Standard.png + ~/Icons/Sigma/AdvancedSettings_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Advanced Settings + [Tab.AdvancedSettings.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + [Tab.AdvancedSettings.ContentPane.Module.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/AdvancedSettings_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + AdvancedSettings + Advanced Settings +
    +
    +
    +
    +
    + + [Tab.SiteSettings.Content.Text] + + + + [Tab.SiteSettings.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteSettings_16X16_Standard.png + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Settings + [Tab.SiteSettings.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SiteSettings.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Portals + Site Settings + + + + + + + [Tab.PageManagement.Content.Text] + + + + [Tab.PageManagement.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tabs_16X16_Standard.png + ~/Icons/Sigma/Tabs_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Pages + [Tab.PageManagement.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Tabs_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.PageManagement.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Tabs + Tabs + + + + + + + [Tab.Extensions.Content.Text] + + + + [Tab.Extensions.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Extensions_16X16_Standard.png + ~/Icons/Sigma/Extensions_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Extensions + [Tab.Extensions.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Extensions_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Extensions.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Extensions + Extensions + + + + + + + [Tab.Languages.Content.Text] + + + + [Tab.Languages.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Languages_16X16_Standard.png + ~/Icons/Sigma/Languages_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Languages + [Tab.Languages.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Languages_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Languages.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Languages + Languages + + + + + + + [Tab.Skins.Content.Text] + + + + [Tab.Skins.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Skins_16X16_Standard.png + ~/Icons/Sigma/Skins_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Skins + [Tab.Skins.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Skins_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Skins.ContentPane.SkinEditorModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Skins + Skins + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Skins_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Skins.ContentPane.SkinDesignerModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + SkinDesigner + Skin Designer + + + + + + + [Tab.SecurityRoles.Content.Text] + + + + [Tab.SecurityRoles.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SecurityRoles_16X16_Standard.png + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Security Roles + [Tab.SecurityRoles.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SecurityRoles.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Security + Security Roles + + + + + + + [Tab.UserAccounts.Content.Text] + + + + [Tab.UserAccounts.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Users_16X16_Standard.png + ~/Icons/Sigma/Users_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + User Accounts + [Tab.UserAccounts.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Users_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.UserAccounts.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Security + User Accounts + + + + + + + [Tab.Vendors.Content.Text] + + + + [Tab.Vendors.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Vendors_16X16_Standard.png + ~/Icons/Sigma/Vendors_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Vendors + [Tab.Vendors.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Vendors_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Vendors.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Vendors + Vendors + + + + + + + [Tab.SiteLog.Content.Text] + + + + [Tab.SiteLog.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteLog_16X16_Standard.png + ~/Icons/Sigma/SiteLog_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Log + [Tab.SiteLog.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/SiteLog_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SiteLog.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + SiteLog + Site Log + + + + + + + [Tab.Newsletters.Content.Text] + + + + [Tab.Newsletters.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/BulkMail_16X16_Standard.png + ~/Icons/Sigma/BulkMail_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Newsletters + [Tab.Newsletters.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/BulkMail_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Newsletters.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Newsletters + Newsletters + + + + + + + [Tab.DigitalAssetsManagement.Content.Text] + + + + [Tab.DigitalAssetsManagement.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Files_16X16_Standard.png + ~/Icons/Sigma/Files_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + File Management + [Tab.DigitalAssetsManagement.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Files_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.DigitalAssetsManagement.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + DotNetNuke.Modules.DigitalAssets + Digital Asset Management + + + + + + + [Tab.RecycleBin.Content.Text] + + + + [Tab.RecycleBin.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Trash_16X16_Standard.png + ~/Icons/Sigma/Trash_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Recycle Bin + [Tab.RecycleBin.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Trash_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.RecycleBin.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + RecycleBin + Recycle Bin + + + + + + + [Tab.LogViewer.Content.Text] + + + + [Tab.LogViewer.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/ViewStats_16X16_Standard.png + ~/Icons/Sigma/ViewStats_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Log Viewer + [Tab.LogViewer.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/ViewStats_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.LogViewer.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + LogViewer + Log Viewer + + + + + + + [Tab.SiteWizard.Content.Text] + + + + [Tab.SiteWizard.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Wizard_16X16_Standard.png + ~/Icons/Sigma/Wizard_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Wizard + [Tab.SiteWizard.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Wizard_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SiteWizard.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + SiteWizard + Site Wizard + + + + + + + [Tab.Taxonomy.Content.Text] + + + + [Tab.Taxonomy.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tag_16X16_Standard.png + ~/Icons/Sigma/Tag_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Taxonomy + [Tab.Taxonomy.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Tag_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Taxonomy.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + DotNetNuke.Taxonomy + Taxonomy Manager + + + + + + + [Tab.SiteMapSettings.Content.Text] + + + + [Tab.SiteMapSettings.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Sitemap_16X16_Standard.png + ~/Icons/Sigma/Sitemap_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Engine SiteMap + [Tab.SiteMapSettings.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Sitemap_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SiteMapSettings.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Sitemap + Sitemap + + + + + + + [Tab.Lists.Content.Text] + + + + [Tab.Lists.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Lists_16X16_Standard.png + ~/Icons/Sigma/Lists_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Lists + [Tab.Lists.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Lists_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.Lists.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + Lists + Lists + + + + + + + [Tab.SiteRedirection.Content.Text] + + + + [Tab.SiteRedirection.Description.Text] + false + 0001-01-01T00:00:00 + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_16x16.png + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Redirection Management + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings /> + <parent>Admin</parent> + <panes> + <pane> + <name>ContentPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod /> + <cachetime>0</cachetime> + <color /> + <containersrc /> + <displayprint>true</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile>~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png</iconfile> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions /> + <title>[Tab.SiteRedirection.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + None + 0001-01-01T00:00:00 + 0 + + + DotNetNuke.MobileManagement + DNN Site Redirection Management + + + + + + + [Tab.DevicePreview.Content.Text] + + + + [Tab.DevicePreview.Description.Text] + false + 0001-01-01T00:00:00 + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_16X16.png + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Device Preview Management + + <url type="Normal" /> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings /> + <parent>Admin</parent> + <panes> + <pane> + <name>ContentPane</name> + <modules> + <module> + <contentKey /> + <alignment /> + <alltabs>false</alltabs> + <border /> + <cachemethod /> + <cachetime>0</cachetime> + <color /> + <containersrc /> + <displayprint>true</displayprint> + <displaysyndicate>false</displaysyndicate> + <displaytitle>true</displaytitle> + <enddate>0001-01-01T00:00:00</enddate> + <footer /> + <header /> + <iconfile>~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png</iconfile> + <inheritviewpermissions>true</inheritviewpermissions> + <iswebslice>false</iswebslice> + <modulepermissions /> + <title>[Tab.DevicePreview.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + None + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + DotNetNuke.Modules.PreviewProfileManagement + DNN Device Preview Management + + + + + + + + [Tab.SearchResultsCE.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + false + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Results + [Tab.SearchResultsCE.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SearchResultsCE.ContentPane.SearchResultsModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + SearchResults + Search Results + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.SearchResultsCE.ContentPane.ResultsModule.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + ContentList + Content List + + + + + + + [Tab.GoogleAnalytics.Content.Text] + + + + [Tab.GoogleAnalytics.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/GoogleAnalytics_16X16_Standard.png + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Google Analytics + [Tab.GoogleAnalytics.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.GoogleAnalytics.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + GoogleAnalytics + GoogleAnalytics + + + + + + + + + [Tab.404ErrorPage.Content.Text] + + + + + false + 0001-01-01T00:00:00 + false + false + + + false + -1 + 0.5 + 0001-01-01T00:00:00 + 404 Error Page + [Tab.404ErrorPage.Title.Text] + [G]Skins/Gravity/404Skin.ascx + + 404Tab + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + false + FileModuleCachingProvider + 1200 + false + false + true + 0001-01-01T00:00:00 + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.404ErrorPage..Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + + + + [Tab.SearchAdmin.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Search_16x16_Standard.png + ~/Icons/Sigma/Search_32x32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Admin + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + [Tab.SearchAdmin.ContentPane.Module.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Search_16x16_Standard.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + SearchAdmin + Search Admin +
    +
    +
    +
    +
    + + + + + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + + + image/png + png + Awesome-Cycles-Logo.png + 67 + 10078 + 282 + + + image/png + png + Logo.png + 68 + 13621 + 278 + + + + + Cache/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + + + + Cache/Pages/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + + + + Images/ + 0 + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + + + image/png + png + Awesome-Cycles-Logo.png + 67 + 10078 + 282 + + + image/jpeg + jpg + Banner1.jpg + 360 + 90444 + 940 + + + image/jpeg + jpg + Banner2.jpg + 360 + 66151 + 940 + + + image/jpeg + jpg + Banner3.jpg + 360 + 83234 + 940 + + + image/jpeg + jpg + Banner4.jpg + 380 + 66951 + 980 + + + image/png + png + bike01.png + 118 + 46142 + 180 + + + image/png + png + bike02.png + 118 + 40623 + 180 + + + image/png + png + button_contactUs.png + 51 + 2889 + 240 + + + image/png + png + connect_facebook.png + 16 + 1356 + 17 + + + image/png + png + connect_googleplus.png + 16 + 1531 + 11 + + + image/png + png + connect_linkedin.png + 16 + 1347 + 17 + + + image/png + png + connect_twitter.png + 13 + 1477 + 19 + + + image/png + png + connect_twitter_t.png + 16 + 1339 + 13 + + + image/jpeg + jpg + Home-Ad1.jpg + 270 + 35239 + 400 + + + image/png + png + Home-Ad2.png + 130 + 56819 + 570 + + + image/png + png + Home-Ad3.png + 130 + 44393 + 570 + + + image/png + png + homeBanner.png + 381 + 613613 + 980 + + + image/png + png + product_WP2GDownhill.png + 195 + 60233 + 320 + + + image/png + png + Product-Junior.png + 200 + 106449 + 300 + + + image/png + png + Product-Road.png + 200 + 123417 + 300 + + + image/png + png + Products-BMX.png + 200 + 91942 + 300 + + + image/png + png + Products-City.png + 200 + 119594 + 300 + + + image/png + png + Products-Gravity.png + 200 + 106856 + 300 + + + image/png + png + Products-Trail.png + 200 + 110041 + 300 + + + image/png + png + storeFront.png + 202 + 108898 + 308 + + + image/png + png + storeNews1.png + 93 + 27942 + 147 + + + image/png + png + storeNews2.png + 93 + 25177 + 147 + + + image/png + png + team_Alejandro.png + 170 + 44581 + 128 + + + image/png + png + team_Beck.png + 170 + 42838 + 128 + + + image/png + png + team_chris.png + 120 + 25041 + 90 + + + image/png + png + team_Drew-Paul.png + 170 + 40522 + 128 + + + image/png + png + team_Ivan.png + 120 + 20968 + 90 + + + image/png + png + team_Jose.png + 170 + 46647 + 128 + + + image/png + png + team_ken.png + 170 + 43531 + 128 + + + image/png + png + team_Kip.png + 170 + 37423 + 128 + + + image/png + png + team_Lynn.png + 120 + 22900 + 90 + + + image/png + png + team_Max.png + 120 + 25076 + 90 + + + image/png + png + team_Michelle.png + 170 + 31137 + 128 + + + image/png + png + team_Mitch.png + 170 + 45033 + 128 + + + image/png + png + team_Myles.png + 170 + 44457 + 128 + + + image/png + png + team_Nathan.png + 120 + 16056 + 90 + + + image/png + png + team_noPic.png + 147 + 1313 + 110 + + + image/png + png + team_Oliver.png + 170 + 51581 + 128 + + + image/png + png + team_Robert Juarez.png + 170 + 36992 + 128 + + + image/png + png + team_Tracey.png + 120 + 24068 + 90 + + + image/png + png + team_Wiley.png + 170 + 42897 + 128 + + + image/png + png + team_Will.png + 120 + 24846 + 90 + + + + + Images/DNN/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + + + image/png + png + bike-powered.png + 345 + 185116 + 450 + + + image/gif + gif + Spacer.gif + 1 + 1093 + 1 + + + + + Images/DNN/Logos/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + + + + Templates/ + 0 + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + + + application/octet-stream + template + Default.page.template + 0 + 1593 + 0 + + + + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Default Website.template.en-US.resx b/DNN Platform/Library/Templates/Default Website.template.en-US.resx new file mode 100644 index 00000000000..4922d11f15e --- /dev/null +++ b/DNN Platform/Library/Templates/Default Website.template.en-US.resx @@ -0,0 +1,1893 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Default Website + + + en-US + + + Copyright [year] by DNN Corp + + + About Us + + + Our Team + + + Customer Support + + + Company + + + Contact Information + + + Products + + + Connect + + + About Us + + + About Us + + + Share your feedback + + + Watch the Getting Started Video + + + Let me at it + + + The video below will <strong> help get you started </strong> building your new site. Using DNN is fast and easy and you can have your new site up and running with real content in just a matter of minutes. + + + Watch the Video + + + What's new with 7.0 + + + Getting Started + + + Already an expert? + + + Setup your email, install languages, and other advanced configuration settings + + + Set Advanced Configuration Settings + + + Looking for answers? + + + Do you have any questions, ideas for improvement or just want to meet some other members? + + + Find an Answer + + + Submit your Ideas + + + We always appreciate your feedback + + + We would love to hear how we're doing + + + Welcome to Your Installation + + + Home + + + Our Products + + + Our Products + + + Customer Support + + + Company + + + Connect + + + News and Promotions + + + Contact Us + + + Contact Us + + + Products + + + Reach Us + + + Message Us + + + Customer Support + + + Company + + + Connect + + + Visit Us + + + Activity Feed + + + Activity Feed + + + Activity Feed + + + Contact Us + + + Products + + + Member Directory + + + Customer Support + + + Company + + + Connect + + + ViewProfile + + + Journal + + + My Profile + + + My Profile + + + My Profile + + + Contact Us + + + Products + + + ViewProfile + + + Member Directory + + + Navigation + + + ViewProfile + + + Customer Support + + + Company + + + Connect + + + My Friends + + + Friends + + + My Friends + + + Contact Us + + + Products + + + ViewProfile + + + Member Directory + + + Navigation + + + ViewProfile + + + Member Directory + + + Customer Support + + + Company + + + Connect + + + My Messages + + + Messages + + + My Messages + + + Contact Us + + + Products + + + ViewProfile + + + Member Directory + + + Navigation + + + ViewProfile + + + Message Center + + + Customer Support + + + Company + + + Connect + + + Website Administration + + + Admin + + + Website Administration + + + Basic Features + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Site Settings + + + Manage configuration settings for the portal. + + + Site Settings + + + Site Settings + + + Site Settings + + + Page Management + + + Manage pages within the site. + + + Pages + + + Page Management + + + Page Management + + + Extensions + + + Install, add, modify and delete extensions, such as modules, skins and language packs. + + + Extensions + + + Extensions + + + Extensions + + + Skins + + + Manage Skin Resources. + + + Skins + + + Skins + + + Skin Editor + + + Skin Designer + + + Languages + + + Manage Language Resources. + + + Languages + + + Languages + + + Language Management + + + Security Roles + + + Manage security roles for the portal. + + + Security Roles + + + Security Roles + + + Security Roles + + + User Accounts + + + Manage user accounts for the portal. + + + User Accounts + + + User Accounts + + + User Accounts + + + Vendors + + + Manage vendor accounts, banner advertising and affiliate referrals within the portal. + + + Vendors + + + Vendors + + + Vendors + + + Site Log + + + View statistical reports on site activity for the portal. + + + Site Log + + + Site Log + + + Site Log + + + Newsletters + + + Send email messages to users, security roles and specific email addresses. + + + Newsletters + + + Newsletters + + + Newsletters + + + File Management + + + Manage assets within the portal. + + + File Management + + + File Management + + + File Management + + + Recycle Bin + + + View, restore or permanently recycle pages and modules that have been deleted from the portal. + + + Recycle Bin + + + Recycle Bin + + + Recycle Bin + + + Log Viewer + + + View a historical log of database events such as event schedules, exceptions, account logins, module and page changes, user account activities, security role activities, etc. + + + Log Viewer + + + Log Viewer + + + Log Viewer + + + Site Wizard + + + Configure portal settings, page design and apply a site template using a step-by-step wizard. + + + Site Wizard + + + Site Wizard + + + Site Wizard + + + Taxonomy + + + Manage the Taxonomy for your Site. + + + Taxonomy + + + Taxonomy + + + Taxonomy Manager + + + Site Map Settings + + + Configure the sitemap for submission to common search engines. + + + Search Engine SiteMap + + + Site Map Settings + + + Search Engine SiteMap + + + Lists + + + Manage common lists + + + Lists + + + Lists + + + Lists + + + Site Redirection Management + + + Site Redirection Management. + + + Site Redirection Management + + + Site Redirection Management + + + Device Preview Management + + + Device Preview Management. + + + Device Preview Management + + + Device Preview Management + + + Search Results + + + Search Results + + + Search Results + + + Search Results + + + Results + + + Google Analytics + + + Configure Site Google Analytics settings. + + + Google Analytics + + + Google Analytics + + + Google Analytics + + + Configure Site Google Analytics Pro settings. + + + Google Analytics Pro + + + Google Analytics Pro + + + Google Analytics Pro + + + Search Results + + + Search Results + + + Search Results + + + Results + + + Manage the Staging of Content for your Site + + + Content Staging + + + Content Staging + + + The SharePoint Connector module allows users to connect and sync files between a SharePoint and DNN Server. + + + SharePoint Connector + + + SharePoint Connector + + + Search Admin + + + Search Admin + + + StyleGuide + + + StyleGuide + + + Headings + + + Buttons + + + Lists + + + Table + + + Image Alignment + + + Awesome Cycles News + + + Contact Us + + + Products + + + Our Products + + + Default Website Template + + + A dummy role group that represents the Global roles + + + Learn the basics of working with DNN + + + <strong>Way to go!</strong> You just completed your installation. <strong>What would you like to do next?</strong> + + + Find out what improvements and additions we've made to DNN Platform 7.1. + + + Watch the Video + + + Featured Product: + + + WP 2G Downhill + + + Learn More + + + +The flagship downhill bike from Awesome Cycles is finally avaliable! + + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + 2013 Models are in stock now + + + Published by + + + Awesome Cycles - + + + 14 August 2012 + + + Introducing the new line up of Awesome Cycles for 2013. We have brought more new bikes to our line up this year. Come and get them! + + + Read More + + + Awesome Cycles at Crankworx 2012 + + + 10 August 2012 + + + This year Awesome Cycles will make its first appearance at one of the largest mountain bike festivals in the world. + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + The 2013 Nebula + + + Competition ready right out of the box. + + + Perfection is in our nature. + + + Read the Awesome Cycles Story. + + + BMX is Back. + + + Go big or go home. + + + Welcome to Awesome Cycles. + + + We make your riding dreams a reality.  + + + We love it when we can provide our customers with their dream bicycle. That’s why we have the best and most creative + + + +people in the industry on hand to design and build exactly what you want. + + + Learn More + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Our very first shop opened in 2011 in SomePlace, + + + +California. We build, sell and ship our bikes worldwide + + + +from this location. + + + We love it when we can provide our customers with their dream bicycle. + + + That's why we have the best and most creative people in the industry on hand to design and build exactly what you want. + + + The story of Awesome cycles started numerous years ago with two guys, a simple idea and shed in Chris's moms backyard. After hundreds of hours of mindstorming and Will's steady hand with a welder the first awesome cycle was forged out of fire in molten lava that had been blessed by Chuck Norris himself! Just kidding, can you imagine? + + + Today the company has evolved to a level that neither Will nor Chris could have ever imagined. + + + Our bikes are created by some of the most passionate people in the industry. We use only the finest materials to elegantly craft some of the most beautiful bikes the roads and trails have ever seen. The use of modern technologies and practices has helped us achieve being one of the top bicycle brands in the world. + + + We continue to push the limits of what bikes are capable of achieving in the hopes of building a future where our bikes are enjoyed by people the world over. + + + Isn't it about time you joined the Awesome Cycles family? + + + Chris Watts + + + Co Founder + + + Will Blackburn + + + Michele Hensley + + + CEO + + + Jose Martinez + + + CFO + + + Lynn Chase + + + Marketing + + + Tracey Bauer + + + Alejandro Conway + + + Sales and Support + + + Beck Livingston + + + Oliver Witt + + + Product Manager + + + Nathan O'Riley + + + Designer + + + Drew-Paul Fauling + + + Engineer + + + Max Davidson + + + Kip Hamilton + + + Quality Assurance + + + Loyd White + + + Wiley Soto + + + Technician + + + Ivan Krivonogov + + + Cat Herder / Painter + + + Mitch Potter + + + Fabrication + + + Myles Hampton + + + Robert Juarez + + + Fabrication / CBO + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + Gravity Series + + + We are constantly pushing the limits of what bikes are capable of. Through careful testing, evaluation and production practices we can 100% guarantee that our gravity specific bikes will help you push the limits in the ever evolving sport of freeride mountain biking. + + + Read more + + + Mountain Series + + + The mountain is where we at Awesome Cycles like to call home. Whether it’s a short ride through the woods with your family, or an epic all day adventure through some of the toughest terrain. We are sure have the perfect mountain bike for any situation. + + + Road Series + + + From the Tour De France to the roads in California our road bikes have done it all. Taking some of the purest materials possible we have developed these modern road bikes to be both strong and amazingly light all without breaking the bank. + + + City Series + + + With the rising cost of gas who has money to commute by car anymore? That is why for 2012 we are proud to launch our new line of city specific bikes. Stylish, affordable and easily customizable our city bikes could be just what you are looking for. + + + Junior Series + + + This is where it all starts. A kids first bike is one of the greatest gifts you can give to them. With bikes designed to fit kids of all ages, we are sure you can find some thing that they will truly enjoy for many years to come. + + + Dirt / Street Series + + + Our next generation of purpose built street, park and dirt jump machines have arrived. Built out of 100% Chromoly steel our BMX and Hard Tail frames can handle it all. + + + So what are you waiting for? + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + Email Addresses + + + +General: + + + webmaster@awesomecycles.biz + + + +Advertising: + + + advertising@awesomecycles.biz + + + +Sponsorships: + + + sales@awesomecycles.biz + + + +Marketing: + + + marketing@awesomecycles.biz + + + +Partnerships: + + + partners@awesomecycles.biz + + + Phone Number + + + To reach Awesome Cycles by telephone during office hours (Monday-Friday 8:00am-5:00pm PST) please call (650) 288-3150. You can fax us at (650) 288-3191. + + + Everything Else + + + If you can't find what you are looking for in the lists we have provide hare, please use the contact form to the right and we will respond within 24 hours. + + + Your Name: + + + Your Email Address: + + + Your Message: + + + Send + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + San Mateo, California, USA | HQ + + + +155 Bovet Road, Suite 201 + + + +San Mateo, California 94402 + + + +USA + + + + Amsterdam, The Netherlands | Store + + + +Barbara Strozzilaan 201 + + + +1083 HN Amsterdam + + + +The Netherlands + + + + Langley, B.C. Canada | Office + + + +#211 - 9440 202nd Street + + + +Langley, British Columbia, Canada + + + +V1M 4A6 + + + + Dealer Locator + + + Submit + + + Enter postal code or city and country + + + This is an h1 heading. + + + Copy 13px Arial Regular on 18px leading + + + Lorem ipsum dolor sit amet, +consectetur adipiscing elit. Fusce sed leo. Maecenas ultrices lorem sit amet diam. Aliquam sollicitudin tristique nulla. + + + This is an h2 heading. + + + Lorem ipsum dolor sit amet, +consectetur adipiscing elit. Fusce sed leo. Maecenas ultrices lorem sit amet diam. Aliquam sollicitudin tristique nulla. + + + This is an h3 heading. + + + This is an h4 heading. + + + This is an h5 heading. + + + This is an h6 heading. + + + Hyperlink Buttons [ + + + Primary Style + + + Secondary Style + + + Alternative Style + + + Form Buttons [ + + + Unordered List + + + Pellentesque eu semt adipiscing tortor. + + + Duis fringilla urnla accumsan venenatis. + + + Nulla id ligula veltesque ac id magna. + + + Duis sollicitudin nisl adipiscing aliquet. + + + Ordered List + + + Table Heading One + + + Table Heading Two + + + Table Heading Three + + + Table Heading Four + + + Column One + + + Column Two + + + Column Three + + + Column Four + + + Image - Align Left + + + Image Align Left + + + amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. + + + + Image - Align Right + + + Image Align Right + + + Image - Border Style + + + Image Border Style + + + Image - Polaroid Style + + + Enter Description Here! + + + Image Polaroid Style + + + amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. + + + 2013 Models are in stock now + + + 14 August 2012 + + + Awesome Cycles at Crankworx 2012 + + + 10 August 2012 + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Awesome Cycles, Inc. + + + +3457 W. Somewhere Street. +Someplace, CA 12345 + + + +Phone: (555) 555-4563 + + + +Fax: (555) 555-4564 + + + Mountain + + + Gravity + + + Road + + + City + + + Junior + + + Dirt/ Street + + + FAQ + + + Bike Manuals + + + Product Catalogs + + + Product Archive + + + Product Support + + + Bike Warranty + + + Newsletter + + + History + + + Careers + + + Legal + + + Add New Functionality + + + Enhance your site with capabilities such as e-commerce. + + + Visit the DNN Store + + + Sponsors + + + Personalize your site + + + Are you ready to make the DNN Platform your own? + + + We have the resources and tools to do just about anything you can imagine. + + + I want to... + + + Change the look of my site + + + Find new skin designs for your website on the DNN Store. + + + 404 Error Page + + + 404 Error Page + + + Advanced URL Management + + + Manage advanced url settings. + + + Sorry, the page you are looking for cannot be found and might have been removed, had its name changed, or is temporarily unavailable. It is recommended that you start again from the homepage. Feel free to contact us if the problem persists or if you definitely cannot find what you’re looking for. + + + Page cannot be found + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Default Website.template.resources b/DNN Platform/Library/Templates/Default Website.template.resources new file mode 100644 index 00000000000..8c39d6f5756 Binary files /dev/null and b/DNN Platform/Library/Templates/Default Website.template.resources differ diff --git a/DNN Platform/Library/Templates/Mobile Website.template b/DNN Platform/Library/Templates/Mobile Website.template new file mode 100644 index 00000000000..e92bd22a0d5 --- /dev/null +++ b/DNN Platform/Library/Templates/Mobile Website.template @@ -0,0 +1,5161 @@ + + + [PortalDescription.Text] + + + Logo.png + [Setting.FooterText.Text] + 1 + 0 + [Setting.DefaultLanguage.Text] + [G]Skins/DarkKnightMobile/interior.ascx + [G]Skins/DarkKnight/2-Column-Right-Mega-Menu.ascx + [G]Containers/DarkKnightMobile/Simple.ascx + [G]Containers/DarkKnight/PageTitle_Grey.ascx + True + Pacific Standard Time + + + + Basic + Prefix + Text + 50 + 0 + + + Basic + FirstName + Text + 50 + 0 + + + Basic + MiddleName + Text + 50 + 0 + + + Basic + LastName + Text + 50 + 0 + + + Basic + Biography + RichText + 0 + 2 + + + Basic + Photo + Image + 0 + 0 + + + Contact + Telephone + Text + 50 + 2 + + + Contact + Cell + Text + 50 + 2 + + + Contact + Fax + Text + 50 + 2 + + + Contact + Website + Text + 50 + 2 + + + Contact + IM + Text + 50 + 2 + + + Contact + Twitter + Text + 50 + 2 + + + Contact + Skype + Text + 50 + 2 + + + Contact + LinkedIn + Text + 50 + 2 + + + Contact + Facebook + Text + 50 + 2 + + + Location + Unit + Text + 50 + 2 + + + Location + Street + Text + 50 + 2 + + + Location + City + Text + 50 + 2 + + + Location + Region + Region + 0 + 2 + + + Location + Country + Country + 0 + 2 + + + Location + PostalCode + Text + 50 + 2 + + + Location + PreferredTimeZone + TimeZoneInfo + 0 + 2 + + + Location + TimeZone + TimeZone + 0 + 2 + + + Location + PreferredLocale + Locale + 0 + 2 + + + + + + Pages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Vendors + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Banners + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Lists + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + File Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Log + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Newletters + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Recycle Bin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Log Viewer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Input + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Results + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Wizard + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Login + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Registration + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Feed Explorer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Extensions + + + + Solutions + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + WhatsNew + + + + Dashboard + + + + Languages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Skins + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Console + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Marketplace + + + + View Profile + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Sitemap + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + ContentList + + + + Configuration Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Professional Preview + + + + DDR Menu + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Taxonomy Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + RadEditor Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + Google Analytics + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + HTML + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Admin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + GlobalRoles + [RoleGroup.Description.Text] + + + Administrators + Administrators of this Website + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + adminrole + true + + + Registered Users + Registered Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + true + + + registeredrole + true + + + Subscribers + A public role for site subscriptions + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + true + true + + + subscriberrole + true + + + Translator (en-US) + A role for English (United States) translators + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + none + false + + + Unverified Users + Unverified Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + unverifiedrole + true + + + + + + + + [G]Containers/Aphelia/Title.ascx + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + [G]Skins/Aphelia/twoColumn-rightAside.ascx + 0001-01-01T00:00:00 + Getting Started + [Tab.GettingStarted.Title.Text] + + gettingStartedTab + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + IncludeVaryBy + + + + + CacheDuration + + + + + CacheIncludeExclude + + + + + ExcludeVaryBy + + + + + MaxVaryByCount + + + + + CacheProvider + + + + + CustomStylesheet + GettingStarted.css + + + + + ContentPane + + + 514 + [Tab.GettingStarted.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/Aphelia/Banner.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + WorkflowID + 1 + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + [Tab.Home.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Home.Keywords.Text] + [Tab.Home.PageHeadText.Text] + false + -1 + 0.5 + [G]Skins/DarkKnightMobile/home.ascx + 0001-01-01T00:00:00 + Home + [Tab.Home.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + + + + + hometab + + + ContentPane + + + 529 + [Tab.Home.ContentPane.Module.Title.Text] + false + true +
    [Tab.Home.ContentPane.Module.Header.Text]
    +
    [Tab.Home.ContentPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/DarkKnightMobile/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + CONTENT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + DELETE + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EXPORT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + IMPORT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + MANAGE + true + Administrators + + + + + + Allow_ModuleWorkflowOverride + True + + + WorkflowID + 1 + + + HtmlText_RenderType + 0 + + + Allow_PageWorkflowOverride + True + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    + + SocialPane + + + 466 + [Tab.Home.SocialPane.Module.Title.Text] + true + true +
    [Tab.Home.SocialPane.Module.Header.Text]
    +
    [Tab.Home.SocialPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/DarkKnightMobile/NoTitle.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + IMPORT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + MANAGE + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + CONTENT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + DELETE + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EXPORT + true + Administrators + + + + + + HtmlText_ReplaceTokens + False + + + WorkflowID + 1 + + + HtmlText_RenderType + 0 + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + [Tab.About.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.About.Keywords.Text] + [Tab.About.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + About Us + [Tab.About.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + SYSTEM_TAB + ADD + true + Administrators + + + SYSTEM_TAB + CONTENT + true + Administrators + + + SYSTEM_TAB + COPY + true + Administrators + + + SYSTEM_TAB + DELETE + true + Administrators + + + SYSTEM_TAB + EXPORT + true + Administrators + + + SYSTEM_TAB + IMPORT + true + Administrators + + + SYSTEM_TAB + MANAGE + true + Administrators + + + SYSTEM_TAB + NAVIGATE + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + + + + + + + ContentPane + + + 530 + [Tab.About.ContentPane.Module.Title.Text] + false + true +
    [Tab.About.ContentPane.Module.Header.Text]
    +
    [Tab.About.ContentPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + FileModuleCachingProvider + + + + + Maximized + [G]Containers/DarkKnightMobile/Simple.ascx + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + CONTENT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + DELETE + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EXPORT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + IMPORT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + MANAGE + true + Administrators + + + + + + Allow_ModuleWorkflowOverride + True + + + WorkflowID + 1 + + + HtmlText_RenderType + 0 + + + Allow_PageWorkflowOverride + True + + + HtmlText_ReplaceTokens + False + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + [Tab.Products.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Products.Keywords.Text] + [Tab.Products.PageHeaderText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Products + [Tab.Products.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + + + ContentPane + + + 531 + [Tab.Products.ContentPane.Module.Title.Text] + false + true +
    [Tab.Products.ContentPane.Module.Header.Text]
    +
    [Tab.Products.ContentPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + [Tab.Services.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Services.Keywords.Text] + [Tab.Services.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Services + [Tab.Services.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + + + ContentPane + + + 532 + [Tab.Services.ContentPane.Module.Title.Text] + false + true +
    [Tab.Services.ContentPane.Module.Header.Text]
    +
    [Tab.Services.ContentPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + [Tab.ContactUs.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.ContactUs.Keywords.Text] + [Tab.ContactUs.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Contact Us + [Tab.ContactUs.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + SYSTEM_TAB + ADD + true + Administrators + + + SYSTEM_TAB + CONTENT + true + Administrators + + + SYSTEM_TAB + COPY + true + Administrators + + + SYSTEM_TAB + DELETE + true + Administrators + + + SYSTEM_TAB + EXPORT + true + Administrators + + + SYSTEM_TAB + IMPORT + true + Administrators + + + SYSTEM_TAB + MANAGE + true + Administrators + + + SYSTEM_TAB + NAVIGATE + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + + + ContentPane + + + 533 + [Tab.ContactUs.ContentPane.Module.Title.Text] + false + true +
    [Tab.ContactUs.ContentPane.Module.Header.Text]
    +
    [Tab.ContactUs.ContentPane.Module.Footer.Text]
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 1200 + + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + DNN_HTML + Text/HTML +
    +
    +
    +
    +
    + + + + + false + 0001-01-01T00:00:00 + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + History + + + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + About Us + + + + + [Tab.Investors.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Investors.Keywords.Text] + [Tab.Investors.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Investor Relations + [Tab.Investors.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + SYSTEM_TAB + ADD + true + Administrators + + + SYSTEM_TAB + CONTENT + true + Administrators + + + SYSTEM_TAB + COPY + true + Administrators + + + SYSTEM_TAB + DELETE + true + Administrators + + + SYSTEM_TAB + EXPORT + true + Administrators + + + SYSTEM_TAB + IMPORT + true + Administrators + + + SYSTEM_TAB + MANAGE + true + Administrators + + + SYSTEM_TAB + NAVIGATE + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + About Us + + + + + [Tab.Directors.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.Directors.Keywords.Text] + [Tab.Directors.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Board of Directors + [Tab.Directors.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + SYSTEM_TAB + ADD + true + Administrators + + + SYSTEM_TAB + CONTENT + true + Administrators + + + SYSTEM_TAB + COPY + true + Administrators + + + SYSTEM_TAB + DELETE + true + Administrators + + + SYSTEM_TAB + EXPORT + true + Administrators + + + SYSTEM_TAB + IMPORT + true + Administrators + + + SYSTEM_TAB + MANAGE + true + Administrators + + + SYSTEM_TAB + NAVIGATE + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + About Us + + + + + [Tab.ManagementTeam.Description.Text] + false + 0001-01-01T00:00:00 + false + true + [Tab.ManagementTeam.Keywords.Text] + [Tab.ManagementTeam.PageHeadText.Text] + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Management Team + [Tab.ManagementTeam.Title.Text] + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + SYSTEM_TAB + ADD + true + Administrators + + + SYSTEM_TAB + CONTENT + true + Administrators + + + SYSTEM_TAB + COPY + true + Administrators + + + SYSTEM_TAB + DELETE + true + Administrators + + + SYSTEM_TAB + EXPORT + true + Administrators + + + SYSTEM_TAB + IMPORT + true + Administrators + + + SYSTEM_TAB + MANAGE + true + Administrators + + + SYSTEM_TAB + NAVIGATE + true + Administrators + + + + + CacheDuration + + + + + ExcludeVaryBy + + + + + CacheProvider + + + + + IncludeVaryBy + + + + + MaxVaryByCount + + + + + CacheIncludeExclude + 0 + + + About Us + + + + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Results + Search Results + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + 463 + Search Results + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ConsoleWidth + + + + + AllowSizeChange + False + + + ShowTooltip + True + + + DefaultSize + IconFileLarge + + + DefaultView + Hide + + + AllowViewChange + False + + + + SearchCrawlerResults + SearchCrawlerResults +
    + + 464 + Results + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ContentList + Content List +
    +
    +
    +
    +
    + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + User Profile + User Profile + + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + usertab + + + ContentPane + + + 465 + My Profile + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ViewProfile + ViewProfile +
    + + 466 + My Inbox + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Registered Users + + + + + DotNetNuke.Messaging + Messaging +
    +
    +
    +
    +
    + + + + + false + 0001-01-01T00:00:00 + false + false + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Admin + Website Administration + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + Basic Features + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + AllowViewChange + False + + + ShowTooltip + True + + + OrderTabsByHierarchy + True + + + AllowSizeChange + False + + + DefaultSize + IconFileLarge + + + DefaultView + Hide + + + ConsoleWidth + + + + + + + hideadminborder + True + + + Console + Console +
    +
    +
    +
    +
    + + + [Tab.AdvancedSettings.Description.Text] + false + 0001-01-01T00:00:00 + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Advanced Settings + [Tab.AdvancedSettings.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + [Tab.AdvancedSettings.ContentPane.Module.Title.Text] + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + AdvancedSettings + Advanced Settings +
    +
    +
    +
    +
    + + + Manage configuration settings for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteSettings_16X16_Standard.png + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Settings + Site Settings + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 467 + Site Settings + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SiteSettings_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Portals + Site Settings +
    +
    +
    +
    +
    + + + Manage pages within the site. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tabs_16X16_Standard.png + ~/Icons/Sigma/Tabs_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Pages + Page Management + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 468 + Page Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Tabs_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Tabs + Tabs +
    +
    +
    +
    +
    + + + Install, add, modify and delete extensions, such as modules, skins and language packs. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Extensions_16X16_Standard.png + ~/Icons/Sigma/Extensions_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Extensions + Extensions + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 469 + Extensions + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Extensions_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Extensions + Extensions +
    +
    +
    +
    +
    + + + Manage Language Resources. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Languages_16X16_Standard.png + ~/Icons/Sigma/Languages_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Languages + Languages + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 470 + Language Management + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Languages_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Languages + Languages + + + + + + + + Manage Skin Resources. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Skins_16X16_Standard.png + ~/Icons/Sigma/Skins_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Skins + Skins + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 471 + Skin Editor + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Skins_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Skins + Skins +
    + + 472 + Skin Designer + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Skins_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SkinDesigner + Skin Designer +
    +
    +
    +
    +
    + + + Manage security roles for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SecurityRoles_16X16_Standard.png + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Security Roles + Security Roles + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 473 + Security Roles + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SecurityRoles_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + Security Roles +
    +
    +
    +
    +
    + + + Manage user accounts for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Users_16X16_Standard.png + ~/Icons/Sigma/Users_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + User Accounts + User Accounts + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 474 + User Accounts + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Users_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + User Accounts +
    +
    +
    +
    +
    + + + Manage vendor accounts, banner advertising and affiliate referrals within the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Vendors_16X16_Standard.png + ~/Icons/Sigma/Vendors_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Vendors + Vendors + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 475 + Vendors + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Vendors_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Vendors + Vendors +
    +
    +
    +
    +
    + + + View statistical reports on site activity for the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/SiteLog_16X16_Standard.png + ~/Icons/Sigma/SiteLog_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Log + Site Log + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 476 + Site Log + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/SiteLog_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteLog + Site Log +
    +
    +
    +
    +
    + + + Send email messages to users, security roles and specific email addresses. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/BulkMail_16X16_Standard.png + ~/Icons/Sigma/BulkMail_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Newsletters + Newsletters + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 477 + Newsletters + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/BulkMail_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Newsletters + Newsletters +
    +
    +
    +
    +
    + + [Tab.DigitalAssetsManagement.Content.Text] + + + + [Tab.DigitalAssetsManagement.Description.Text] + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Files_16X16_Standard.png + ~/Icons/Sigma/Files_32X32_Standard.png + false + true + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + File Management + [Tab.DigitalAssetsManagement.Title.Text] + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + + + false + + + 0 + + + true + false + true + 0001-01-01T00:00:00 +
    +
    + ~/Icons/Sigma/Files_32X32_Standard.png + true + false + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + [Tab.DigitalAssetsManagement.ContentPane.Module.Title.Text] + 0001-01-01T00:00:00 + Maximized + 0001-01-01T00:00:00 + 0 + + + + hideadminborder + True + + + DotNetNuke.Modules.DigitalAssets + Digital Asset Management + + + + + + + + View, restore or permanently recycle pages and modules that have been deleted from the portal. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Trash_16X16_Standard.png + ~/Icons/Sigma/Trash_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Recycle Bin + Recycle Bin + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 479 + Recycle Bin + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Trash_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + RecycleBin + Recycle Bin +
    +
    +
    +
    +
    + + + View a historical log of database events such as event schedules, exceptions, account logins, module and page changes, user account activities, security role activities, etc. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/ViewStats_16X16_Standard.png + ~/Icons/Sigma/ViewStats_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Log Viewer + Log Viewer + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 480 + Log Viewer + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/ViewStats_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + LogViewer + Log Viewer +
    +
    +
    +
    +
    + + + Configure portal settings, page design and apply a site template using a step-by-step wizard. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Wizard_16X16_Standard.png + ~/Icons/Sigma/Wizard_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Wizard + Site Wizard + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 481 + Site Wizard + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Wizard_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteWizard + Site Wizard +
    +
    +
    +
    +
    + + + Manage the Taxonomy for your Site. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Tag_16X16_Standard.png + ~/Icons/Sigma/Tag_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Taxonomy + Taxonomy + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 483 + Taxonomy Manager + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Tag_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + DotNetNuke.Taxonomy + Taxonomy Manager + + + + + + + + Configure the sitemap for submission to common search engines. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Sitemap_16X16_Standard.png + ~/Icons/Sigma/Sitemap_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Engine SiteMap + Search Engine SiteMap + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 484 + Search Engine SiteMap + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Sitemap_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Sitemap + Sitemap + + + + + + + + Manage common lists + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Lists_16X16_Standard.png + ~/Icons/Sigma/Lists_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Lists + Lists + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 342 + Lists + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Lists_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Lists + Lists +
    +
    +
    +
    +
    + + + Site Redirection Management. + false + 0001-01-01T00:00:00 + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_16x16.png + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Site Redirection Management + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 486 + Site Redirection Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/desktopmodules/MobileManagement/images/MobileManagement_Standard_32x32.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + DotNetNuke.MobileManagement + DNN Site Redirection Management +
    +
    +
    +
    +
    + + + Device Preview Management. + false + 0001-01-01T00:00:00 + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_16X16.png + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Device Preview Management + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 487 + Device Preview Management + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/desktopmodules/DevicePreviewManagement/images/DevicePreview_Standard_32X32.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + DotNetNuke.Modules.PreviewProfileManagement + DNN Device Preview Management +
    +
    +
    +
    +
    + + + + + + Configure Site Google Analytics settings. + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/GoogleAnalytics_16X16_Standard.png + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Google Analytics + Google Analytics + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 482 + Google Analytics + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/GoogleAnalytics_32X32_Standard.png + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + GoogleAnalytics + GoogleAnalytics +
    +
    +
    +
    +
    + + + Search Admin + false + 0001-01-01T00:00:00 + ~/Icons/Sigma/Search_16x16_Standard.png + ~/Icons/Sigma/Search_32x32_Standard.png + false + true + + + + + false + -1 + 0.5 + + 0001-01-01T00:00:00 + Search Admin + + + + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + Search Admin + false + true +
    +
    +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/Icons/Sigma/Search_16x16_Standard.png + None + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + + + hideadminborder + True + + + SearchAdmin + Search Admin +
    +
    +
    +
    +
    + + + + + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + ADD + Administrators + true + + + SYSTEM_FOLDER + COPY + Administrators + true + + + SYSTEM_FOLDER + DELETE + Administrators + true + + + SYSTEM_FOLDER + MANAGE + Administrators + true + + + + + image/png + png + dnn-goes-mobile.png + 320 + 106010 + 760 + + + image/jpeg + jpg + dotnetnuke-goes-mobile.jpg + 317 + 37942 + 702 + + + image/png + png + dotnetnuke-goes-mobile-campaign-en-US.png + 320 + 76048 + 760 + + + image/png + png + dotnetnuke-goes-mobile-campaign-de-DE.png + 320 + 76048 + 760 + + + image/png + png + dotnetnuke-goes-mobile-campaign-es-ES.png + 320 + 76048 + 760 + + + image/png + png + dotnetnuke-goes-mobile-campaign-fr-FR.png + 320 + 76048 + 760 + + + image/png + png + dotnetnuke-goes-mobile-campaign-it-IT.png + 320 + 76048 + 760 + + + image/png + png + dotnetnuke-goes-mobile-campaign-nl-NL.png + 320 + 76048 + 760 + + + image/jpeg + jpg + dotnetnuke-logo.jpg + 97 + 9308 + 400 + + + image/png + png + dotnetnuke-logo.png + 97 + 21363 + 400 + + + image/jpeg + jpg + map.jpg + 280 + 37898 + 520 + + + image/jpeg + jpg + mobile-campaign760.jpg + 320 + 33165 + 760 + + + image/png + png + PageImage-431523-2157664-6141-preview.png + 225 + 70043 + 300 + + + image/png + png + PageImage-431523-2159279-3146-preview.png + 225 + 57169 + 300 + + + image/png + png + PageImage-431523-2162195-9738-preview1.png + 225 + 74833 + 300 + + + image/png + png + PageImage-490125-2157645-preview.png + 225 + 28435 + 300 + + + image/png + png + PageImage-490125-2185195-preview.png + 225 + 44810 + 300 + + + image/png + png + PageImage-490125-2197371-preview.png + 225 + 69429 + 300 + + + image/png + png + social-icns.png + 24 + 6751 + 204 + + + image/jpeg + jpg + teamImg01.jpg + 140 + 6704 + 140 + + + image/jpeg + jpg + teamImg02.jpg + 140 + 9522 + 140 + + + + + Cache/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + ADD + Administrators + true + + + SYSTEM_FOLDER + COPY + Administrators + true + + + SYSTEM_FOLDER + DELETE + Administrators + true + + + SYSTEM_FOLDER + MANAGE + Administrators + true + + + + + + Cache/Pages/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + ADD + Administrators + true + + + SYSTEM_FOLDER + COPY + Administrators + true + + + SYSTEM_FOLDER + DELETE + Administrators + true + + + SYSTEM_FOLDER + MANAGE + Administrators + true + + + + + + Templates/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + ADD + Administrators + true + + + SYSTEM_FOLDER + COPY + Administrators + true + + + SYSTEM_FOLDER + DELETE + Administrators + true + + + SYSTEM_FOLDER + MANAGE + Administrators + true + + + + + application/octet-stream + template + Default.page.template + -1 + 1593 + -1 + + + + + Users/ + 0 + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + ADD + Administrators + true + + + SYSTEM_FOLDER + COPY + Administrators + true + + + SYSTEM_FOLDER + DELETE + Administrators + true + + + SYSTEM_FOLDER + MANAGE + Administrators + true + + + + + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Mobile Website.template.en-US.resx b/DNN Platform/Library/Templates/Mobile Website.template.en-US.resx new file mode 100644 index 00000000000..ed403f93f05 --- /dev/null +++ b/DNN Platform/Library/Templates/Mobile Website.template.en-US.resx @@ -0,0 +1,563 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Mobile Website + + + A dummy role group that represents the Global roles + + + en-US + + + Copyright [year] by DNN Corp + + + Elizabeth Taylor + + + President, CEO + + + Donec nibh ipsum, ullamcorper eleifend molestie nec, elementum et est. Quisque a massa et sapien vestibulum pulvinar. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam diam lacus, scelerisque eu luctus a, blandit nec mi. + + + Vestibulum interdum porttitor sapien, quis tempor nisl bibendum quis. Vestibulum ac feugiat urna. Morbi quis velit sed magna blandit gravida vel nec purus. Vivamus vel nibh nisl. + + + James Woolworth + + + Nam augue velit, tincidunt in ultricies at, varius pellentesque mauris. Etiam orci risus, tincidunt eu faucibus at, dictum et mauris. + + + Donec turpis urna, suscipit ut eleifend semper, commodo non sapien. Aenean facilisis ipsum at elit consequat quis luctus justo feugiat. Vivamus lacus diam, scelerisque vitae bibendum id, condimentum eu diam. + + + Susan G. Komen + + + Vestibulum scelerisque tincidunt nisl nec laoreet. Proin pellentesque aliquet molestie. + + + Morbi quis velit sed magna blandit gravida vel nec purus. Vivamus vel nibh nisl.Vestibulum scelerisque tincidunt nisl nec laoreet. + + + Marisa Miller + + + + + + + + + Our Management + + + About Us + + + + + + DotNetNuke Corp. + + + 155 Bovet Road, Suite 201 + + + +San Mateo, CA 94402 + + + E + + + sales@dnncorp.com + + + P + + + (650) 288 - 3150 + + + F + + + : (650) 288 - 3191 + + + + + + + + + Contact Us + + + + + + + + + Contact Us + + + + + + + + + DotNetNuke powers mobile websites – FAST. Just follow the three simple steps below: + + + Create your mobile content + + + Creating content with DotNetNuke is very easy. You can start by editing the content in the existing pages or creating new ones and add your own modules. + + + Preview content + + + Mobile devices have different resolutions. Use the included profiles and create your own to see how your content will look in different screen resolutions. + + + Manage URL redirection + + + Define what devices must use your new mobile website. The most common scenario will be for mobile phones to be redirected to your new site, but you can define sites for tablets or other devices based on their capabilities. + + + + + + + + + DotNetNuke Goes Mobile + + + + + + + + + Home + + + + + + + .socialIcons{ width:204px;height: 24px; margin: 0 auto; text-align: center;} + .socialIcons .icon{width: 24px; height: 24px; display: block; float: left; margin-right: 21px; background-image: url({{PortalRoot}}/social-icns.png);} + .socialIcons .youtube{background-position: -45px 0;} + .socialIcons .linkedin{background-position: -90px 0;} + .socialIcons .flickr{background-position: -135px 0;} + .socialIcons .facebook{background-position: -180px 0;margin-right: 0;} + + + + + + + + + + Text/HTML + + + + + + + + + + + + + + + Vintage Design + + + Proin condimentum odio ipsum, sit amet consequat lacus. Ut elementum nisl id lectus ullamcorper bibendum. Praesent pellentesque bibendum sodales. Aenean ut convallis velit. In vestibulum aliquam condimentum. Vivamus tincidunt ante id nibh volutpat porta. + + + Praesent pellentesque bibendum sodales. Aenean ut convallis velit. In vestibulum aliquam condimentum. Vivamus tincidunt ante id nibh volutpat porta. + + + High Performance + + + Electric Dance + + + Proin condimentum odio ipsum, sit amet consequat lacus. Ut elementum nisl id lectus ullamcorper bibendum. + + + + + + + + + Our Awesome Bicycles + + + + + + + + + Products + + + + + + + + + Suspendisse hendrerit mi a mi vehicula tempus vitae nec felis. Praesent ac urna at lectus porta porttitor. Cras nulla leo, porta nec laoreet ac, lobortis non enim. Duis nisl nisi, mattis vel egestas sed, venenatissed turpis. Donec vel metus risus, egestas.  + + + Praesent pellentesque bibendum sodales. Aenean ut convallis velit. In vestibulum aliquam condimentum. Vivamus tincidunt ante id nibh volutpat porta. Nulla ut dolor massa, eu vestibulum massa. + + + Proin condimentum odio ipsum, sit amet consequat lacus. + + + Ut elementum nisl id lectus ullamcorper bibendum. + + + Praesent pellentesque bibendum sodales. + + + Aenean ut convallis velit. + + + In vestibulum aliquam condimentum. + + + Vivamus tincidunt ante id nibh volutpat porta. + + + Do you miss the clean lines and classic designs of the past? Check out our custom recreations based on some of the most popular designs from your childhood.  + + + Suspendisse eget elit vel sem egestas pretium. Mauris id nulla et dolor fringilla feugiat. Etiam vitae turpis ac mauris rhoncus rutrum id ac nunc. Phasellus mi dolor, consequat nec malesuada non, pulvinar a risus. Sed consequat, ante vel lacinia convallis, ante nibh eleifend neque, id hendrerit nulla quam non mauris. Suspendisse auctor, sapien sed egestas mollis, mi sem congue lorem, quis tempus felis arcu nec nisl. Suspendisse ac massa dolor. Curabitur lacus mi, porta vel pretium sed, aliquet at felis. Integer sem metus, scelerisque ut. + + + + + + + + + Our Services + + + + + + + + + Services + + + + + + + + + Mobile Template + + + + + + + + + Board of Directors + + + + + + + + + + + + + + + Investor Relations + + + + + + + + + + + + + + + Management Team + + + + + + + + + en-US + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Advanced Configuration Settings + + + Watch the Getting Started Video + + + Let me at it + + + <strong>Way to go!</strong> you just completed your installation of DotNetNuke; <strong>what whould you like to do next?</strong> + + + The video below will <strong> help get you started </strong> building your new DotNetNuke site. Using DotNetNuke is fast and easy and you can have your new site up and running with real content in just a matter of minutes. + + + Watch the Video + + + Add New Functionality + + + Enhance your site with capabilities such as e-commerce. + + + Visit the DotNetNuke Store + + + Sponsors + + + Find out what improvements and additions we've made to DotNetNuke 7.0. + + + Watch the Video + + + Personalize your DotNetNuke + + + Are you ready to make DotNetNuke your own? + + + We have the resources and tools to do just about anything you can imagine. + + + I want to... + + + Change the look of my site + + + Find new skin designs for your website on the DotNetNuke Store. + + + What's new with 7.0 + + + Learn the basics of working with DNN + + + Getting Started + + + Already an expert? + + + Setup your email, install languages, and other advanced configuration settings + + + Set Advanced Configuration Settings + + + Looking for answers? + + + Do you have any questions, ideas for improvement or just want to meet some other DotNetNuke members? + + + Find an Answer + + + Submit you Ideas + + + We always appreciate your feedback + + + We would love to hear how we're doing + + + Welcome to Your DotNetNuke Installation + + + Share your feedback + + + Search Admin + + + Search Admin + + \ No newline at end of file diff --git a/DNN Platform/Library/Templates/Mobile Website.template.resources b/DNN Platform/Library/Templates/Mobile Website.template.resources new file mode 100644 index 00000000000..70ad8c5879f Binary files /dev/null and b/DNN Platform/Library/Templates/Mobile Website.template.resources differ diff --git a/DNN Platform/Library/TemplatesBeta/Default Website.template b/DNN Platform/Library/TemplatesBeta/Default Website.template new file mode 100644 index 00000000000..9e0427050d9 --- /dev/null +++ b/DNN Platform/Library/TemplatesBeta/Default Website.template @@ -0,0 +1,3075 @@ + + Default Website Template + + logo.gif + Copyright 2011 by DotNetNuke Corporation + 2 + 0 + en-US + Pacific Standard Time + true + 0 + 0 + 0 + canonicalurl + + + + Name + Prefix + Text + 50 + 0 + + + Name + FirstName + Text + 50 + 0 + + + Name + MiddleName + Text + 50 + 0 + + + Name + LastName + Text + 50 + 0 + + + Name + Suffix + Text + 50 + 0 + + + Address + Unit + Text + 50 + 2 + + + Address + Street + Text + 50 + 2 + + + Address + City + Text + 50 + 2 + + + Address + Region + Region + 0 + 2 + + + Address + Country + Country + 0 + 2 + + + Address + PostalCode + Text + 50 + 2 + + + Contact Info + Telephone + Text + 50 + 2 + + + Contact Info + Cell + Text + 50 + 2 + + + Contact Info + Fax + Text + 50 + 2 + + + Contact Info + Website + Text + 50 + 2 + + + Contact Info + IM + Text + 50 + 2 + + + Preferences + Photo + Image + 0 + 0 + + + Preferences + Biography + RichText + 0 + 2 + + + Preferences + TimeZoneInfo + TimeZoneInfo + 0 + 2 + + + Preferences + PreferredLocale + Locale + 0 + 2 + + + + + Tabs + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Vendors + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Banners + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + File Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Log + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Newsletters + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Recycle Bin + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Log Viewer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Input + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Search Results + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Site Wizard + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Account Login + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Feed Explorer + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Extensions + + + + Solutions + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + WhatsNew + + + + Dashboard + + + + Languages + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Skins + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Console + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Google Analytics + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Marketplace + + + + ViewProfile + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Sitemap + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + ContentList + + + + HTML + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + Taxonomy Manager + + + SYSTEM_DESKTOPMODULE + DEPLOY + true + Administrators + + + + + + + GlobalRoles + A dummy role group that represents the Global roles + + + Administrators + Portal Administration + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + adminrole + + + Registered Users + Registered Users + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + true + + + registeredrole + + + Subscribers + A public role for portal subscriptions + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + true + true + + + subscriberrole + + + Translator (en-US) + A role for English (United States) translators + + -1 + -3.402823E+38 + + -1 + -3.402823E+38 + false + false + + + none + + + + + + + Home + true + + + false + + <description /> + <keywords /> + <url type="Normal" /> + <skinsrc /> + <containersrc /> + <startdate>0001-01-01T00:00:00</startdate> + <enddate>0001-01-01T00:00:00</enddate> + <refreshinterval>-1</refreshinterval> + <pageheadtext /> + <issecure>false</issecure> + <permanentredirect>false</permanentredirect> + <sitemappriority>0.5</sitemappriority> + <tabpermissions> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>All Users</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>VIEW</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + <permission> + <permissioncode>SYSTEM_TAB</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </tabpermissions> + <tabsettings> + <tabsetting> + <settingname>CacheIncludeExclude</settingname> + <settingvalue></settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheDuration</settingname> + <settingvalue></settingvalue> + </tabsetting> + <tabsetting> + <settingname>IncludeVaryBy</settingname> + <settingvalue></settingvalue> + </tabsetting> + <tabsetting> + <settingname>CacheProvider</settingname> + <settingvalue></settingvalue> + </tabsetting> + <tabsetting> + <settingname>MaxVaryByCount</settingname> + <settingvalue></settingvalue> + </tabsetting> + <tabsetting> + <settingname>ExcludeVaryBy</settingname> + <settingvalue></settingvalue> + </tabsetting> + </tabsettings> + <tabtype>hometab</tabtype> + <panes> + <pane> + <name>BottomPane</name> + <modules> + <module> + <moduleID>354</moduleID> + <title>DotNetNuke® Community Edition + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 3600 + FileModuleCachingProvider + left + + + + None + + false + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + HtmlText_ReplaceTokens + False + + + WorkflowID + 1 + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + 355 + + <alltabs>false</alltabs> + <inheritviewpermissions>true</inheritviewpermissions> + <header /> + <footer /> + <startdate>0001-01-01T00:00:00</startdate> + <enddate>0001-01-01T00:00:00</enddate> + <cachetime>3600</cachetime> + <cachemethod>FileModuleCachingProvider</cachemethod> + <alignment>left</alignment> + <color /> + <border /> + <iconfile /> + <visibility>None</visibility> + <containersrc /> + <displaytitle>false</displaytitle> + <displayprint>false</displayprint> + <displaysyndicate>false</displaysyndicate> + <iswebslice>false</iswebslice> + <websliceexpirydate>0001-01-01T00:00:00</websliceexpirydate> + <webslicettl>0</webslicettl> + <modulepermissions> + <permission> + <permissioncode>SYSTEM_MODULE_DEFINITION</permissioncode> + <permissionkey>EDIT</permissionkey> + <allowaccess>true</allowaccess> + <rolename>Administrators</rolename> + </permission> + </modulepermissions> + <content type="DNNHTML" version="05.04.03"><![CDATA[<htmltext><content><![CDATA[&lt;div class=&quot;hr&quot;&gt;&lt;hr /&gt; +&lt;/div&gt; +&lt;div id=&quot;LoginInfo&quot;&gt; +&lt;h2 class=&quot;Head&quot;&gt;Getting Started&lt;/h2&gt; +&lt;p&gt;In order to get started, you should login to your site and review the default settings under the &lt;em&gt;Host&amp;gt;Host Settings &lt;/em&gt;menu and the&lt;em&gt; Admin&amp;gt;Site Settings &lt;/em&gt;menu.&amp;nbsp; DotNetNuke is highly configurable and these pages are the first step in customizing your site.&lt;/p&gt; +&lt;p&gt;If your site was installed using the &quot;Auto&quot; option in the installation wizard, a couple of default user accounts were created which will&amp;nbsp;allow you to access the various site management features offered by the application. In this case, please take note of the following user account information:&lt;/p&gt; +&lt;div class=&quot;LoginBlock&quot;&gt; +&lt;h3 class=&quot;NormalBold&quot;&gt;Administrator Login:&lt;/h3&gt; +&lt;dl&gt; + &lt;dt&gt;Username: &lt;/dt&gt; + &lt;dd&gt;admin&lt;br /&gt; + &lt;/dd&gt; + &lt;dt&gt;Password: &lt;/dt&gt; + &lt;dd&gt;dnnadmin &lt;/dd&gt; +&lt;/dl&gt; +&lt;p class=&quot;LoginNotes&quot;&gt;* The Administrator account is a privileged user account which allows you to manage various aspects of your site. Once you login as the Administrator, an Admin menu option will be visible in the site navigation. Please note that the first time you login to the site using this account, you will be prompted to enter a new password for security purposes.&lt;/p&gt; +&lt;/div&gt; +&lt;div class=&quot;LoginBlock&quot;&gt; +&lt;h3 class=&quot;NormalBold&quot;&gt;Host Login:&lt;/h3&gt; +&lt;dl&gt; + &lt;dt&gt;Username: &lt;/dt&gt; + &lt;dd&gt;host&lt;br /&gt; + &lt;/dd&gt; + &lt;dt&gt;Password: &lt;/dt&gt; + &lt;dd&gt;dnnhost &lt;/dd&gt; +&lt;/dl&gt; +&lt;p class=&quot;LoginNotes&quot;&gt;* The Host account is a highly privileged user account which allows you to manage various aspects of your hosting environment. Once you login as the Host, a Host menu option will be visible in the site navigation. Please note that the first time you login to the site using this account, you will be prompted to enter a new password for security purposes.&lt;/p&gt; +&lt;/div&gt; +&lt;/div&gt; +&lt;div id=&quot;RightColumnInfo&quot;&gt; +&lt;div id=&quot;TelerikInside&quot;&gt; +&lt;h2 class=&quot;Head&quot;&gt;Includes Telerik ASP.Net AJAX&lt;/h2&gt; +DotNetNuke now includes Telerik ASP.Net AJAX support. For licensing information on using Telerik within your own modules please refer to the &lt;a href=&quot;Documentation/TELERIK_EULA.pdf&quot; target=&quot;_blank&quot;&gt;Telerik Commercial EULA&lt;/a&gt;.&lt;/div&gt; +&lt;div id=&quot;QuickLinks&quot;&gt; +&lt;h2 class=&quot;Head&quot;&gt;Quick Links&lt;/h2&gt; +&lt;p&gt;The following links provide additional information about using DotNetNuke and some of the people behind the project.&lt;/p&gt; +&lt;ul id=&quot;qlCol1&quot;&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/Products/Development/Forge/tabid/824/Default.aspx&quot; title=&quot;DotNetNuke Forge&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;DotNetNuke Forge&lt;/a&gt; &lt;/li&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/tabid/825/default.aspx&quot; title=&quot;DotNetNuke Project Blogs&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;Project Blogs&lt;/a&gt; &lt;/li&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/Development/LanguagePacks/tabid/933/Default.aspx&quot; title=&quot;Language Packs for DotNetNuke&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;Language Packs&lt;/a&gt; &lt;/li&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/tabid/787/default.aspx&quot; title=&quot;Online Help for DotNetNuke&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;Online Help&lt;/a&gt; &lt;/li&gt; +&lt;/ul&gt; +&lt;ul id=&quot;qlCol2&quot;&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/Community/UserGroupProgram/tabid/1074/Default.aspx&quot; title=&quot;Join or Create a DotNetNuke User Group in your area.&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;Join a User Group&lt;/a&gt; &lt;/li&gt; + &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/Default.aspx&quot; title=&quot;The DotNetNuke Issue Tracking System&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;Issue Tracking&lt;/a&gt; &lt;/li&gt; + &lt;li&gt;&lt;a href=&quot;http://www.dotnetnuke.com/About/Overview/tabid/822/Default.aspx&quot; title=&quot;Creators and maintainers of DotNetNuke.&quot; class=&quot;Normal&quot; target=&quot;_blank&quot;&gt;DotNetNuke Corporation&lt;/a&gt; &lt;/li&gt; +&lt;/ul&gt; +&lt;div style=&quot;clear: both;&quot;&gt;&amp;nbsp;&lt;/div&gt; +&lt;/div&gt; +&lt;/div&gt; +&lt;div class=&quot;hr&quot;&gt;&lt;hr /&gt; +&lt;/div&gt;]]></content></htmltext>]]></content> + <modulesettings> + <modulesetting> + <settingname>HtmlText_ReplaceTokens</settingname> + <settingvalue>False</settingvalue> + </modulesetting> + <modulesetting> + <settingname>WorkflowID</settingname> + <settingvalue>1</settingvalue> + </modulesetting> + </modulesettings> + <tabmodulesettings> + <tabmodulesetting> + <settingname>hideadminborder</settingname> + <settingvalue>False</settingvalue> + </tabmodulesetting> + </tabmodulesettings> + <definition>DNN_HTML</definition> + <moduledefinition>Text/HTML</moduledefinition> + </module> + <module> + <moduleID>356</moduleID> + <title>Sponsors + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 3600 + FileModuleCachingProvider + center + + + + None + + true + false + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + + HtmlText_ReplaceTokens + False + + + WorkflowID + 1 + + + + + hideadminborder + False + + + DNN_HTML + Text/HTML + + + + + + + Search Results + false + + + false + Search Results + + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + 357 + Search Results + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + SearchResults + Search Results + + + 358 + Results + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ContentList + Content List + + + + + + + User Profile + false + + + false + User Profile + + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + All Users + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + usertab + + + ContentPane + + + 359 + My Profile + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + All Users + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + ViewProfile + ViewProfile + + + 360 + My InBox + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Registered Users + + + + + DotNetNuke.Messaging + Messaging + + + + + + + Admin + false + + + false + Portal Administration + + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + + + ContentPane + + + 361 + Basic Features + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + VIEW + true + Administrators + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + ShowTooltip + True + + + DefaultSize + IconFileLarge + + + AllowSizeChange + False + + + ConsoleWidth + + + + DefaultView + Hide + + + AllowViewChange + False + + + + + hideadminborder + True + + + Console + Console + + + + + + + Site Settings + true + ~/images/icon_sitesettings_16px.gif + ~/images/icon_sitesettings_32px.gif + false + Site Settings + Manage configuration settings for the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 362 + Site Settings + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_sitesettings_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Portals + Site Settings + + + + + + + Pages + true + ~/images/icon_tabs_16px.gif + ~/images/icon_tabs_32px.gif + false + Pages + Manage pages within the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 363 + Pages + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_tabs_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Tabs + Tabs + + + + + + + Extensions + true + ~/images/icon_extensions_16px.gif + ~/images/icon_extensions_32px.gif + false + Extensions + Install, add, modify and delete extensions, such as modules, skins and language packs. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 364 + Extensions + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_extensions_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Extensions + Extensions + + + + + + + Languages + true + ~/images/icon_language_16px.gif + ~/images/icon_language_32px.gif + false + Languages + Manage Language Resources. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 365 + Language Management + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_language_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Languages + Languages + + + + + + + Skins + true + ~/images/icon_skins_16px.gif + ~/images/icon_skins_32px.gif + false + Skins + Manage Skin Resources. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 366 + Skin Editor + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_skins_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Skins + Skins + + + 367 + Skin Designer + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_skins_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SkinDesigner + Skin Designer + + + + + + + Security Roles + true + ~/images/icon_securityroles_16px.gif + ~/images/icon_securityroles_32px.gif + false + Security Roles + Manage security roles for the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 368 + Security Roles + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_securityroles_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + Security Roles + + + + + + + User Accounts + true + ~/images/icon_users_16px.gif + ~/images/icon_users_32px.gif + false + User Accounts + Manage user accounts for the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 369 + User Accounts + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_users_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Security + User Accounts + + + + + + + Vendors + true + ~/images/icon_vendors_16px.gif + ~/images/icon_vendors_32px.gif + false + Vendors + Manage vendor accounts, banner advertising and affiliate referrals within the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 370 + Vendors + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_vendors_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Vendors + Vendors + + + + + + + Site Log + true + ~/images/icon_sitelog_16px.gif + ~/images/icon_sitelog_32px.gif + false + Site Log + View statistical reports on site activity for the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 371 + Site Log + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_sitelog_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteLog + Site Log + + + + + + + Newsletters + true + ~/images/icon_bulkmail_16px.gif + ~/images/icon_bulkmail_32px.gif + false + Newsletters + Send email messages to users, security roles and specific email addresses. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 372 + Newsletters + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_bulkmail_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Newsletters + Newsletters + + + + + + + File Manager + true + ~/images/icon_filemanager_16px.gif + ~/images/icon_filemanager_32px.gif + false + File Manager + Manage files within the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 373 + File Manager + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_filemanager_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + FileManager + File Manager + + + + + + + Recycle Bin + true + ~/images/icon_recyclebin_16px.gif + ~/images/icon_recyclebin_32px.gif + false + Recycle Bin + View, restore or permanently recycle pages and modules that have been deleted from the portal. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 374 + Recycle Bin + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_recyclebin_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + RecycleBin + Recycle Bin + + + + + + + Log Viewer + true + ~/images/icon_viewstats_16px.gif + ~/images/icon_viewstats_32px.gif + false + Log Viewer + View a historical log of database events such as event schedules, exceptions, account logins, module and page changes, user account activities, security role activities, etc. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 375 + Log Viewer + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_viewstats_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + LogViewer + Log Viewer + + + + + + + Site Wizard + true + ~/images/icon_wizard_16px.gif + ~/images/icon_wizard_32px.gif + false + Site Wizard + Configure portal settings, page design and apply a site template using a step-by-step wizard. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 376 + Site Wizard + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_wizard_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + SiteWizard + Site Wizard + + + + + + + Google Analytics + true + ~/images/icon_analytics_16px.gif + ~/images/icon_analytics_32px.gif + false + Google Analytics + Configure portal Google Analytics settings. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 377 + Google Analytics + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_analytics_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + GoogleAnalytics + GoogleAnalytics + + + + + + + Taxonomy + true + ~/images/icon_tag_16px.gif + ~/images/icon_tag_32px.gif + false + Taxonomy + Manage the Taxonomy for your Site. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 378 + Taxonomy Manager + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_tag_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + DotNetNuke.Taxonomy + Taxonomy Manager + + + + + + + Search Engine SiteMap + true + ~/images/icon_siteMap_16px.gif + ~/images/icon_siteMap_32px.gif + false + Site Settings + Configure the sitemap for submission to common search engines. + + + + + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + -1 + + false + false + 0.5 + + + SYSTEM_TAB + VIEW + true + Administrators + + + SYSTEM_TAB + EDIT + true + Administrators + + + + Admin + + + ContentPane + + + 379 + Search Engine SiteMap + false + true +
    +
    + 0001-01-01T00:00:00 + 0001-01-01T00:00:00 + 0 + + + + + ~/images/icon_analytics_32px.gif + Maximized + + true + true + false + false + 0001-01-01T00:00:00 + 0 + + + SYSTEM_MODULE_DEFINITION + EDIT + true + Administrators + + + + + + hideadminborder + True + + + Sitemap + Sitemap + + + + + + + + + + 0 + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + + + image/gif + gif + aspnet.gif + 60 + 2965 + 120 + + + image/gif + gif + community_icon.gif + 54 + 1666 + 77 + + + image/gif + gif + community_title.gif + 33 + 2190 + 210 + + + image/gif + gif + conferences_icon.gif + 54 + 1510 + 77 + + + image/gif + gif + conferences_title.gif + 33 + 2630 + 210 + + + application/octet-stream + png + dnn_manuals.png + 137 + 10209 + 316 + + + application/octet-stream + png + dnn_large_banner.png + 428 + 116468 + 900 + + + application/octet-stream + png + connect_btn.png + 26 + 2802 + 118 + + + application/octet-stream + png + engage_btn.png + 26 + 2783 + 118 + + + application/octet-stream + png + learn_btn.png + 26 + 2666 + 118 + + + application/octet-stream + png + shop_btn.png + 26 + 2592 + 118 + + + application/octet-stream + png + dnn_proedition.png + 137 + 13807 + 514 + + + image/gif + gif + exacttarget.gif + 60 + 1001 + 120 + + + image/gif + gif + item_bt_bg.gif + 32 + 1234 + 210 + + + image/gif + gif + itembg.gif + 2 + 225 + 210 + + + image/gif + gif + logo.gif + 86 + 3934 + 279 + + + image/gif + gif + marketplace_icon.gif + 54 + 1606 + 77 + + + image/gif + gif + marketplace_title.gif + 33 + 2626 + 210 + + + image/gif + gif + maximumasp.gif + 60 + 2016 + 120 + + + application/octet-stream + css + portal.css + -1 + 3617 + -1 + + + image/gif + gif + redgate.gif + 60 + 1725 + 120 + + + image/gif + gif + telerik.gif + 60 + 1193 + 120 + + + image/jpeg + jpg + telerikInside.jpg + 171 + 7366 + 340 + + + image/gif + gif + training_icon.gif + 54 + 1693 + 77 + + + image/gif + gif + training_title.gif + 33 + 2100 + 210 + + + image/gif + gif + windowslive.gif + 60 + 3262 + 120 + + + + + Cache/ + 0 + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + + + + Cache/Modules/ + 0 + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + BROWSE + Administrators + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + + + + Templates/ + 0 + + + SYSTEM_FOLDER + READ + Administrators + true + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + BROWSE + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + true + + + + + application/octet-stream + template + Default.page.template + -1 + 1592 + -1 + + + + + Users/ + 0 + + + SYSTEM_FOLDER + READ + Administrators + false + + + SYSTEM_FOLDER + READ + All Users + true + + + SYSTEM_FOLDER + WRITE + Administrators + false + + + SYSTEM_FOLDER + BROWSE + Administrators + false + + + + + + diff --git a/DNN Platform/Library/TemplatesBeta/Default Website.template.resources b/DNN Platform/Library/TemplatesBeta/Default Website.template.resources new file mode 100644 index 00000000000..4ac6e76f13b Binary files /dev/null and b/DNN Platform/Library/TemplatesBeta/Default Website.template.resources differ diff --git a/DNN Platform/Library/UI/Containers/ActionBase.cs b/DNN Platform/Library/UI/Containers/ActionBase.cs new file mode 100644 index 00000000000..262c5adeec1 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionBase.cs @@ -0,0 +1,337 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; + +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionBase + /// ----------------------------------------------------------------------------- + /// + /// ActionBase is an abstract base control for Action objects that inherit from UserControl. + /// + /// + /// ActionBase inherits from UserControl, and implements the IActionControl Interface + /// + /// + /// [cnurse] 10/07/2004 Documented + /// [cnurse] 12/15/2007 Refactored + /// + /// ----------------------------------------------------------------------------- + public abstract class ActionBase : UserControl, IActionControl + { + #region "Private Members" + + private ActionManager _ActionManager; + private ModuleAction _ActionRoot; + + [Obsolete("Obsoleted in DotNetNuke 5.1.2. The concept of an adminControl no longer exists.")] + protected bool m_adminControl; + + [Obsolete("Obsoleted in DotNetNuke 5.1.2. The concept of an adminModule no longer exists.")] + protected bool m_adminModule; + + [Obsolete("Obsoleted in DotNetNuke 5.1.2 Replaced by ActionRoot Property")] + protected ModuleAction m_menuActionRoot; + + [Obsolete("Obsoleted in DotNetNuke 5.1.2. Replaced by Actions Property")] + protected ModuleActionCollection m_menuActions; + + protected bool m_supportsIcons = true; + + [Obsolete("Obsoleted in DotNetNuke 5.1.2. No longer neccessary as there is no concept of an Admin Page")] + protected bool m_tabPreview; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Actions Collection + /// + /// A ModuleActionCollection + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleActionCollection Actions + { + get + { + return ModuleContext.Actions; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionRoot + /// + /// A ModuleActionCollection + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleAction ActionRoot + { + get + { + if (_ActionRoot == null) + { + _ActionRoot = new ModuleAction(ModuleContext.GetNextActionID(), Localization.GetString("Manage.Text", Localization.GlobalResourceFile), string.Empty, string.Empty, "manage-icn.png"); + } + return _ActionRoot; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleContext + /// + /// A ModuleInstanceContext + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleInstanceContext ModuleContext + { + get + { + return ModuleControl.ModuleContext; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PortalSettings + /// + /// A PortalSettings object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected PortalSettings PortalSettings + { + get + { + PortalSettings _settings = ModuleControl.ModuleContext.PortalSettings; + //following If clase left to preserve backwards compatibility + //liable to be removed if related obsolete variable gets removed + if (!_settings.ActiveTab.IsSuperTab) + { +//still maintaining an obsolete type in public interface to maintain binary compatibility +#pragma warning disable 612,618 + m_tabPreview = (_settings.UserMode == PortalSettings.Mode.View); +#pragma warning restore 612,618 + } + return _settings; + } + } + + #endregion + + #region Public Properties + + public bool EditMode + { + get + { + return ModuleContext.PortalSettings.UserMode != PortalSettings.Mode.View; + } + } + + public bool SupportsIcons + { + get + { + return m_supportsIcons; + } + } + + [Obsolete("Obsoleted in DotNetNuke 5.0. Use ModuleContext.Configuration")] + public ModuleInfo ModuleConfiguration + { + get + { + return ModuleContext.Configuration; + } + } + + [Obsolete("Obsoleted in DotNetNuke 5.0. Replaced by ModuleControl")] + public PortalModuleBase PortalModule + { + get + { + return new PortalModuleBase(); + } + set + { + ModuleControl = value; + } + } + + [Obsolete("Obsoleted in DotNetNuke 5.1.2. Replaced by Actions Property")] + public ModuleActionCollection MenuActions + { + get + { + return Actions; + } + } + + #endregion + + #region IActionControl Members + + public event ActionEventHandler Action; + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionManager instance for this Action control + /// + /// An ActionManager object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public ActionManager ActionManager + { + get + { + if (_ActionManager == null) + { + _ActionManager = new ActionManager(this); + } + return _ActionManager; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleControl instance for this Action control + /// + /// An IModuleControl object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl { get; set; } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// DisplayControl determines whether the control should be displayed + /// + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + protected bool DisplayControl(DNNNodeCollection objNodes) + { + return ActionManager.DisplayControl(objNodes); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnAction raises the Action Event for this control + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void OnAction(ActionEventArgs e) + { + if (Action != null) + { + Action(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessAction processes the action event + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected void ProcessAction(string ActionID) + { + int output; + if (Int32.TryParse(ActionID, out output)) + { + ModuleAction action = Actions.GetActionByID(output); + if (action != null) + { + if (!ActionManager.ProcessAction(action)) + { + OnAction(new ActionEventArgs(action, ModuleContext.Configuration)); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the class is loaded + /// + /// + /// + /// + /// [cnurse] 05/12/2005 Documented + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + try + { + ActionRoot.Actions.AddRange(Actions); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + + base.OnLoad(e); + } + + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/ActionButton.cs b/DNN Platform/Library/UI/Containers/ActionButton.cs new file mode 100644 index 00000000000..7d455e18ed9 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionButton.cs @@ -0,0 +1,252 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Entities.Modules.Actions; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionButton + /// ----------------------------------------------------------------------------- + /// + /// ActionButton provides a button (or group of buttons) for action(s). + /// + /// + /// ActionBase inherits from UserControl, and implements the IActionControl Interface. + /// + /// + /// [cnurse] 10/07/2004 Documented + /// [cnurse] 12/15/2007 Deprectaed and Refactored to use ActionButtonList + /// by Containment + /// + /// ----------------------------------------------------------------------------- + [Obsolete("This class has been deprecated in favour of the new ActionCommandButton and ActionButtonList.")] + public class ActionButton : ActionBase + { + private ActionButtonList _ButtonList; + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Command Name + /// + /// + /// Maps to ModuleActionType in DotNetNuke.Entities.Modules.Actions + /// + /// A String + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public string CommandName + { + get + { + EnsureChildControls(); + return _ButtonList.CommandName; + } + set + { + EnsureChildControls(); + _ButtonList.CommandName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the CSS Class + /// + /// + /// Defaults to 'CommandButton' + /// + /// A String + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public string CssClass + { + get + { + EnsureChildControls(); + return _ButtonList.CssClass; + } + set + { + EnsureChildControls(); + _ButtonList.CssClass = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets whether the link is displayed + /// + /// + /// Defaults to True + /// + /// A Boolean + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public bool DisplayLink + { + get + { + EnsureChildControls(); + return _ButtonList.DisplayLink; + } + set + { + EnsureChildControls(); + _ButtonList.DisplayLink = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets whether the icon is displayed + /// + /// + /// Defaults to False + /// + /// A Boolean + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public bool DisplayIcon + { + get + { + EnsureChildControls(); + return _ButtonList.DisplayIcon; + } + set + { + EnsureChildControls(); + _ButtonList.DisplayIcon = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Icon used + /// + /// + /// Defaults to the icon defined in Action + /// + /// A String + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public string IconFile + { + get + { + EnsureChildControls(); + return _ButtonList.ImageURL; + } + set + { + EnsureChildControls(); + _ButtonList.ImageURL = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Separator between Buttons + /// + /// + /// Defaults to 2 non-breaking spaces + /// + /// A String + /// + /// [cnurse] 6/29/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public string ButtonSeparator + { + get + { + EnsureChildControls(); + return _ButtonList.ButtonSeparator; + } + set + { + EnsureChildControls(); + _ButtonList.ButtonSeparator = value; + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Action_Click responds to an Action Event in the contained actionButtonList + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + private void Action_Click(object sender, ActionEventArgs e) + { + ProcessAction(e.Action.ID.ToString()); + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// CreateChildControls builds the control tree + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void CreateChildControls() + { + base.CreateChildControls(); + + _ButtonList = new ActionButtonList(); + _ButtonList.Action += Action_Click; + + Controls.Add(_ButtonList); + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/ActionButtonList.cs b/DNN Platform/Library/UI/Containers/ActionButtonList.cs new file mode 100644 index 00000000000..ad6342112c3 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionButtonList.cs @@ -0,0 +1,296 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionButtonList + /// ----------------------------------------------------------------------------- + /// + /// ActionButtonList provides a list of buttons for a group of actions of the same type. + /// + /// + /// ActionButtonList inherits from CompositeControl, and implements the IActionControl + /// Interface. It uses a single ActionCommandButton for each Action. + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ActionButtonList : CompositeControl, IActionControl + { + #region "Private Members" + + private ActionManager _ActionManager; + private ModuleActionCollection _ModuleActions; + private string _buttonSeparator = "  "; + private string _commandName = ""; + private bool _displayLink = true; + + + #endregion + + #region "Protected Members" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleActionCollection to bind to the list + /// + /// A ModuleActionCollection + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleActionCollection ModuleActions + { + get + { + if (_ModuleActions == null) + { + _ModuleActions = ModuleControl.ModuleContext.Actions.GetActionsByCommandName(CommandName); + } + return _ModuleActions; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Separator between Buttons + /// + /// Defaults to 2 non-breaking spaces + /// A String + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ButtonSeparator + { + get + { + return _buttonSeparator; + } + set + { + _buttonSeparator = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Command Name + /// + /// Maps to ModuleActionType in DotNetNuke.Entities.Modules.Actions + /// A String + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public string CommandName + { + get + { + return _commandName; + } + set + { + _commandName = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets whether the icon is displayed + /// + /// Defaults to False + /// A Boolean + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public bool DisplayIcon { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets whether the link is displayed + /// + /// Defaults to True + /// A Boolean + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public bool DisplayLink + { + get + { + return _displayLink; + } + set + { + _displayLink = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets or sets the Icon used + /// + /// Defaults to the icon defined in Action + /// A String + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ImageURL { get; set; } + + #region IActionControl Members + + public event ActionEventHandler Action; + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionManager instance for this Action control + /// + /// An ActionManager object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public ActionManager ActionManager + { + get + { + if (_ActionManager == null) + { + _ActionManager = new ActionManager(this); + } + return _ActionManager; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleControl instance for this Action control + /// + /// An IModuleControl object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl { get; set; } + + #endregion + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// OnAction raises the Action Event + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void OnAction(ActionEventArgs e) + { + if (Action != null) + { + Action(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OnLoad runs when the control is loaded into the Control Tree + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + foreach (ModuleAction action in ModuleActions) + { + if (action != null && ActionManager.IsVisible(action)) + { + //Create a new ActionCommandButton + var actionButton = new ActionCommandButton(); + + //Set all the properties + actionButton.ModuleAction = action; + actionButton.ModuleControl = ModuleControl; + actionButton.CommandName = CommandName; + actionButton.CssClass = CssClass; + actionButton.DisplayLink = DisplayLink; + actionButton.DisplayIcon = DisplayIcon; + actionButton.ImageUrl = ImageURL; + + //Add a handler for the Action Event + actionButton.Action += ActionButtonClick; + + Controls.Add(actionButton); + + Controls.Add(new LiteralControl(ButtonSeparator)); + } + } + Visible = (Controls.Count > 0); + } + + #endregion + + #region "Event Handlers" + + /// ----------------------------------------------------------------------------- + /// + /// ActionButtonClick handles the Action event of the contained ActionCommandButton(s) + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ActionButtonClick(object sender, ActionEventArgs e) + { + OnAction(e); + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/ActionCommandButton.cs b/DNN Platform/Library/UI/Containers/ActionCommandButton.cs new file mode 100644 index 00000000000..60b12b3ff09 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionCommandButton.cs @@ -0,0 +1,223 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionCommandButton + /// ----------------------------------------------------------------------------- + /// + /// ActionCommandButton provides a button for a single action. + /// + /// + /// ActionBase inherits from CommandButton, and implements the IActionControl Interface. + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ActionCommandButton : CommandButton, IActionControl + { + #region "Private Members" + + private ActionManager _ActionManager; + private ModuleAction _ModuleAction; + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleAction for this Action control + /// + /// A ModuleAction object + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleAction ModuleAction + { + get + { + if (_ModuleAction == null) + { + _ModuleAction = ModuleControl.ModuleContext.Actions.GetActionByCommandName(CommandName); + } + return _ModuleAction; + } + set + { + _ModuleAction = value; + } + } + + #region IActionControl Members + + public event ActionEventHandler Action; + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionManager instance for this Action control + /// + /// An ActionManager object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public ActionManager ActionManager + { + get + { + if (_ActionManager == null) + { + _ActionManager = new ActionManager(this); + } + return _ActionManager; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleControl instance for this Action control + /// + /// An IModuleControl object + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl { get; set; } + + #endregion + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// CreateChildControls builds the control tree + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void CreateChildControls() + { + //Call base class method to ensure Control Tree is built + base.CreateChildControls(); + + //Set Causes Validation and Enables ViewState to false + CausesValidation = false; + EnableViewState = false; + } + + /// ----------------------------------------------------------------------------- + /// + /// OnAction raises the Action Event + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void OnAction(ActionEventArgs e) + { + if (Action != null) + { + Action(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OnButtonClick runs when the underlying CommandButton is clicked + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnButtonClick(EventArgs e) + { + base.OnButtonClick(e); + if (!ActionManager.ProcessAction(ModuleAction)) + { + OnAction(new ActionEventArgs(ModuleAction, ModuleControl.ModuleContext.Configuration)); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OnPreRender runs when just before the Render phase of the Page Lifecycle + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + if (ModuleAction != null && ActionManager.IsVisible(ModuleAction)) + { + Text = ModuleAction.Title; + CommandArgument = ModuleAction.ID.ToString(); + + if (DisplayIcon && (!string.IsNullOrEmpty(ModuleAction.Icon) || !string.IsNullOrEmpty(ImageUrl))) + { + if (!string.IsNullOrEmpty(ImageUrl)) + { + ImageUrl = ModuleControl.ModuleContext.Configuration.ContainerPath.Substring(0, ModuleControl.ModuleContext.Configuration.ContainerPath.LastIndexOf("/") + 1) + ImageUrl; + } + else + { + if (ModuleAction.Icon.IndexOf("/") > Null.NullInteger) + { + ImageUrl = ModuleAction.Icon; + } + else + { + ImageUrl = "~/images/" + ModuleAction.Icon; + } + } + } + ActionManager.GetClientScriptURL(ModuleAction, this); + } + else + { + Visible = false; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/ActionManager.cs b/DNN Platform/Library/UI/Containers/ActionManager.cs new file mode 100644 index 00000000000..345e075b17e --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionManager.cs @@ -0,0 +1,454 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Web; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionManager + /// ----------------------------------------------------------------------------- + /// + /// ActionManager is a helper class that provides common Action Behaviours that can + /// be used by any IActionControl implementation + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ActionManager + { + #region Private Members + + private readonly PortalSettings PortalSettings = PortalController.GetCurrentPortalSettings(); + private readonly HttpRequest Request = HttpContext.Current.Request; + private readonly HttpResponse Response = HttpContext.Current.Response; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new ActionManager + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public ActionManager(IActionControl actionControl) + { + ActionControl = actionControl; + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Action Control that is connected to this ActionManager instance + /// + /// An IActionControl object + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + public IActionControl ActionControl { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleInstanceContext instance that is connected to this ActionManager + /// instance + /// + /// A ModuleInstanceContext object + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleInstanceContext ModuleContext + { + get + { + return ActionControl.ModuleControl.ModuleContext; + } + } + + #endregion + + #region Private Methods + + private void ClearCache(ModuleAction Command) + { + //synchronize cache + ModuleController.SynchronizeModule(ModuleContext.ModuleId); + + //Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + private void Delete(ModuleAction Command) + { + var moduleController = new ModuleController(); + var module = moduleController.GetModule(int.Parse(Command.CommandArgument), ModuleContext.TabId, true); + + //Check if this is the owner instance of a shared module. + var user = UserController.GetCurrentUserInfo(); + var eventLogController = new EventLogController(); + if (!module.IsShared) + { + foreach(ModuleInfo instance in moduleController.GetModuleTabs(module.ModuleID)) + { + if(instance.IsShared) + { + //HARD Delete Shared Instance + moduleController.DeleteTabModule(instance.TabID, instance.ModuleID, false); + eventLogController.AddLog(instance, PortalSettings, user.UserID, "", EventLogController.EventLogType.MODULE_DELETED); + } + } + } + + moduleController.DeleteTabModule(ModuleContext.TabId, int.Parse(Command.CommandArgument), true); + eventLogController.AddLog(module, PortalSettings, user.UserID, "", EventLogController.EventLogType.MODULE_SENT_TO_RECYCLE_BIN); + + //Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + private void DoAction(ModuleAction Command) + { + if (Command.NewWindow) + { + UrlUtils.OpenNewWindow(ActionControl.ModuleControl.Control.Page, GetType(), Command.Url); + } + else + { + Response.Redirect(Command.Url, true); + } + } + + private void Localize(ModuleAction Command) + { + var moduleCtrl = new ModuleController(); + ModuleInfo sourceModule = moduleCtrl.GetModule(ModuleContext.ModuleId, ModuleContext.TabId, false); + + switch (Command.CommandName) + { + case ModuleActionType.LocalizeModule: + moduleCtrl.LocalizeModule(sourceModule, LocaleController.Instance.GetCurrentLocale(ModuleContext.PortalId)); + break; + case ModuleActionType.DeLocalizeModule: + moduleCtrl.DeLocalizeModule(sourceModule); + break; + } + + // Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + private void Translate(ModuleAction Command) + { + var moduleCtrl = new ModuleController(); + ModuleInfo sourceModule = moduleCtrl.GetModule(ModuleContext.ModuleId, ModuleContext.TabId, false); + switch (Command.CommandName) + { + case ModuleActionType.TranslateModule: + moduleCtrl.UpdateTranslationStatus(sourceModule, true); + break; + case ModuleActionType.UnTranslateModule: + moduleCtrl.UpdateTranslationStatus(sourceModule, false); + break; + } + + // Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + private void MoveToPane(ModuleAction Command) + { + var objModules = new ModuleController(); + + objModules.UpdateModuleOrder(ModuleContext.TabId, ModuleContext.ModuleId, -1, Command.CommandArgument); + objModules.UpdateTabModuleOrder(ModuleContext.TabId); + + //Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + private void MoveUpDown(ModuleAction Command) + { + var objModules = new ModuleController(); + switch (Command.CommandName) + { + case ModuleActionType.MoveTop: + objModules.UpdateModuleOrder(ModuleContext.TabId, ModuleContext.ModuleId, 0, Command.CommandArgument); + break; + case ModuleActionType.MoveUp: + objModules.UpdateModuleOrder(ModuleContext.TabId, ModuleContext.ModuleId, ModuleContext.Configuration.ModuleOrder - 3, Command.CommandArgument); + break; + case ModuleActionType.MoveDown: + objModules.UpdateModuleOrder(ModuleContext.TabId, ModuleContext.ModuleId, ModuleContext.Configuration.ModuleOrder + 3, Command.CommandArgument); + break; + case ModuleActionType.MoveBottom: + objModules.UpdateModuleOrder(ModuleContext.TabId, ModuleContext.ModuleId, (ModuleContext.Configuration.PaneModuleCount*2) + 1, Command.CommandArgument); + break; + } + objModules.UpdateTabModuleOrder(ModuleContext.TabId); + + //Redirect to the same page to pick up changes + Response.Redirect(Request.RawUrl, true); + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// DisplayControl determines whether the associated Action control should be + /// displayed + /// + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public bool DisplayControl(DNNNodeCollection objNodes) + { + if (objNodes != null && objNodes.Count > 0 && PortalSettings.UserMode != PortalSettings.Mode.View) + { + DNNNode objRootNode = objNodes[0]; + if (objRootNode.HasNodes && objRootNode.DNNNodes.Count == 0) + { + //if has pending node then display control + return true; + } + else if (objRootNode.DNNNodes.Count > 0) + { + //verify that at least one child is not a break + foreach (DNNNode childNode in objRootNode.DNNNodes) + { + if (!childNode.IsBreak) + { + //Found a child so make Visible + return true; + } + } + } + } + return false; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAction gets the action associated with the commandName + /// + /// The command name + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public ModuleAction GetAction(string commandName) + { + return ActionControl.ModuleControl.ModuleContext.Actions.GetActionByCommandName(commandName); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetAction gets the action associated with the id + /// + /// The Id + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public ModuleAction GetAction(int id) + { + return ActionControl.ModuleControl.ModuleContext.Actions.GetActionByID(id); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetClientScriptURL gets the client script to attach to the control's client + /// side onclick event + /// + /// The Action + /// The Control + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public void GetClientScriptURL(ModuleAction action, WebControl control) + { + if (!String.IsNullOrEmpty(action.ClientScript)) + { + string Script = action.ClientScript; + int JSPos = Script.ToLower().IndexOf("javascript:"); + if (JSPos > -1) + { + Script = Script.Substring(JSPos + 11); + } + string FormatScript = "javascript: return {0};"; + control.Attributes.Add("onClick", string.Format(FormatScript, Script)); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// IsVisible determines whether the action control is Visible + /// + /// The Action + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public bool IsVisible(ModuleAction action) + { + bool _IsVisible = false; + if (action.Visible && ModulePermissionController.HasModuleAccess(action.Secure, Null.NullString, ModuleContext.Configuration)) + { + if ((ModuleContext.PortalSettings.UserMode == PortalSettings.Mode.Edit) || (action.Secure == SecurityAccessLevel.Anonymous || action.Secure == SecurityAccessLevel.View)) + { + _IsVisible = true; + } + else + { + _IsVisible = false; + } + } + else + { + _IsVisible = false; + } + return _IsVisible; + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessAction processes the action + /// + /// The Id of the Action + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public bool ProcessAction(string id) + { + bool bProcessed = true; + int nid = 0; + if (Int32.TryParse(id, out nid)) + { + bProcessed = ProcessAction(ActionControl.ModuleControl.ModuleContext.Actions.GetActionByID(nid)); + } + return bProcessed; + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessAction processes the action + /// + /// The Action + /// + /// [cnurse] 12/23/2007 documented + /// + /// ----------------------------------------------------------------------------- + public bool ProcessAction(ModuleAction action) + { + bool bProcessed = true; + switch (action.CommandName) + { + case ModuleActionType.ModuleHelp: + DoAction(action); + break; + case ModuleActionType.OnlineHelp: + DoAction(action); + break; + case ModuleActionType.ModuleSettings: + DoAction(action); + break; + case ModuleActionType.DeleteModule: + Delete(action); + break; + case ModuleActionType.PrintModule: + case ModuleActionType.SyndicateModule: + DoAction(action); + break; + case ModuleActionType.ClearCache: + ClearCache(action); + break; + case ModuleActionType.MovePane: + MoveToPane(action); + break; + case ModuleActionType.MoveTop: + case ModuleActionType.MoveUp: + case ModuleActionType.MoveDown: + case ModuleActionType.MoveBottom: + MoveUpDown(action); + break; + case ModuleActionType.LocalizeModule: + Localize(action); + break; + case ModuleActionType.DeLocalizeModule: + Localize(action); + break; + case ModuleActionType.TranslateModule: + Translate(action); + break; + case ModuleActionType.UnTranslateModule: + Translate(action); + break; + default: //custom action + if (!String.IsNullOrEmpty(action.Url) && action.UseActionEvent == false) + { + DoAction(action); + } + else + { + bProcessed = false; + } + break; + } + return bProcessed; + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/ActionsMenu.cs b/DNN Platform/Library/UI/Containers/ActionsMenu.cs new file mode 100644 index 00000000000..8913e1d7f22 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/ActionsMenu.cs @@ -0,0 +1,449 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Text.RegularExpressions; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Modules.NavigationProvider; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : ActionsMenu + /// ----------------------------------------------------------------------------- + /// + /// ActionsMenu provides a menu for a collection of actions. + /// + /// + /// ActionsMenu inherits from CompositeControl, and implements the IActionControl + /// Interface. It uses the Navigation Providers to implement the Menu. + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ActionsMenu : Control, IActionControl + { + #region "Private Members" + + private ActionManager _ActionManager; + private ModuleAction _ActionRoot; + private int _ExpandDepth = -1; + private NavigationProvider _ProviderControl; + private string _ProviderName = "DNNMenuNavigationProvider"; + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionRoot + /// + /// A ModuleActionCollection + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + protected ModuleAction ActionRoot + { + get + { + if (_ActionRoot == null) + { + _ActionRoot = new ModuleAction(ModuleControl.ModuleContext.GetNextActionID(), " ", "", "", "action.gif"); + } + return _ActionRoot; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Provider Control + /// + /// A NavigationProvider + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + protected NavigationProvider ProviderControl + { + get + { + return _ProviderControl; + } + } + + #endregion + + #region "Public Properties" + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Expansion Depth for the Control + /// + /// An Integer + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public int ExpandDepth + { + get + { + if (PopulateNodesFromClient == false || ProviderControl.SupportsPopulateOnDemand == false) + { + return -1; + } + return _ExpandDepth; + } + set + { + _ExpandDepth = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Path to the Script Library for the provider + /// + /// A String + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string PathSystemScript { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets whether the Menu should be populated from the client + /// + /// A Boolean + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public bool PopulateNodesFromClient { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and Sets the Name of the provider to use + /// + /// A String + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ProviderName + { + get + { + return _ProviderName; + } + set + { + _ProviderName = value; + } + } + + #region IActionControl Members + + public event ActionEventHandler Action; + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ActionManager instance for this Action control + /// + /// An ActionManager object + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public ActionManager ActionManager + { + get + { + if (_ActionManager == null) + { + _ActionManager = new ActionManager(this); + } + return _ActionManager; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleControl instance for this Action control + /// + /// An IModuleControl object + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl { get; set; } + + #endregion + + #endregion + + #region "Private Methods" + + + /// ----------------------------------------------------------------------------- + /// + /// BindMenu binds the Navigation Provider to the Node Collection + /// + /// The Nodes collection to bind + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void BindMenu(DNNNodeCollection objNodes) + { + Visible = ActionManager.DisplayControl(objNodes); + if (Visible) + { + //since we always bind we need to clear the nodes for providers that maintain their state + ProviderControl.ClearNodes(); + foreach (DNNNode objNode in objNodes) + { + ProcessNodes(objNode); + } + ProviderControl.Bind(objNodes); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessNodes proceses a single node and its children + /// + /// The Node to process + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ProcessNodes(DNNNode objParent) + { + if (!String.IsNullOrEmpty(objParent.JSFunction)) + { + objParent.JSFunction = string.Format("if({0}){{{1}}};", objParent.JSFunction, Page.ClientScript.GetPostBackEventReference(ProviderControl.NavigationControl, objParent.ID)); + } + foreach (DNNNode objNode in objParent.DNNNodes) + { + ProcessNodes(objNode); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// SetMenuDefaults sets up the default values + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void SetMenuDefaults() + { + try + { + //--- original page set attributes --- + ProviderControl.StyleIconWidth = 15; + ProviderControl.MouseOutHideDelay = 500; + ProviderControl.MouseOverAction = NavigationProvider.HoverAction.Expand; + ProviderControl.MouseOverDisplay = NavigationProvider.HoverDisplay.None; + + //style sheet settings + ProviderControl.CSSControl = "ModuleTitle_MenuBar"; + ProviderControl.CSSContainerRoot = "ModuleTitle_MenuContainer"; + ProviderControl.CSSNode = "ModuleTitle_MenuItem"; + ProviderControl.CSSIcon = "ModuleTitle_MenuIcon"; + ProviderControl.CSSContainerSub = "ModuleTitle_SubMenu"; + ProviderControl.CSSBreak = "ModuleTitle_MenuBreak"; + ProviderControl.CSSNodeHover = "ModuleTitle_MenuItemSel"; + ProviderControl.CSSIndicateChildSub = "ModuleTitle_MenuArrow"; + ProviderControl.CSSIndicateChildRoot = "ModuleTitle_RootMenuArrow"; + + //generate dynamic menu + if (String.IsNullOrEmpty(ProviderControl.PathSystemScript)) + { + ProviderControl.PathSystemScript = Globals.ApplicationPath + "/Controls/SolpartMenu/"; + } + ProviderControl.PathImage = Globals.ApplicationPath + "/Images/"; + ProviderControl.PathSystemImage = Globals.ApplicationPath + "/Images/"; + ProviderControl.IndicateChildImageSub = "action_right.gif"; + ProviderControl.IndicateChildren = true; + ProviderControl.StyleRoot = "background-color: Transparent; font-size: 1pt;"; + ProviderControl.NodeClick += MenuItem_Click; + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// BindMenu binds the Navigation Provider to the Node Collection + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + protected void BindMenu() + { + BindMenu(Navigation.GetActionNodes(ActionRoot, this, ExpandDepth)); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnAction raises the Action Event + /// + /// + /// [cnurse] 12/23/2007 created + /// + /// ----------------------------------------------------------------------------- + protected virtual void OnAction(ActionEventArgs e) + { + if (Action != null) + { + Action(this, e); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OnInit runs during the controls initialisation phase + /// + /// + /// [cnurse] 01/02/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnInit(EventArgs e) + { + _ProviderControl = NavigationProvider.Instance(ProviderName); + ProviderControl.PopulateOnDemand += ProviderControl_PopulateOnDemand; + base.OnInit(e); + ProviderControl.ControlID = "ctl" + ID; + ProviderControl.Initialize(); + Controls.Add(ProviderControl.NavigationControl); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnLoad runs during the controls load phase + /// + /// + /// [cnurse] 01/02/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + //Add the Actions to the Action Root + ActionRoot.Actions.AddRange(ModuleControl.ModuleContext.Actions); + + //Set Menu Defaults + SetMenuDefaults(); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnPreRender runs during the controls pre-render phase + /// + /// + /// [cnurse] 01/02/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + BindMenu(); + } + + #endregion + + #region "Event Handlers" + + /// ----------------------------------------------------------------------------- + /// + /// MenuItem_Click handles the Menu Click event + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void MenuItem_Click(NavigationEventArgs args) + { + if (Regex.IsMatch(args.ID, "^\\d+$")) + { + ModuleAction action = ModuleControl.ModuleContext.Actions.GetActionByID(Convert.ToInt32(args.ID)); + if (!ActionManager.ProcessAction(action)) + { + OnAction(new ActionEventArgs(action, ModuleControl.ModuleContext.Configuration)); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProviderControl_PopulateOnDemand handles the Populate On Demand Event + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + private void ProviderControl_PopulateOnDemand(NavigationEventArgs args) + { + SetMenuDefaults(); + ActionRoot.Actions.AddRange(ModuleControl.ModuleContext.Actions); //Modules how add custom actions in control lifecycle will not have those actions populated... + + ModuleAction objAction = ActionRoot; + if (ActionRoot.ID != Convert.ToInt32(args.ID)) + { + objAction = ModuleControl.ModuleContext.Actions.GetActionByID(Convert.ToInt32(args.ID)); + } + if (args.Node == null) + { + args.Node = Navigation.GetActionNode(args.ID, ProviderControl.ID, objAction, this); + } + ProviderControl.ClearNodes(); //since we always bind we need to clear the nodes for providers that maintain their state + BindMenu(Navigation.GetActionNodes(objAction, args.Node, this, ExpandDepth)); + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/Container.cs b/DNN Platform/Library/UI/Containers/Container.cs new file mode 100644 index 00000000000..c48619806d1 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/Container.cs @@ -0,0 +1,667 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Linq; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Application; +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Framework; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Containers.EventListeners; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.Skins; +using DotNetNuke.UI.WebControls; +using DotNetNuke.Web.Client.ClientResourceManagement; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + using Web.Client; + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : Container + /// ----------------------------------------------------------------------------- + /// + /// Container is the base for the Containers + /// + /// + /// + /// + /// [cnurse] 07/04/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public class Container : UserControl + { + #region Private Members + + private HtmlContainerControl _contentPane; + private ModuleInfo _moduleConfiguration; + private ModuleHost _moduleHost; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Content Pane Control (Id="ContentPane") + /// + /// An HtmlContainerControl + /// + /// [cnurse] 12/05/2007 created + /// + /// ----------------------------------------------------------------------------- + protected HtmlContainerControl ContentPane + { + get + { + return _contentPane ?? (_contentPane = FindControl(Globals.glbDefaultPane) as HtmlContainerControl); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Portal Settings for the current Portal + /// + /// A PortalSettings object + /// + /// [cnurse] 12/05/2007 created + /// + /// ----------------------------------------------------------------------------- + protected PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleControl object that this container is displaying + /// + /// A ModuleHost object + /// + /// [cnurse] 01/12/2009 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl + { + get + { + IModuleControl moduleControl = null; + if (ModuleHost != null) + { + moduleControl = ModuleHost.ModuleControl; + } + return moduleControl; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the ModuleInfo object that this container is displaying + /// + /// A ModuleInfo object + /// + /// [cnurse] 12/05/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo ModuleConfiguration + { + get + { + return _moduleConfiguration; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleHost object that this container is displaying + /// + /// A ModuleHost object + /// + /// [cnurse] 01/12/2009 created + /// + /// ----------------------------------------------------------------------------- + public ModuleHost ModuleHost + { + get + { + return _moduleHost; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Parent Container for this container + /// + /// A String + /// + /// [cnurse] 12/05/2007 documented + /// + /// ----------------------------------------------------------------------------- + public Skins.Skin ParentSkin + { + get + { + //This finds a reference to the containing skin + return Skins.Skin.GetParentSkin(this); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this container + /// + /// A String + /// + /// [cnurse] 12/05/2007 documented + /// + /// ----------------------------------------------------------------------------- + public string ContainerPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Source for this container + /// + /// A String + /// + /// [cnurse] 06/10/2009 documented + /// + /// ----------------------------------------------------------------------------- + public string ContainerSrc { get; set; } + + [Obsolete("Deprecated in 5.1. Replaced by ContainerPath")] + public string SkinPath + { + get + { + return ContainerPath; + } + } + + internal bool InjectActionMenu { get; set; } + + #endregion + + #region Private Helper Methods + + private void AddAdministratorOnlyHighlighting(string message) + { + ContentPane.Controls.Add(new LiteralControl(string.Format("
    {0}
    ", message))); + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessChildControls parses all the controls in the container, and if the + /// control is an action (IActionControl) it attaches the ModuleControl (IModuleControl) + /// and an EventHandler to respond to the Actions Action event. If the control is a + /// Container Object (IContainerControl) it attaches the ModuleControl. + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void ProcessChildControls(Control control) + { + IActionControl actions; + ISkinControl skinControl; + foreach (Control childControl in control.Controls) + { + //check if control is an action control + actions = childControl as IActionControl; + if (actions != null) + { + actions.ModuleControl = ModuleControl; + actions.Action += ModuleActionClick; + } + + //check if control is an actionLink control + var actionLink = childControl as ActionLink; + if (actionLink != null) + { + actionLink.ModuleControl = ModuleControl; + } + + //check if control is a skin control + skinControl = childControl as ISkinControl; + if (skinControl != null) + { + skinControl.ModuleControl = ModuleControl; + } + if (childControl.HasControls()) + { + //recursive call for child controls + ProcessChildControls(childControl); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessContentPane processes the ContentPane, setting its style and other + /// attributes. + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void ProcessContentPane() + { + SetAlignment(); + + SetBackground(); + + SetBorder(); + + //display visual indicator if module is only visible to administrators + string viewRoles = ModuleConfiguration.InheritViewPermissions + ? TabPermissionController.GetTabPermissions(ModuleConfiguration.TabID, ModuleConfiguration.PortalID).ToString("VIEW") + : ModuleConfiguration.ModulePermissions.ToString("VIEW"); + + string pageEditRoles = TabPermissionController.GetTabPermissions(ModuleConfiguration.TabID, ModuleConfiguration.PortalID).ToString("EDIT"); + string moduleEditRoles = ModuleConfiguration.ModulePermissions.ToString("EDIT"); + + viewRoles = viewRoles.Replace(";", string.Empty).Trim().ToLowerInvariant(); + pageEditRoles = pageEditRoles.Replace(";", string.Empty).Trim().ToLowerInvariant(); + moduleEditRoles = moduleEditRoles.Replace(";", string.Empty).Trim().ToLowerInvariant(); + + var showMessage = false; + var adminMessage = Null.NullString; + if (viewRoles == PortalSettings.AdministratorRoleName.ToLowerInvariant() + && (moduleEditRoles == PortalSettings.AdministratorRoleName.ToLowerInvariant() + || String.IsNullOrEmpty(moduleEditRoles)) + && pageEditRoles == PortalSettings.AdministratorRoleName.ToLowerInvariant()) + { + adminMessage = Localization.GetString("ModuleVisibleAdministrator.Text"); + showMessage = !ModuleConfiguration.HideAdminBorder && !Globals.IsAdminControl(); + } + if (ModuleConfiguration.StartDate >= DateTime.Now) + { + adminMessage = string.Format(Localization.GetString("ModuleEffective.Text"), ModuleConfiguration.StartDate); + showMessage = !Globals.IsAdminControl(); + } + if (ModuleConfiguration.EndDate <= DateTime.Now) + { + adminMessage = string.Format(Localization.GetString("ModuleExpired.Text"), ModuleConfiguration.EndDate); + showMessage = !Globals.IsAdminControl(); + } + if (showMessage) + { + AddAdministratorOnlyHighlighting(adminMessage); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessFooter adds an optional footer (and an End_Module comment).. + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void ProcessFooter() + { + //inject the footer + if (!String.IsNullOrEmpty(ModuleConfiguration.Footer)) + { + var footer = new Literal {Text = ModuleConfiguration.Footer}; + ContentPane.Controls.Add(footer); + } + + //inject an end comment around the module content + if (!Globals.IsAdminControl()) + { + ContentPane.Controls.Add(new LiteralControl("")); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessHeader adds an optional header (and a Start_Module_ comment).. + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void ProcessHeader() + { + if (!Globals.IsAdminControl()) + { + //inject a start comment around the module content + ContentPane.Controls.Add(new LiteralControl("")); + } + + //inject the header + if (!String.IsNullOrEmpty(ModuleConfiguration.Header)) + { + var header = new Literal {Text = ModuleConfiguration.Header}; + ContentPane.Controls.Add(header); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessModule processes the module which is attached to this container + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void ProcessModule() + { + if (ContentPane != null) + { + //Process Content Pane Attributes + ProcessContentPane(); + + // always add the actions menu as the first item in the content pane. + if (InjectActionMenu && !ModuleHost.IsViewMode(ModuleConfiguration, PortalSettings) && Request.QueryString["dnnprintmode"] != "true") + { + ContentPane.Controls.Add(LoadControl("~/admin/Menus/ModuleActions/ModuleActions.ascx")); + + //register admin.css + ClientResourceManager.RegisterAdminStylesheet(Page, Globals.HostPath + "admin.css"); + } + + //Process Module Header + ProcessHeader(); + + //Try to load the module control + _moduleHost = new ModuleHost(ModuleConfiguration, ParentSkin, this); + ContentPane.Controls.Add(ModuleHost); + + //Process Module Footer + ProcessFooter(); + + //Process the Action Controls + if (ModuleHost != null && ModuleControl != null) + { + ProcessChildControls(this); + } + + //Add Module Stylesheets + ProcessStylesheets(ModuleHost != null); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessStylesheets processes the Module and Container stylesheets and adds + /// them to the Page. + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + + private void ProcessStylesheets(bool includeModuleCss) + { + ClientResourceManager.RegisterStyleSheet(Page, ContainerPath + "container.css", FileOrder.Css.ContainerCss); + ClientResourceManager.RegisterStyleSheet(Page, ContainerSrc.Replace(".ascx", ".css"), FileOrder.Css.SpecificContainerCss); + + //process the base class module properties + if (includeModuleCss) + { + string controlSrc = ModuleConfiguration.ModuleControl.ControlSrc; + string folderName = ModuleConfiguration.DesktopModule.FolderName; + + if (String.IsNullOrEmpty(folderName)==false) + { + ClientResourceManager.RegisterStyleSheet(Page, Globals.ApplicationPath + "/DesktopModules/" + folderName.Replace("\\", "/") + "/module.css", FileOrder.Css.ModuleCss); + } + + if (controlSrc.LastIndexOf("/") > 0) + { + ClientResourceManager.RegisterStyleSheet(Page, Globals.ApplicationPath + "/" + controlSrc.Substring(0, controlSrc.LastIndexOf("/") + 1) + "module.css", FileOrder.Css.ModuleCss); + } + } + } + + private void SetAlignment() + { + if (!String.IsNullOrEmpty(ModuleConfiguration.Alignment)) + { + if (ContentPane.Attributes["class"] != null) + { + ContentPane.Attributes["class"] = ContentPane.Attributes["class"] + " DNNAlign" + ModuleConfiguration.Alignment.ToLower(); + } + else + { + ContentPane.Attributes["class"] = "DNNAlign" + ModuleConfiguration.Alignment.ToLower(); + } + } + } + + private void SetBackground() + { + if (!String.IsNullOrEmpty(ModuleConfiguration.Color)) + { + ContentPane.Style["background-color"] = ModuleConfiguration.Color; + } + } + + private void SetBorder() + { + if (!String.IsNullOrEmpty(ModuleConfiguration.Border)) + { + ContentPane.Style["border-top"] = String.Format("{0}px #000000 solid", ModuleConfiguration.Border); + ContentPane.Style["border-bottom"] = String.Format("{0}px #000000 solid", ModuleConfiguration.Border); + ContentPane.Style["border-right"] = String.Format("{0}px #000000 solid", ModuleConfiguration.Border); + ContentPane.Style["border-left"] = String.Format("{0}px #000000 solid", ModuleConfiguration.Border); + } + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// OnInit runs when the Container is initialised. + /// + /// + /// [cnurse] 07/04/2005 Documented + /// [cnurse] 12/05/2007 Refactored + /// [cnurse] 04/17/2009 Refactored to use ContainerAdapter + /// + /// ----------------------------------------------------------------------------- + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + InvokeContainerEvents(ContainerEventType.OnContainerInit); + } + + /// + /// OnLoad runs when the Container is loaded. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + + InvokeContainerEvents(ContainerEventType.OnContainerLoad); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnLoad runs just before the Container is rendered. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + InvokeContainerEvents(ContainerEventType.OnContainerPreRender); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnUnLoad runs when the Container is unloaded. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnUnload(EventArgs e) + { + base.OnUnload(e); + + InvokeContainerEvents(ContainerEventType.OnContainerUnLoad); + } + + private void InvokeContainerEvents(ContainerEventType containerEventType) + { + SharedList list = ((NaiveLockingList)DotNetNukeContext.Current.ContainerEventListeners).SharedList; + + using (list.GetReadLock()) + { + foreach (var listener in list.Where(x => x.EventType == containerEventType)) + { + listener.ContainerEvent.Invoke(this, new ContainerEventArgs(this)); + } + } + } + + #endregion + + #region Public Methods + + public void SetModuleConfiguration(ModuleInfo configuration) + { + _moduleConfiguration = configuration; + ProcessModule(); + } + + #endregion + + #region Event Handlers + + /// ----------------------------------------------------------------------------- + /// + /// ModuleAction_Click runs when a ModuleAction is clicked. + /// + /// The Module Action must be configured to fire an event (it may be configured + /// to redirect to a new url). The event handler finds the Parent Container and invokes each + /// registered ModuleActionEventListener delegate. + /// + /// Note: with the refactoring of this to the Container, this could be handled at the container level. + /// However, for legacy purposes this is left this way, as many moodules would have registered their + /// listeners on the Container directly, rather than through the helper method in PortalModuleBase. + /// + /// [cnurse] 07/04/2005 Documented + /// [cnurse] 12/05/2007 Moved from Container.vb + /// + /// ----------------------------------------------------------------------------- + private void ModuleActionClick(object sender, ActionEventArgs e) + { + //Search through the listeners + foreach (ModuleActionEventListener listener in ParentSkin.ActionEventListeners) + { + //If the associated module has registered a listener + if (e.ModuleConfiguration.ModuleID == listener.ModuleID) + { + //Invoke the listener to handle the ModuleAction_Click event + listener.ActionEvent.Invoke(sender, e); + } + } + } + + #endregion + + #region Obsolete + + [Obsolete("Deprecated in 5.0. Shouldn't need to be used any more. ContainerObjects (IContainerControl implementations) have a property ModuleControl.")] + public static PortalModuleBase GetPortalModuleBase(UserControl control) + { + PortalModuleBase moduleControl = null; + Panel panel; + if (control is SkinObjectBase) + { + panel = (Panel) control.Parent.FindControl("ModuleContent"); + } + else + { + panel = (Panel) control.FindControl("ModuleContent"); + } + if (panel != null) + { + try + { + moduleControl = (PortalModuleBase) panel.Controls[1]; + } + catch + { + //check if it is nested within an UpdatePanel + try + { + moduleControl = (PortalModuleBase) panel.Controls[0].Controls[0].Controls[1]; + } + catch (Exception exc) + { + Exceptions.LogException(exc); + } + } + } + return moduleControl ?? (new PortalModuleBase {ModuleConfiguration = new ModuleInfo()}); + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventArgs.cs b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventArgs.cs new file mode 100644 index 00000000000..9255cbf76bd --- /dev/null +++ b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventArgs.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.UI.Containers.EventListeners +{ + ///----------------------------------------------------------------------------- + /// + /// ContainerEventArgs provides a custom EventARgs class for Container Events + /// + /// + /// + /// [cnurse] 05/20/2009 Created + /// + ///----------------------------------------------------------------------------- + public class ContainerEventArgs : EventArgs + { + private readonly Container _Container; + + public ContainerEventArgs(Container container) + { + _Container = container; + } + + public Container Container + { + get + { + return _Container; + } + } + } +} diff --git a/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventHandler.cs b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventHandler.cs new file mode 100644 index 00000000000..c5168d4c384 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventHandler.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Containers.EventListeners +{ + /// ----------------------------------------------------------------------------- + /// + /// The ContainerEventHandler delegate defines a custom event handler for a Container + /// Event. + /// + /// + /// [cnurse] 05/19/2009 Created + /// + /// ----------------------------------------------------------------------------- + public delegate void ContainerEventHandler(object sender, ContainerEventArgs e); +} diff --git a/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventListener.cs b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventListener.cs new file mode 100644 index 00000000000..92331a22f99 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventListener.cs @@ -0,0 +1,50 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Containers.EventListeners +{ + public class ContainerEventListener + { + private readonly ContainerEventHandler _ContainerEvent; + private readonly ContainerEventType _Type; + + public ContainerEventListener(ContainerEventType type, ContainerEventHandler e) + { + _Type = type; + _ContainerEvent = e; + } + + public ContainerEventType EventType + { + get + { + return _Type; + } + } + + public ContainerEventHandler ContainerEvent + { + get + { + return _ContainerEvent; + } + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventType.cs b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventType.cs new file mode 100644 index 00000000000..91405536f55 --- /dev/null +++ b/DNN Platform/Library/UI/Containers/EventListeners/ContainerEventType.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Containers.EventListeners +{ + ///----------------------------------------------------------------------------- + /// + /// ContainerEventType provides a custom enum for Container event types + /// + /// + /// + /// [cnurse] 05/19/2009 Created + /// + ///----------------------------------------------------------------------------- + public enum ContainerEventType + { + OnContainerInit, + OnContainerLoad, + OnContainerPreRender, + OnContainerUnLoad + } +} diff --git a/DNN Platform/Library/UI/Containers/IActionControl.cs b/DNN Platform/Library/UI/Containers/IActionControl.cs new file mode 100644 index 00000000000..ad9b14d8bae --- /dev/null +++ b/DNN Platform/Library/UI/Containers/IActionControl.cs @@ -0,0 +1,48 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.UI.Containers +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Containers + /// Class : IActionControl + /// ----------------------------------------------------------------------------- + /// + /// IActionControl provides a common INterface for Action Controls + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public interface IActionControl + { + ActionManager ActionManager { get; } + IModuleControl ModuleControl { get; set; } + event ActionEventHandler Action; + } +} diff --git a/DNN Platform/Library/UI/ControlPanels/ControlPanelBase.cs b/DNN Platform/Library/UI/ControlPanels/ControlPanelBase.cs new file mode 100644 index 00000000000..b3a1d796c42 --- /dev/null +++ b/DNN Platform/Library/UI/ControlPanels/ControlPanelBase.cs @@ -0,0 +1,563 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Personalization; + +#endregion + +namespace DotNetNuke.UI.ControlPanels +{ + /// ----------------------------------------------------------------------------- + /// + /// The ControlPanel class defines a custom base class inherited by all + /// ControlPanel controls. + /// + /// + /// + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + public class ControlPanelBase : UserControl + { + #region Private Members + + private string _localResourceFile; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the ControlPanel is Visible + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected bool IsVisible + { + get + { + return PortalSettings.ControlPanelVisible; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the current Portal Settings + /// + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the User mode of the Control Panel + /// + /// A Boolean + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected PortalSettings.Mode UserMode + { + get + { + return PortalSettings.UserMode; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Local ResourceFile for the Control Panel + /// + /// A String + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + public string LocalResourceFile + { + get + { + string fileRoot; + if (String.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = TemplateSourceDirectory + "/" + Localization.LocalResourceDirectory + "/" + ID; + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + + public virtual bool IncludeInControlHierarchy + { + get { return true; } + } + + public virtual bool IsDockable + { + get { return false; } + set { } + } + + [Obsolete("Deprecated in 5.0. Replaced By UserMode.")] + protected bool ShowContent + { + get + { + return PortalSettings.UserMode != PortalSettings.Mode.Layout; + } + } + + [Obsolete("Deprecated in 5.0. Replaced By UserMode.")] + protected bool IsPreview + { + get + { + if (PortalSettings.UserMode == PortalSettings.Mode.Edit) + { + return false; + } + return true; + } + } + + #endregion + + #region Protected Methods + + protected bool IsModuleAdmin() + { + bool _IsModuleAdmin = Null.NullBoolean; + foreach (ModuleInfo objModule in TabController.CurrentPage.Modules) + { + if (!objModule.IsDeleted) + { + bool blnHasModuleEditPermissions = ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, Null.NullString, objModule); + if (blnHasModuleEditPermissions && objModule.ModuleDefinition.DefaultCacheTime != -1) + { + _IsModuleAdmin = true; + break; + } + } + } + return PortalSettings.ControlPanelSecurity == PortalSettings.ControlPanelPermission.ModuleEditor && _IsModuleAdmin; + } + + protected bool IsPageAdmin() + { + bool _IsPageAdmin = Null.NullBoolean; + if (TabPermissionController.CanAddContentToPage() || TabPermissionController.CanAddPage() || TabPermissionController.CanAdminPage() || TabPermissionController.CanCopyPage() || + TabPermissionController.CanDeletePage() || TabPermissionController.CanExportPage() || TabPermissionController.CanImportPage() || TabPermissionController.CanManagePage()) + { + _IsPageAdmin = true; + } + return _IsPageAdmin; + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// Adds a Module Permission + /// + /// Module Info + /// The permission to add + /// The Id of the role to add the permission for. + /// Operator + /// Whether allow to access the module + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + private ModulePermissionInfo AddModulePermission(ModuleInfo objModule, PermissionInfo permission, int roleId, int userId, bool allowAccess) + { + var objModulePermission = new ModulePermissionInfo(); + objModulePermission.ModuleID = objModule.ModuleID; + objModulePermission.PermissionID = permission.PermissionID; + objModulePermission.RoleID = roleId; + objModulePermission.UserID = userId; + objModulePermission.PermissionKey = permission.PermissionKey; + objModulePermission.AllowAccess = allowAccess; + + //add the permission to the collection + if (!objModule.ModulePermissions.Contains(objModulePermission)) + { + objModule.ModulePermissions.Add(objModulePermission); + } + return objModulePermission; + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// Adds an Existing Module to a Pane + /// + /// The alignment for the Modue + /// The Id of the existing module + /// The id of the tab + /// The pane to add the module to + /// The relative position within the pane for the module + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected void AddExistingModule(int moduleId, int tabId, string paneName, int position, string align) + { + var objModules = new ModuleController(); + ModuleInfo objModule; + var objEventLog = new EventLogController(); + + int UserId = -1; + if (Request.IsAuthenticated) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + UserId = objUserInfo.UserID; + } + objModule = objModules.GetModule(moduleId, tabId, false); + if (objModule != null) + { + //clone the module object ( to avoid creating an object reference to the data cache ) + ModuleInfo objClone = objModule.Clone(); + objClone.TabID = PortalSettings.ActiveTab.TabID; + objClone.ModuleOrder = position; + objClone.PaneName = paneName; + objClone.Alignment = align; + objModules.AddModule(objClone); + objEventLog.AddLog(objClone, PortalSettings, UserId, "", EventLogController.EventLogType.MODULE_CREATED); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Adds a New Module to a Pane + /// + /// The alignment for the Modue + /// The Id of the DesktopModule + /// The View Permission Type for the Module + /// The Title for the resulting module + /// The pane to add the module to + /// The relative position within the pane for the module + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected void AddNewModule(string title, int desktopModuleId, string paneName, int position, ViewPermissionType permissionType, string align) + { + TabPermissionCollection objTabPermissions = PortalSettings.ActiveTab.TabPermissions; + var objPermissionController = new PermissionController(); + var objModules = new ModuleController(); + try + { + DesktopModuleInfo desktopModule; + if (!DesktopModuleController.GetDesktopModules(PortalSettings.PortalId).TryGetValue(desktopModuleId, out desktopModule)) + { + throw new ArgumentException("desktopModuleId"); + } + } + catch (Exception ex) + { + Exceptions.LogException(ex); + } + int UserId = -1; + if (Request.IsAuthenticated) + { + UserInfo objUserInfo = UserController.GetCurrentUserInfo(); + UserId = objUserInfo.UserID; + } + foreach (ModuleDefinitionInfo objModuleDefinition in + ModuleDefinitionController.GetModuleDefinitionsByDesktopModuleID(desktopModuleId).Values) + { + var objModule = new ModuleInfo(); + objModule.Initialize(PortalSettings.PortalId); + objModule.PortalID = PortalSettings.PortalId; + objModule.TabID = PortalSettings.ActiveTab.TabID; + objModule.ModuleOrder = position; + if (String.IsNullOrEmpty(title)) + { + objModule.ModuleTitle = objModuleDefinition.FriendlyName; + } + else + { + objModule.ModuleTitle = title; + } + objModule.PaneName = paneName; + objModule.ModuleDefID = objModuleDefinition.ModuleDefID; + if (objModuleDefinition.DefaultCacheTime > 0) + { + objModule.CacheTime = objModuleDefinition.DefaultCacheTime; + if (PortalSettings.Current.DefaultModuleId > Null.NullInteger && PortalSettings.Current.DefaultTabId > Null.NullInteger) + { + ModuleInfo defaultModule = objModules.GetModule(PortalSettings.Current.DefaultModuleId, PortalSettings.Current.DefaultTabId, true); + if (defaultModule != null) + { + objModule.CacheTime = defaultModule.CacheTime; + } + } + } + switch (permissionType) + { + case ViewPermissionType.View: + objModule.InheritViewPermissions = true; + break; + case ViewPermissionType.Edit: + objModule.InheritViewPermissions = false; + break; + } + + //get the default module view permissions + ArrayList arrSystemModuleViewPermissions = objPermissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", "VIEW"); + + //get the permissions from the page + foreach (TabPermissionInfo objTabPermission in objTabPermissions) + { + if (objTabPermission.PermissionKey == "VIEW" && permissionType == ViewPermissionType.View) + { + //Don't need to explicitly add View permisisons if "Same As Page" + continue; + } + + //get the system module permissions for the permissionkey + ArrayList arrSystemModulePermissions = objPermissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", objTabPermission.PermissionKey); + //loop through the system module permissions + int j; + for (j = 0; j <= arrSystemModulePermissions.Count - 1; j++) + { + PermissionInfo objSystemModulePermission; + objSystemModulePermission = (PermissionInfo) arrSystemModulePermissions[j]; + if (objSystemModulePermission.PermissionKey == "VIEW" && permissionType == ViewPermissionType.Edit && objTabPermission.PermissionKey != "EDIT") + { + //Only Page Editors get View permissions if "Page Editors Only" + continue; + } + ModulePermissionInfo objModulePermission = AddModulePermission(objModule, + objSystemModulePermission, + objTabPermission.RoleID, + objTabPermission.UserID, + objTabPermission.AllowAccess); + + //ensure that every EDIT permission which allows access also provides VIEW permission + if (objModulePermission.PermissionKey == "EDIT" && objModulePermission.AllowAccess) + { + ModulePermissionInfo objModuleViewperm = AddModulePermission(objModule, + (PermissionInfo) arrSystemModuleViewPermissions[0], + objModulePermission.RoleID, + objModulePermission.UserID, + true); + } + } + + //Get the custom Module Permissions, Assume that roles with Edit Tab Permissions + //are automatically assigned to the Custom Module Permissions + if (objTabPermission.PermissionKey == "EDIT") + { + ArrayList arrCustomModulePermissions = objPermissionController.GetPermissionsByModuleDefID(objModule.ModuleDefID); + + //loop through the custom module permissions + for (j = 0; j <= arrCustomModulePermissions.Count - 1; j++) + { + //create the module permission + PermissionInfo objCustomModulePermission; + objCustomModulePermission = (PermissionInfo) arrCustomModulePermissions[j]; + AddModulePermission(objModule, objCustomModulePermission, objTabPermission.RoleID, objTabPermission.UserID, objTabPermission.AllowAccess); + } + } + } + + if (PortalSettings.Current.ContentLocalizationEnabled) + { + Locale defaultLocale = LocaleController.Instance.GetDefaultLocale(PortalSettings.Current.PortalId); + //set the culture of the module to that of the tab + var tabInfo = new TabController().GetTab(objModule.TabID, PortalSettings.Current.PortalId, false); + objModule.CultureCode = tabInfo != null ? tabInfo.CultureCode : defaultLocale.Code; + } + else + { + objModule.CultureCode = Null.NullString; + } + + objModule.AllTabs = false; + objModule.Alignment = align; + objModules.AddModule(objModule); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Builds a URL + /// + /// The friendly name of the Module + /// The ID of the portal + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected string BuildURL(int PortalID, string FriendlyName) + { + string strURL = "~/" + Globals.glbDefaultPage; + var objModules = new ModuleController(); + ModuleInfo objModule = objModules.GetModuleByDefinition(PortalID, FriendlyName); + if (objModule != null) + { + if (PortalID == Null.NullInteger) + { + strURL = Globals.NavigateURL(objModule.TabID, true); + } + else + { + strURL = Globals.NavigateURL(objModule.TabID); + } + } + return strURL; + } + + protected bool GetModulePermission(int PortalID, string FriendlyName) + { + bool AllowAccess = Null.NullBoolean; + var objModules = new ModuleController(); + ModuleInfo objModule = objModules.GetModuleByDefinition(PortalID, FriendlyName); + if (objModule != null) + { + AllowAccess = ModulePermissionController.CanViewModule(objModule); + } + return AllowAccess; + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets the UserMode + /// + /// The userMode to set + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected void SetUserMode(string userMode) + { + Personalization.SetProfile("Usability", "UserMode" + PortalSettings.PortalId, userMode.ToUpper()); + } + + /// ----------------------------------------------------------------------------- + /// + /// Sets the current Visible Mode + /// + /// A flag indicating whether the Control Panel should be visible + /// + /// [cnurse] 01/11/2008 documented + /// + /// ----------------------------------------------------------------------------- + protected void SetVisibleMode(bool isVisible) + { + Personalization.SetProfile("Usability", "ControlPanelVisible" + PortalSettings.PortalId, isVisible.ToString()); + } + + protected override void OnInit(EventArgs e) + { + if (this.Page.Items.Contains(typeof(ControlPanelBase)) && this.Page.Items[typeof(ControlPanelBase)] is ControlPanelBase) + { + this.Parent.Controls.Remove(this); + } + else + { + this.Page.Items[typeof(ControlPanelBase)] = this; + base.OnInit(e); + } + + } + + #endregion + + #region Obsolete + + [Obsolete("Deprecated in 5.0. Replaced by SetMode(UserMode).")] + protected void SetContentMode(bool showContent) + { + Personalization.SetProfile("Usability", "ContentVisible" + PortalSettings.PortalId, showContent.ToString()); + } + + [Obsolete("Deprecated in 5.0. Replaced by SetMode(UserMode).")] + protected void SetPreviewMode(bool isPreview) + { + if (isPreview) + { + Personalization.SetProfile("Usability", "UserMode" + PortalSettings.PortalId, "View"); + } + else + { + Personalization.SetProfile("Usability", "UserMode" + PortalSettings.PortalId, "Edit"); + } + } + + #endregion + + #region Nested type: ViewPermissionType + + protected enum ViewPermissionType + { + View = 0, + Edit = 1 + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/ControlUtilities.cs b/DNN Platform/Library/UI/ControlUtilities.cs new file mode 100644 index 00000000000..d304f405d6a --- /dev/null +++ b/DNN Platform/Library/UI/ControlUtilities.cs @@ -0,0 +1,123 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; + +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.UI +{ + public class ControlUtilities + { + public static T FindParentControl(Control control) where T : Control + { + T parent = default(T); + if (control.Parent == null) + { + parent = null; + } + else + { + var parentT = control.Parent as T; + if (parentT != null) + { + parent = parentT; + } + else + { + parent = FindParentControl(control.Parent); + } + } + return parent; + } + + public static T FindControl(Control control, string id, bool recursive) where T : Control + { + T target = null; + if(control.Parent != null) + { + target = control.Parent.FindControl(id) as T; + + if (target == null && recursive) + { + target = FindControl(control.Parent, id, true); + } + } + + return target; + } + + public static T FindFirstDescendent(Control control) where T : Control + { + return FindFirstDescendent(control, idx => idx is T); + } + + public static T FindFirstDescendent(Control control, Predicate predicate) where T : Control + { + if (predicate(control)) return control as T; + + foreach (Control childControl in control.Controls) + { + T descendent = FindFirstDescendent(childControl, predicate); + if (descendent != null) + return descendent; + } + + return null; + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadControl loads a control and returns a reference to the control + /// + /// The type of control to Load + /// The parent Container Control + /// The source for the control. This can either be a User Control (.ascx) or a compiled + /// control. + /// A Control of type T + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + public static T LoadControl(TemplateControl containerControl, string ControlSrc) where T : Control + { + T ctrl; + + //load the control dynamically + if (ControlSrc.ToLower().EndsWith(".ascx")) + { + //load from a user control on the file system + ctrl = (T) containerControl.LoadControl("~/" + ControlSrc); + } + else + { + //load from a typename in an assembly ( ie. server control ) + Type objType = Reflection.CreateType(ControlSrc); + ctrl = (T) containerControl.LoadControl(objType, null); + } + return ctrl; + } + } +} diff --git a/DNN Platform/Library/UI/Diagrams/Skinning.cd b/DNN Platform/Library/UI/Diagrams/Skinning.cd new file mode 100644 index 00000000000..2926723122d --- /dev/null +++ b/DNN Platform/Library/UI/Diagrams/Skinning.cd @@ -0,0 +1,67 @@ + + + + + + + + + AAAAAQDAgQFAQAFoIBCKAACEAAQRQAYAgEEgEIERAEA= + UI\Skins\Skin.vb + + + + + + + + + + + + AAAQICBAAAEAAAAAAAABAAQAAAIEAAEAQAgAAAAAAAA= + UI\Skins\Pane.vb + + + + + + + + + + + + CAQAACAQAABAgAABAAAgAAIFAAACACAAAABEAAQgAAA= + UI\Containers\Container.vb + + + + + + + + + + + + + + + + gAAAACAAAAAAghAQAAAAAAihAAAAAACAgAAAAgAAAAQ= + UI\Modules\ModuleHost.vb + + + + + + + + + AAAAAAAEAABAAAQAAAAAAAAEAAgAAAAAAAAAAAAAAAA= + UI\Modules\IModuleControl.vb + + + + \ No newline at end of file diff --git a/DNN Platform/Library/UI/FavIcon.cs b/DNN Platform/Library/UI/FavIcon.cs new file mode 100644 index 00000000000..3416cdea656 --- /dev/null +++ b/DNN Platform/Library/UI/FavIcon.cs @@ -0,0 +1,135 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.FileSystem; + +namespace DotNetNuke.UI.Internals +{ + /// + /// Manages the FavIcon of a portal + /// + public class FavIcon + { + private const string SettingName = "FavIconPath"; + + private readonly int _portalId; + + /// + /// Initializes a FavIcon instance + /// + /// The id of the portal + public FavIcon(int portalId) + { + _portalId = portalId; + } + + /// + /// Get the path of the favicon file relative to the portal root + /// + /// This relative path is only relevant to use with Host/Portal Settings the path is not guaranteed any + /// physical relevance in the local file system + /// Path to the favicon file relative to portal root, or empty string when there is no favicon set + public string GetSettingPath() + { + return PortalController.GetPortalSetting(SettingName, _portalId, ""); + } + + /// + /// Update the file to use for a favIcon + /// + /// The file id or Null.NullInteger for none + public void Update(int fileId) + { + PortalController.UpdatePortalSetting(_portalId, SettingName, fileId != Null.NullInteger ? string.Format("FileID={0}", fileId) : "", /*clearCache*/ true); + DataCache.ClearCache(GetCacheKey(_portalId)); + } + + /// + /// Get the HTML for a favicon link + /// + /// The portal id + /// The HTML for the favicon link for the portal, or an empty string if there is no favicon + public static string GetHeaderLink(int portalId) + { + string headerLink; + object fromCache = DataCache.GetCache(GetCacheKey(portalId)); + + if (fromCache == null) + { + //only create an instance of FavIcon when there is a cache miss + string favIconPath = new FavIcon(portalId).GetRelativeUrl(); + if (!string.IsNullOrEmpty(favIconPath)) + { + headerLink = string.Format("", favIconPath); + } + else + { + headerLink = ""; + } + + //cache link or empty string to ensure we don't always have a + //cache miss when no favicon is in use + UpdateCachedHeaderLink(portalId, headerLink); + } + else + { + headerLink = fromCache.ToString(); + } + + return headerLink; + } + + private string GetRelativeUrl() + { + var fileInfo = GetFileInfo(); + return fileInfo == null ? string.Empty : FileManager.Instance.GetUrl(fileInfo); + } + + private IFileInfo GetFileInfo() + { + var path = GetSettingPath(); + if( ! String.IsNullOrEmpty(path) ) + { + return FileManager.Instance.GetFile(_portalId, path); + } + + return null; + } + + private static void UpdateCachedHeaderLink(int portalId, string headerLink) + { + if (Host.PerformanceSetting != Globals.PerformanceSettings.NoCaching) + { + DataCache.SetCache(GetCacheKey(portalId), headerLink); + } + } + + private static string GetCacheKey(int portalId) + { + return "FAVICON" + portalId; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/CachedModuleControl.cs b/DNN Platform/Library/UI/Modules/CachedModuleControl.cs new file mode 100644 index 00000000000..219f6b0181b --- /dev/null +++ b/DNN Platform/Library/UI/Modules/CachedModuleControl.cs @@ -0,0 +1,171 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : CachedModuleControl + /// ----------------------------------------------------------------------------- + /// + /// CachedModuleControl represents a cached "ModuleControl". It inherits from + /// Literal and implements the IModuleControl interface + /// + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public class CachedModuleControl : Literal, IModuleControl + { + private string _localResourceFile; + private ModuleInstanceContext _moduleContext; + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new CachedModuleControl + /// + /// The cached Content for this control + /// + /// [cnurse] 12/17/2007 created + /// + /// ----------------------------------------------------------------------------- + public CachedModuleControl(string cachedContent) + { + Text = cachedContent; + } + + #region IModuleControl Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets the underlying base control for this ModuleControl + /// + /// A String + /// + /// [cnurse] 12/17/2007 created + /// + /// ----------------------------------------------------------------------------- + public Control Control + { + get + { + return this; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this control (used primarily for UserControls) + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlName + { + get + { + return GetType().Name.Replace("_", "."); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the local resource file for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string LocalResourceFile + { + get + { + string fileRoot; + + if (string.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = ControlPath + "/" + Localization.LocalResourceDirectory + "/" + ID; + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Context for this control + /// + /// A ModuleInstanceContext + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleInstanceContext ModuleContext + { + get + { + if (_moduleContext == null) + { + _moduleContext = new ModuleInstanceContext(this); + } + return _moduleContext; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Modules/IModuleControl.cs b/DNN Platform/Library/UI/Modules/IModuleControl.cs new file mode 100644 index 00000000000..2ac311e9928 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/IModuleControl.cs @@ -0,0 +1,49 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : IModuleControl + /// ----------------------------------------------------------------------------- + /// + /// IModuleControl provides a common Interface for Module Controls + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public interface IModuleControl + { + Control Control { get; } + string ControlPath { get; } + string ControlName { get; } + string LocalResourceFile { get; set; } + ModuleInstanceContext ModuleContext { get; } + } +} diff --git a/DNN Platform/Library/UI/Modules/IModuleControlFactory.cs b/DNN Platform/Library/UI/Modules/IModuleControlFactory.cs new file mode 100644 index 00000000000..9f14de31a32 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/IModuleControlFactory.cs @@ -0,0 +1,35 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public interface IModuleControlFactory + { + Control CreateModuleControl(TemplateControl containerControl, ModuleInfo moduleConfiguration); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/IModuleInjectionFilter.cs b/DNN Platform/Library/UI/Modules/IModuleInjectionFilter.cs new file mode 100644 index 00000000000..720b873bc49 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/IModuleInjectionFilter.cs @@ -0,0 +1,37 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public interface IModuleInjectionFilter + { + bool CanInjectModule(ModuleInfo module, PortalSettings portalSettings); + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/IProfileModule.cs b/DNN Platform/Library/UI/Modules/IProfileModule.cs new file mode 100644 index 00000000000..32f783c8054 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/IProfileModule.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Modules +{ + public interface IProfileModule + { + bool DisplayModule { get; } + + int ProfileUserId { get; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/ISettingsControl.cs b/DNN Platform/Library/UI/Modules/ISettingsControl.cs new file mode 100644 index 00000000000..79818420568 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ISettingsControl.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : ISettingsControl + /// ----------------------------------------------------------------------------- + /// + /// ISettingsControl provides a common Interface for Module Settings Controls + /// + /// + /// [cnurse] 12/24/2007 created + /// + /// ----------------------------------------------------------------------------- + public interface ISettingsControl : IModuleControl + { + void LoadSettings(); + + void UpdateSettings(); + } +} diff --git a/DNN Platform/Library/UI/Modules/ModuleCachingType.cs b/DNN Platform/Library/UI/Modules/ModuleCachingType.cs new file mode 100644 index 00000000000..589672c1e8b --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleCachingType.cs @@ -0,0 +1,41 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : ModuleCachingType + /// ----------------------------------------------------------------------------- + /// + /// ModuleCachingType is an enum that provides the caching types for Module Content + /// + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public enum ModuleCachingType + { + Memory, + Disk, + Database + } +} diff --git a/DNN Platform/Library/UI/Modules/ModuleControlBase.cs b/DNN Platform/Library/UI/Modules/ModuleControlBase.cs new file mode 100644 index 00000000000..684a50bdf27 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleControlBase.cs @@ -0,0 +1,156 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : ModuleControlBase + /// ----------------------------------------------------------------------------- + /// + /// ModuleControlBase is a base class for Module Controls that inherits from the + /// Control base class. As with all MontrolControl base classes it implements + /// IModuleControl. + /// + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ModuleControlBase : Control, IModuleControl + { + private string _localResourceFile; + private ModuleInstanceContext _moduleContext; + + #region IModuleControl Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets the underlying base control for this ModuleControl + /// + /// A String + /// + /// [cnurse] 12/17/2007 created + /// + /// ----------------------------------------------------------------------------- + public Control Control + { + get + { + return this; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this control (used primarily for UserControls) + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlName + { + get + { + return GetType().Name.Replace("_", "."); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the local resource file for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string LocalResourceFile + { + get + { + string fileRoot; + if (string.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = ControlPath + "/" + Localization.LocalResourceDirectory + "/" + ID; + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Context for this control + /// + /// A ModuleInstanceContext + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleInstanceContext ModuleContext + { + get + { + if (_moduleContext == null) + { + _moduleContext = new ModuleInstanceContext(this); + } + return _moduleContext; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Modules/ModuleControlFactory.cs b/DNN Platform/Library/UI/Modules/ModuleControlFactory.cs new file mode 100644 index 00000000000..20990943c80 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleControlFactory.cs @@ -0,0 +1,99 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Web.UI; + +using DotNetNuke.Entities.Modules; +using DotNetNuke.Framework; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public class ModuleControlFactory + { + public static Control LoadModuleControl(TemplateControl containerControl, ModuleInfo moduleConfiguration) + { + Control control = null; + + string extension = Path.GetExtension(moduleConfiguration.ModuleControl.ControlSrc.ToLower()); + + IModuleControlFactory controlFactory = null; + switch (extension) + { + case ".ascx": + controlFactory = new WebFormsModuleControlFactory(); + break; + case ".cshtml": + case ".vbhtml": + Type factoryType = Reflection.CreateType("DotNetNuke.Web.Razor.RazorModuleControlFactory"); + if (factoryType != null) + { + controlFactory = Reflection.CreateObject(factoryType) as IModuleControlFactory; + } + break; + default: + // load from a typename in an assembly ( ie. server control) + Type objType = Reflection.CreateType(moduleConfiguration.ModuleControl.ControlSrc); + control = (containerControl.LoadControl(objType, null)); + break; + } + + if (controlFactory != null) + { + control = controlFactory.CreateModuleControl(containerControl, moduleConfiguration); + } + + // set the control ID to the resource file name ( ie. controlname.ascx = controlname ) + // this is necessary for the Localization in PageBase + if (control != null) + { + control.ID = Path.GetFileNameWithoutExtension(moduleConfiguration.ModuleControl.ControlSrc); + + var moduleControl = control as IModuleControl; + + if (moduleControl != null) + { + moduleControl.ModuleContext.Configuration = moduleConfiguration; + } + } + + return control; + } + + public static Control CreateCachedControl(string cachedContent, ModuleInfo moduleConfiguration) + { + var moduleControl = new CachedModuleControl(cachedContent); + moduleControl.ModuleContext.Configuration = moduleConfiguration; + return moduleControl; + } + + public static Control CreateModuleControl(ModuleInfo moduleConfiguration) + { + var moduleControl = new ModuleControlBase(); + moduleControl.ModuleContext.Configuration = moduleConfiguration; + return moduleControl; + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/ModuleHost.cs b/DNN Platform/Library/UI/Modules/ModuleHost.cs new file mode 100644 index 00000000000..64eeee928f8 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleHost.cs @@ -0,0 +1,578 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.ModuleCache; +using DotNetNuke.UI.WebControls; +using DotNetNuke.Web.Client.ClientResourceManagement; + +using Telerik.Web.UI; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : ModuleHost + /// ----------------------------------------------------------------------------- + /// + /// ModuleHost hosts a Module Control (or its cached Content). + /// + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public sealed class ModuleHost : Panel + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModuleHost)); + #region Private Members + + private readonly ModuleInfo _moduleConfiguration; + private Control _control; + private bool _isCached; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// Creates a Module Host control using the ModuleConfiguration for the Module + /// + /// + /// + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleHost(ModuleInfo moduleConfiguration, Skins.Skin skin, Containers.Container container) + { + ID = "ModuleContent"; + Container = container; + _moduleConfiguration = moduleConfiguration; + Skin = skin; + } + + #endregion + + #region Public Properties + + public Containers.Container Container { get; private set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the attached ModuleControl + /// + /// An IModuleControl + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl + { + get + { + //Make sure the Control tree has been created + EnsureChildControls(); + return _control as IModuleControl; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the current POrtal Settings + /// + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + public PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + public Skins.Skin Skin { get; private set; } + + #endregion + + #region Private Methods + + private void InjectModuleContent(Control content) + { + if (_moduleConfiguration.IsWebSlice && !Globals.IsAdminControl()) + { + //Assign the class - hslice to the Drag-N-Drop Panel + CssClass = "hslice"; + var titleLabel = new Label + { + CssClass = "entry-title Hidden", + Text = !string.IsNullOrEmpty(_moduleConfiguration.WebSliceTitle) ? _moduleConfiguration.WebSliceTitle : _moduleConfiguration.ModuleTitle + }; + Controls.Add(titleLabel); + + var websliceContainer = new Panel {CssClass = "entry-content"}; + websliceContainer.Controls.Add(content); + + var expiry = new HtmlGenericControl {TagName = "abbr"}; + expiry.Attributes["class"] = "endtime"; + if (!Null.IsNull(_moduleConfiguration.WebSliceExpiryDate)) + { + expiry.Attributes["title"] = _moduleConfiguration.WebSliceExpiryDate.ToString("o"); + websliceContainer.Controls.Add(expiry); + } + else if (_moduleConfiguration.EndDate < DateTime.MaxValue) + { + expiry.Attributes["title"] = _moduleConfiguration.EndDate.ToString("o"); + websliceContainer.Controls.Add(expiry); + } + + var ttl = new HtmlGenericControl {TagName = "abbr"}; + ttl.Attributes["class"] = "ttl"; + if (_moduleConfiguration.WebSliceTTL > 0) + { + ttl.Attributes["title"] = _moduleConfiguration.WebSliceTTL.ToString(); + websliceContainer.Controls.Add(ttl); + } + else if (_moduleConfiguration.CacheTime > 0) + { + ttl.Attributes["title"] = (_moduleConfiguration.CacheTime/60).ToString(); + websliceContainer.Controls.Add(ttl); + } + + Controls.Add(websliceContainer); + } + else + { + Controls.Add(content); + } + } + + /// ---------------------------------------------------------------------------- + /// + /// Gets a flag that indicates whether the Module Content should be displayed + /// + /// A Boolean + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + private bool DisplayContent() + { + //module content visibility options + var content = PortalSettings.UserMode != PortalSettings.Mode.Layout; + if (Page.Request.QueryString["content"] != null) + { + switch (Page.Request.QueryString["Content"].ToLower()) + { + case "1": + case "true": + content = true; + break; + case "0": + case "false": + content = false; + break; + } + } + if (Globals.IsAdminControl()) + { + content = true; + } + return content; + } + + private static void InjectMessageControl(Control container) + { + //inject a message placeholder for common module messaging - UI.Skins.Skin.AddModuleMessage + var messagePlaceholder = new PlaceHolder {ID = "MessagePlaceHolder", Visible = false}; + container.Controls.Add(messagePlaceholder); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that indicates whether the Module is in View Mode + /// + /// A Boolean + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + internal static bool IsViewMode(ModuleInfo moduleInfo, PortalSettings settings) + { + bool viewMode; + + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.ViewPermissions, Null.NullString, + moduleInfo)) + { + viewMode = false; + } + else + { + viewMode = !(ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, Null.NullString, + moduleInfo)); + } + + return viewMode || settings.UserMode == PortalSettings.Mode.View; + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadModuleControl loads the ModuleControl (PortalModuelBase) + /// + /// + /// [cnurse] 12/15/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void LoadModuleControl() + { + try + { + if (DisplayContent()) + { + //if the module supports caching and caching is enabled for the instance and the user does not have Edit rights or is currently in View mode + if (SupportsCaching() && IsViewMode(_moduleConfiguration, PortalSettings)) + { + //attempt to load the cached content + _isCached = TryLoadCached(); + } + if (!_isCached) + { + // load the control dynamically + _control = ModuleControlFactory.LoadModuleControl(Page, _moduleConfiguration); + } + } + else //content placeholder + { + _control = ModuleControlFactory.CreateModuleControl(_moduleConfiguration); + } + if (Skin != null) + { + + //check for IMC + Skin.Communicator.LoadCommunicator(_control); + } + + //add module settings + ModuleControl.ModuleContext.Configuration = _moduleConfiguration; + } + catch (ThreadAbortException exc) + { + Logger.Debug(exc); + + Thread.ResetAbort(); + } + catch (Exception exc) + { + Logger.Error(exc); + + //add module settings + _control = ModuleControlFactory.CreateModuleControl(_moduleConfiguration); + ModuleControl.ModuleContext.Configuration = _moduleConfiguration; + if (TabPermissionController.CanAdminPage()) + { + //only display the error to page administrators + Exceptions.ProcessModuleLoadException(_control, exc); + } + else + { + // Otherwise just log the fact that an exception occurred + new ExceptionLogController().AddLog(exc); + } + } + } + + private void LoadAjaxPanel() + { + var loadingPanel = new RadAjaxLoadingPanel { ID = _control.ID + "_Prog", Skin = "Default" }; + + Controls.Add(loadingPanel); + + var ajaxPanel = new RadAjaxPanel { + ID = _control.ID + "_UP", + LoadingPanelID = loadingPanel.ID, + RestoreOriginalRenderDelegate = false + }; + InjectMessageControl(ajaxPanel); + ajaxPanel.Controls.Add(_control); + + Controls.Add(ajaxPanel); + + } + + /// + /// LoadUpdatePanel optionally loads an AJAX Update Panel + /// + /// + /// [cnurse] 12/16/2007 Created + /// + /// ----------------------------------------------------------------------------- + private void LoadUpdatePanel() + { + //register AJAX + AJAX.RegisterScriptManager(); + + //enable Partial Rendering + var scriptManager = AJAX.GetScriptManager(Page); + if (scriptManager != null) + { + scriptManager.EnablePartialRendering = true; + } + + //create update panel + var updatePanel = new UpdatePanel + { + UpdateMode = UpdatePanelUpdateMode.Conditional, + ID = _control.ID + "_UP" + }; + + //get update panel content template + var templateContainer = updatePanel.ContentTemplateContainer; + + //inject a message placeholder for common module messaging - UI.Skins.Skin.AddModuleMessage + InjectMessageControl(templateContainer); + + //inject module into update panel content template + templateContainer.Controls.Add(_control); + + //inject the update panel into the panel + InjectModuleContent(updatePanel); + + //create image for update progress control + var image = new Image + { + ImageUrl = "~/images/progressbar.gif", //hardcoded + AlternateText = "ProgressBar" + }; + + //inject updateprogress into the panel + var updateProgress = new UpdateProgress + { + AssociatedUpdatePanelID = updatePanel.ID, + ID = updatePanel.ID + "_Prog", + ProgressTemplate = new LiteralTemplate(image) + }; + Controls.Add(updateProgress); + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a flag that indicates whether the Module Instance supports Caching + /// + /// A Boolean + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + private bool SupportsCaching() + { + return _moduleConfiguration.CacheTime > 0; + } + + /// ----------------------------------------------------------------------------- + /// + /// Trys to load previously cached Module Content + /// + /// A Boolean that indicates whether the cahed content was loaded + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + private bool TryLoadCached() + { + bool success = false; + string cachedContent = string.Empty; + try + { + var cache = ModuleCachingProvider.Instance(_moduleConfiguration.GetEffectiveCacheMethod()); + var varyBy = new SortedDictionary {{"locale", Thread.CurrentThread.CurrentUICulture.ToString()}}; + + string cacheKey = cache.GenerateCacheKey(_moduleConfiguration.TabModuleID, varyBy); + byte[] cachedBytes = ModuleCachingProvider.Instance(_moduleConfiguration.GetEffectiveCacheMethod()).GetModule(_moduleConfiguration.TabModuleID, cacheKey); + + if (cachedBytes != null && cachedBytes.Length > 0) + { + cachedContent = Encoding.UTF8.GetString(cachedBytes); + success = true; + } + } + catch (Exception ex) + { + cachedContent = string.Empty; + Exceptions.LogException(ex); + success = false; + } + if (success) + { + //parse the registered CDF from content + var matches = Regex.Matches(cachedContent, "<\\!--CDF\\((JAVASCRIPT|CSS)\\|(.+?)\\)-->", RegexOptions.IgnoreCase); + if (matches.Count > 0) + { + foreach (Match match in matches) + { + cachedContent = cachedContent.Replace(match.Value, string.Empty); + if (match.Groups[1].Value.ToUpperInvariant() == "JAVASCRIPT") + { + ClientResourceManager.RegisterScript(Page, match.Groups[2].Value); + } + else + { + ClientResourceManager.RegisterStyleSheet(Page, match.Groups[2].Value); + } + } + } + _control = ModuleControlFactory.CreateCachedControl(cachedContent, _moduleConfiguration); + Controls.Add(_control); + } + return success; + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// CreateChildControls builds the control tree + /// + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void CreateChildControls() + { + Controls.Clear(); + + //Load Module Control (or cached control) + LoadModuleControl(); + + //Optionally Inject AJAX Update Panel + if (ModuleControl != null) + { + //if module is dynamically loaded and AJAX is installed and the control supports partial rendering (defined in ModuleControls table ) + if (!_isCached && _moduleConfiguration.ModuleControl.SupportsPartialRendering && AJAX.IsInstalled()) + { + LoadAjaxPanel(); + } + else + { + //inject a message placeholder for common module messaging - UI.Skins.Skin.AddModuleMessage + InjectMessageControl(this); + + //inject the module into the panel + InjectModuleContent(_control); + } + } + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + if (Host.EnableCustomModuleCssClass) + { + string moduleName = ModuleControl.ModuleContext.Configuration.DesktopModule.ModuleName; + if (moduleName != null) + { + moduleName = Globals.CleanName(moduleName); + } + Attributes.Add("class", string.Format("DNNModuleContent Mod{0}C", moduleName)); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// RenderContents renders the contents of the control to the output stream + /// + /// + /// [cnurse] 12/15/2007 created + /// + /// ----------------------------------------------------------------------------- + protected override void RenderContents(HtmlTextWriter writer) + { + if (_isCached) + { + //Render the cached control to the output stream + base.RenderContents(writer); + } + else + { + if (SupportsCaching() && IsViewMode(_moduleConfiguration, PortalSettings) && !Globals.IsAdminControl()) + { + //Render to cache + var tempWriter = new StringWriter(); + + _control.RenderControl(new HtmlTextWriter(tempWriter)); + string cachedOutput = tempWriter.ToString(); + + if (!string.IsNullOrEmpty(cachedOutput) && (!HttpContext.Current.Request.Browser.Crawler)) + { + //Save content to cache + var moduleContent = Encoding.UTF8.GetBytes(cachedOutput); + var cache = ModuleCachingProvider.Instance(_moduleConfiguration.GetEffectiveCacheMethod()); + + var varyBy = new SortedDictionary {{"locale", Thread.CurrentThread.CurrentUICulture.ToString()}}; + + var cacheKey = cache.GenerateCacheKey(_moduleConfiguration.TabModuleID, varyBy); + cache.SetModule(_moduleConfiguration.TabModuleID, cacheKey, new TimeSpan(0, 0, _moduleConfiguration.CacheTime), moduleContent); + } + + //Render the cached content to Response + writer.Write(cachedOutput); + } + else + { + //Render the control to Response + base.RenderContents(writer); + } + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/ModuleInjectionManager.cs b/DNN Platform/Library/UI/Modules/ModuleInjectionManager.cs new file mode 100644 index 00000000000..589d162ac72 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleInjectionManager.cs @@ -0,0 +1,88 @@ +#region Copyright + +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using DotNetNuke.Collections.Internal; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Framework.Internal.Reflection; +using DotNetNuke.Instrumentation; + +namespace DotNetNuke.UI.Modules +{ + internal class ModuleInjectionManager + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (ModuleInjectionManager)); + private static NaiveLockingList _filters; + + public static void RegisterInjectionFilters() + { + _filters = new NaiveLockingList(); + + foreach (IModuleInjectionFilter filter in GetFilters()) + { + _filters.Add(filter); + } + } + + private static IEnumerable GetFilters() + { + var typeLocator = new TypeLocator(); + IEnumerable types = typeLocator.GetAllMatchingTypes(IsValidModuleInjectionFilter); + + foreach (Type filterType in types) + { + IModuleInjectionFilter filter; + try + { + filter = Activator.CreateInstance(filterType) as IModuleInjectionFilter; + } + catch (Exception e) + { + Logger.ErrorFormat("Unable to create {0} while registering module injection filters. {1}", filterType.FullName, + e.Message); + filter = null; + } + + if (filter != null) + { + yield return filter; + } + } + } + + internal static bool IsValidModuleInjectionFilter(Type t) + { + return t != null && t.IsClass && !t.IsAbstract && t.IsVisible && + typeof(IModuleInjectionFilter).IsAssignableFrom(t); + } + + public static bool CanInjectModule(ModuleInfo module, PortalSettings portalSettings) + { + return _filters.All(filter => filter.CanInjectModule(module, portalSettings)); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/ModuleInstanceContext.cs b/DNN Platform/Library/UI/Modules/ModuleInstanceContext.cs new file mode 100644 index 00000000000..85ba5cf449b --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleInstanceContext.cs @@ -0,0 +1,843 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Linq; +using System.Web; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Skins; +using DotNetNuke.UI.Utilities; + +using Globals = DotNetNuke.Common.Globals; +using System.Web.UI; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// + /// Provides context data for a particular instance of a module + /// + public class ModuleInstanceContext + { + #region Private Members + + private readonly IModuleControl _moduleControl; + private ModuleActionCollection _actions; + private ModuleAction _moduleSpecificActions; + private ModuleAction _moduleGenericActions; + private ModuleAction _moduleMoveActions; + private ModuleInfo _configuration; + private bool? _isEditable; + private int _nextActionId = -1; + private Hashtable _settings; + + #endregion + + #region Constructors + + public ModuleInstanceContext() + { + } + + public ModuleInstanceContext(IModuleControl moduleControl) + { + _moduleControl = moduleControl; + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Actions for this module context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public ModuleActionCollection Actions + { + get + { + if (_actions == null) + { + LoadActions(HttpContext.Current.Request); + } + return _actions; + } + set + { + _actions = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the Module Configuration (ModuleInfo) for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public ModuleInfo Configuration + { + get + { + return _configuration; + } + set + { + _configuration = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// The EditMode property is used to determine whether the user is in the + /// Administrator role + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool EditMode + { + get + { + return TabPermissionController.CanAdminPage(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the HelpUrl for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public string HelpURL { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether the module is Editable (in Admin mode) + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public bool IsEditable + { + get + { + //Perform tri-state switch check to avoid having to perform a security + //role lookup on every property access (instead caching the result) + if (!_isEditable.HasValue) + { + bool blnPreview = (PortalSettings.UserMode == PortalSettings.Mode.View); + if (Globals.IsHostTab(PortalSettings.ActiveTab.TabID)) + { + blnPreview = false; + } + bool blnHasModuleEditPermissions = false; + if (_configuration != null) + { + blnHasModuleEditPermissions = ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Edit, "CONTENT", Configuration); + } + if (blnPreview == false && blnHasModuleEditPermissions) + { + _isEditable = true; + } + else + { + _isEditable = false; + } + } + return _isEditable.Value; + } + } + + public bool IsHostMenu + { + get + { + return Globals.IsHostTab(PortalSettings.ActiveTab.TabID); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the module ID for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int ModuleId + { + get + { + if (_configuration != null) + { + return _configuration.ModuleID; + } + + return Null.NullInteger; + } + set + { + if (_configuration != null) + { + _configuration.ModuleID = value; + } + } + } + + public PortalAliasInfo PortalAlias + { + get + { + return PortalSettings.PortalAlias; + } + } + + public int PortalId + { + get + { + return PortalSettings.PortalId; + } + } + + public PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the settings for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public Hashtable Settings + { + get + { + var controller = new ModuleController(); + if (_settings == null) + { + //we need to make sure we don't directly modify the ModuleSettings so create new HashTable DNN-8715 + _settings = new Hashtable(controller.GetModuleSettings(ModuleId)); + + //add the TabModuleSettings to the ModuleSettings + Hashtable tabModuleSettings = controller.GetTabModuleSettings(TabModuleId); + foreach (string strKey in tabModuleSettings.Keys) + { + _settings[strKey] = tabModuleSettings[strKey]; + } + } + return _settings; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the tab ID for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int TabId + { + get + { + if (_configuration != null) + { + return Convert.ToInt32(_configuration.TabID); + } + + return Null.NullInteger; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the tabnmodule ID for this context + /// + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + public int TabModuleId + { + get + { + if (_configuration != null) + { + return Convert.ToInt32(_configuration.TabModuleID); + } + + return Null.NullInteger; + } + set + { + if (_configuration != null) + { + _configuration.TabModuleID = value; + } + } + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// AddHelpActions Adds the Help actions to the Action Menu + /// + /// + /// + /// + /// [cnurse] 05/12/2005 Documented + /// [cnurse] 01/19/2006 Moved from ActionBase + /// [cnurse] 12/24/2007 Renamed (from SetHelpVisibility) + /// + /// ----------------------------------------------------------------------------- + private void AddHelpActions() + { + var url = string.Empty; + if (!string.IsNullOrEmpty(Configuration.ModuleControl.HelpURL) && Host.EnableModuleOnLineHelp && PortalSettings.EnablePopUps) + { + url = UrlUtils.PopUpUrl(Configuration.ModuleControl.HelpURL, PortalSettings, false, false, 550, 950); + } + else + { + url = NavigateUrl(TabId, "Help", false, "ctlid=" + Configuration.ModuleControlId, "moduleid=" + ModuleId); + } + + var helpAction = new ModuleAction(GetNextActionID()) + { + Title = Localization.GetString(ModuleActionType.ModuleHelp, Localization.GlobalResourceFile), + CommandName = ModuleActionType.ModuleHelp, + CommandArgument = "", + Icon = "action_help.gif", + Url = url, + Secure = SecurityAccessLevel.Edit, + Visible = true, + NewWindow = false, + UseActionEvent = true + }; + _moduleGenericActions.Actions.Add(helpAction); + } + + private void AddPrintAction() + { + var action = new ModuleAction(GetNextActionID()) + { + Title = Localization.GetString(ModuleActionType.PrintModule, Localization.GlobalResourceFile), + CommandName = ModuleActionType.PrintModule, + CommandArgument = "", + Icon = "action_print.gif", + Url = NavigateUrl(TabId, + "", + false, + "mid=" + ModuleId, + "SkinSrc=" + Globals.QueryStringEncode("[G]" + SkinController.RootSkin + "/" + Globals.glbHostSkinFolder + "/" + "No Skin"), + "ContainerSrc=" + Globals.QueryStringEncode("[G]" + SkinController.RootContainer + "/" + Globals.glbHostSkinFolder + "/" + "No Container"), + "dnnprintmode=true"), + Secure = SecurityAccessLevel.Anonymous, + UseActionEvent = true, + Visible = true, + NewWindow = true + }; + _moduleGenericActions.Actions.Add(action); + } + + private void AddSyndicateAction() + { + var action = new ModuleAction(GetNextActionID()) + { + Title = Localization.GetString(ModuleActionType.SyndicateModule, Localization.GlobalResourceFile), + CommandName = ModuleActionType.SyndicateModule, + CommandArgument = "", + Icon = "action_rss.gif", + Url = NavigateUrl(PortalSettings.ActiveTab.TabID, "", "RSS.aspx", false, "moduleid=" + ModuleId), + Secure = SecurityAccessLevel.Anonymous, + UseActionEvent = true, + Visible = true, + NewWindow = true + }; + _moduleGenericActions.Actions.Add(action); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddMenuMoveActions Adds the Move actions to the Action Menu + /// + /// + /// + /// + /// [cnurse] 01/04/2008 Refactored from LoadActions + /// + /// ----------------------------------------------------------------------------- + private void AddMenuMoveActions() + { + //module movement + _moduleMoveActions = new ModuleAction(GetNextActionID(), Localization.GetString(ModuleActionType.MoveRoot, Localization.GlobalResourceFile), string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, false); + + //move module up/down + if (Configuration != null) + { + if ((Configuration.ModuleOrder != 0) && (Configuration.PaneModuleIndex > 0)) + { + _moduleMoveActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.MoveTop, Localization.GlobalResourceFile), + ModuleActionType.MoveTop, + Configuration.PaneName, + "action_top.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + _moduleMoveActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.MoveUp, Localization.GlobalResourceFile), + ModuleActionType.MoveUp, + Configuration.PaneName, + "action_up.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + } + if ((Configuration.ModuleOrder != 0) && (Configuration.PaneModuleIndex < (Configuration.PaneModuleCount - 1))) + { + _moduleMoveActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.MoveDown, Localization.GlobalResourceFile), + ModuleActionType.MoveDown, + Configuration.PaneName, + "action_down.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + _moduleMoveActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.MoveBottom, Localization.GlobalResourceFile), + ModuleActionType.MoveBottom, + Configuration.PaneName, + "action_bottom.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + } + } + + //move module to pane + foreach (object obj in PortalSettings.ActiveTab.Panes) + { + var pane = obj as string; + if (!string.IsNullOrEmpty(pane) && Configuration != null && !Configuration.PaneName.Equals(pane, StringComparison.InvariantCultureIgnoreCase)) + { + _moduleMoveActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.MovePane, Localization.GlobalResourceFile) + " " + pane, + ModuleActionType.MovePane, + pane, + "action_move.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + } + } + + } + + /// ----------------------------------------------------------------------------- + /// + /// GetActionsCount gets the current number of actions + /// + /// The actions collection to count. + /// The current count + /// + /// [cnurse] 01/04/2008 Documented + /// + /// ----------------------------------------------------------------------------- + private static int GetActionsCount(int count, ModuleActionCollection actions) + { + foreach (ModuleAction action in actions) + { + if (action.HasChildren()) + { + count += action.Actions.Count; + + //Recursively call to see if this collection has any child actions that would affect the count + count = GetActionsCount(count, action.Actions); + } + } + return count; + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadActions loads the Actions collections + /// + /// + /// + /// + /// [cnurse] 01/19/2006 created + /// + /// ----------------------------------------------------------------------------- + private void LoadActions(HttpRequest request) + { + _actions = new ModuleActionCollection(); + _moduleGenericActions = new ModuleAction(GetNextActionID(), Localization.GetString("ModuleGenericActions.Action", Localization.GlobalResourceFile), string.Empty, string.Empty, string.Empty); + int maxActionId = Null.NullInteger; + + //check if module Implements Entities.Modules.IActionable interface + var actionable = _moduleControl as IActionable; + if (actionable != null) + { + _moduleSpecificActions = new ModuleAction(GetNextActionID(), Localization.GetString("ModuleSpecificActions.Action", Localization.GlobalResourceFile), string.Empty, string.Empty, string.Empty); + + ModuleActionCollection moduleActions = actionable.ModuleActions; + + foreach (ModuleAction action in moduleActions) + { + if (ModulePermissionController.HasModuleAccess(action.Secure, "CONTENT", Configuration)) + { + if (String.IsNullOrEmpty(action.Icon)) + { + action.Icon = "edit.gif"; + } + if (action.ID > maxActionId) + { + maxActionId = action.ID; + } + _moduleSpecificActions.Actions.Add(action); + + if (!UIUtilities.IsLegacyUI(ModuleId, action.ControlKey, PortalId) && action.Url.Contains("ctl")) + { + action.ClientScript = UrlUtils.PopUpUrl(action.Url, _moduleControl as Control, PortalSettings, true, false); + } + } + } + if (_moduleSpecificActions.Actions.Count > 0) + { + _actions.Add(_moduleSpecificActions); + } + } + + //Make sure the Next Action Id counter is correct + int actionCount = GetActionsCount(_actions.Count, _actions); + if (_nextActionId < maxActionId) + { + _nextActionId = maxActionId; + } + if (_nextActionId < actionCount) + { + _nextActionId = actionCount; + } + + //Custom injection of Module Settings when shared as ViewOnly + if (Configuration != null && (Configuration.IsShared && Configuration.IsShareableViewOnly) + && TabPermissionController.CanAddContentToPage()) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString("ModulePermissions.Action", Localization.GlobalResourceFile), + "ModulePermissions", + "", + "action_settings.gif", + NavigateUrl(TabId, "ModulePermissions", false, "ModuleId=" + ModuleId), + false, + SecurityAccessLevel.ViewPermissions, + true, + false); + } + else + { + if (!Globals.IsAdminControl() && ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "DELETE,MANAGE", Configuration)) + { + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "MANAGE", Configuration)) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.ModuleSettings, Localization.GlobalResourceFile), + ModuleActionType.ModuleSettings, + "", + "action_settings.gif", + NavigateUrl(TabId, "Module", false, "ModuleId=" + ModuleId), + false, + SecurityAccessLevel.Edit, + true, + false); + } + } + } + + if (!string.IsNullOrEmpty(Configuration.DesktopModule.BusinessControllerClass)) + { + //check if module implements IPortable interface, and user has Admin permissions + if (Configuration.DesktopModule.IsPortable) + { + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "EXPORT", Configuration)) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.ExportModule, Localization.GlobalResourceFile), + "", + "", + "action_export.gif", + NavigateUrl(PortalSettings.ActiveTab.TabID, "ExportModule", false, "moduleid=" + ModuleId), + + "", + false, + SecurityAccessLevel.View, + true, + false); + } + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "IMPORT", Configuration)) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.ImportModule, Localization.GlobalResourceFile), + "", + "", + "action_import.gif", + NavigateUrl(PortalSettings.ActiveTab.TabID, "ImportModule", false, "moduleid=" + ModuleId), + "", + false, + SecurityAccessLevel.View, + true, + false); + } + } + if (Configuration.DesktopModule.IsSearchable && Configuration.DisplaySyndicate) + { + AddSyndicateAction(); + } + } + + //help module actions available to content editors and administrators + const string permisisonList = "CONTENT,DELETE,EDIT,EXPORT,IMPORT,MANAGE"; + if (ModulePermissionController.HasModulePermission(Configuration.ModulePermissions, permisisonList) && request.QueryString["ctl"] != "Help") + { + AddHelpActions(); + } + + //Add Print Action + if (Configuration.DisplayPrint) + { + //print module action available to everyone + AddPrintAction(); + } + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Host, "MANAGE", Configuration)) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.ViewSource, Localization.GlobalResourceFile), + ModuleActionType.ViewSource, + "", + "action_source.gif", + NavigateUrl(TabId, "ViewSource", false, "ModuleId=" + ModuleId, "ctlid=" + Configuration.ModuleControlId), + false, + SecurityAccessLevel.Host, + true, + false); + } + + + + if (!Globals.IsAdminControl() && ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "DELETE,MANAGE", Configuration)) + { + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "DELETE", Configuration)) + { + //Check if this is the owner instance of a shared module. + string confirmText = "confirm('" + ClientAPI.GetSafeJSString(Localization.GetString("DeleteModule.Confirm")) + "')"; + if (!Configuration.IsShared) + { + var moduleController = new ModuleController(); + if (moduleController.GetModuleTabs(Configuration.ModuleID).Cast().Any(instance => instance.IsShared)) + { + confirmText = "confirm('" + ClientAPI.GetSafeJSString(Localization.GetString("DeleteSharedModule.Confirm")) + "')"; + } + } + + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.DeleteModule, Localization.GlobalResourceFile), + ModuleActionType.DeleteModule, + Configuration.ModuleID.ToString(), + "action_delete.gif", + "", + confirmText, + false, + SecurityAccessLevel.View, + true, + false); + } + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "MANAGE", Configuration)) + { + _moduleGenericActions.Actions.Add(GetNextActionID(), + Localization.GetString(ModuleActionType.ClearCache, Localization.GlobalResourceFile), + ModuleActionType.ClearCache, + Configuration.ModuleID.ToString(), + "action_refresh.gif", + "", + false, + SecurityAccessLevel.View, + true, + false); + } + + if (ModulePermissionController.HasModuleAccess(SecurityAccessLevel.Admin, "MANAGE", Configuration)) + { + //module movement + AddMenuMoveActions(); + } + } + + if (_moduleGenericActions.Actions.Count > 0) + { + _actions.Add(_moduleGenericActions); + } + + if (_moduleMoveActions != null && _moduleMoveActions.Actions.Count > 0) + { + _actions.Add(_moduleMoveActions); + } + + foreach (ModuleAction action in _moduleGenericActions.Actions) + { + if (!UIUtilities.IsLegacyUI(ModuleId, action.ControlKey, PortalId) && action.Url.Contains("ctl")) + { + action.ClientScript = UrlUtils.PopUpUrl(action.Url, _moduleControl as Control, PortalSettings, true, false); + } + } + } + + #endregion + + #region Public Methods + + public string EditUrl() + { + return EditUrl("", "", "Edit"); + } + + public string EditUrl(string controlKey) + { + return EditUrl("", "", controlKey); + } + + public string EditUrl(string keyName, string keyValue) + { + return EditUrl(keyName, keyValue, "Edit"); + } + + public string EditUrl(string keyName, string keyValue, string controlKey) + { + var parameters = new string[] { }; + return EditUrl(keyName, keyValue, controlKey, parameters); + } + + public string EditUrl(string keyName, string keyValue, string controlKey, params string[] additionalParameters) + { + string key = controlKey; + if (string.IsNullOrEmpty(key)) + { + key = "Edit"; + } + string moduleIdParam = string.Empty; + if (Configuration != null) + { + moduleIdParam = string.Format("mid={0}", Configuration.ModuleID); + } + + string[] parameters; + if (!string.IsNullOrEmpty(keyName) && !string.IsNullOrEmpty(keyValue)) + { + parameters = new string[2 + additionalParameters.Length]; + parameters[0] = moduleIdParam; + parameters[1] = string.Format("{0}={1}", keyName, keyValue); + Array.Copy(additionalParameters, 0, parameters, 2, additionalParameters.Length); + } + else + { + parameters = new string[1 + additionalParameters.Length]; + parameters[0] = moduleIdParam; + Array.Copy(additionalParameters, 0, parameters, 1, additionalParameters.Length); + } + + return NavigateUrl(PortalSettings.ActiveTab.TabID, key, false, parameters); + } + + public string NavigateUrl(int tabID, string controlKey, bool pageRedirect, params string[] additionalParameters) + { + return NavigateUrl(tabID, controlKey, Globals.glbDefaultPage, pageRedirect, additionalParameters); + } + + public string NavigateUrl(int tabID, string controlKey, string pageName, bool pageRedirect, params string[] additionalParameters) + { + var isSuperTab = Globals.IsHostTab(tabID); + var settings = PortalController.GetCurrentPortalSettings(); + var language = Globals.GetCultureCode(tabID, isSuperTab, settings); + var url = Globals.NavigateURL(tabID, isSuperTab, settings, controlKey, language, pageName, additionalParameters); + + // Making URLs call popups + if (PortalSettings != null && PortalSettings.EnablePopUps) + { + if (!UIUtilities.IsLegacyUI(ModuleId, controlKey, PortalId) && (url.Contains("ctl"))) + { + url = UrlUtils.PopUpUrl(url, null, PortalSettings, false, pageRedirect); + } + } + return url; + } + + public int GetNextActionID() + { + _nextActionId += 1; + return _nextActionId; + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Modules/ModuleUserControlBase.cs b/DNN Platform/Library/UI/Modules/ModuleUserControlBase.cs new file mode 100644 index 00000000000..76d7a7ab576 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ModuleUserControlBase.cs @@ -0,0 +1,162 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.IO; +using System.Web.UI; + +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Modules + /// Class : ModuleUserControlBase + /// ----------------------------------------------------------------------------- + /// + /// ModuleUserControlBase is a base class for Module Controls that inherits from the + /// UserControl base class. As with all MontrolControl base classes it implements + /// IModuleControl. + /// + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public class ModuleUserControlBase : UserControl, IModuleControl + { + private string _localResourceFile; + private ModuleInstanceContext _moduleContext; + + protected string LocalizeString(string key) + { + return Localization.GetString(key, LocalResourceFile); + } + + #region IModuleControl Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets the underlying base control for this ModuleControl + /// + /// A String + /// + /// [cnurse] 12/17/2007 created + /// + /// ----------------------------------------------------------------------------- + public Control Control + { + get + { + return this; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this control (used primarily for UserControls) + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Name for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string ControlName + { + get + { + return GetType().Name.Replace("_", "."); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the local resource file for this control + /// + /// A String + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public string LocalResourceFile + { + get + { + string fileRoot; + if (string.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = Path.Combine(ControlPath, Localization.LocalResourceDirectory + "/" + ID); + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Module Context for this control + /// + /// A ModuleInstanceContext + /// + /// [cnurse] 12/16/2007 created + /// + /// ----------------------------------------------------------------------------- + public ModuleInstanceContext ModuleContext + { + get + { + if (_moduleContext == null) + { + _moduleContext = new ModuleInstanceContext(this); + } + return _moduleContext; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Modules/ProfileModuleUserControlBase.cs b/DNN Platform/Library/UI/Modules/ProfileModuleUserControlBase.cs new file mode 100644 index 00000000000..d07a67226e3 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/ProfileModuleUserControlBase.cs @@ -0,0 +1,114 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Globalization; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Skins.Controls; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public abstract class ProfileModuleUserControlBase : ModuleUserControlBase, IProfileModule + { + #region IProfileModule Members + + public abstract bool DisplayModule { get; } + + public int ProfileUserId + { + get + { + if (!string.IsNullOrEmpty(Request.Params["UserId"])) + { + return Int32.Parse(Request.Params["UserId"]); + } + + return UserController.GetCurrentUserInfo().UserID; + } + } + + #endregion + + #region Protected Properties + + protected bool IsUser + { + get { return ProfileUserId == ModuleContext.PortalSettings.UserId; } + } + + protected UserInfo ProfileUser + { + get { return UserController.GetUserById(ModuleContext.PortalId, ProfileUserId); } + } + + #endregion + + #region Private Methods + + private string GetRedirectUrl() + { + //redirect user to default page if not specific the home tab, do this action to prevent loop redirect. + var homeTabId = ModuleContext.PortalSettings.HomeTabId; + string redirectUrl; + + if (homeTabId > Null.NullInteger) + { + redirectUrl = Globals.NavigateURL(homeTabId); + } + else + { + redirectUrl = Globals.GetPortalDomainName(PortalSettings.Current.PortalAlias.HTTPAlias, Request, true) + + "/" + Globals.glbDefaultPage; + } + + return redirectUrl; + } + + #endregion + + #region Protected Methods + + protected override void OnInit(EventArgs e) + { + if (string.IsNullOrEmpty(Request.Params["UserId"]) && + (ModuleContext.PortalSettings.ActiveTab.TabID == ModuleContext.PortalSettings.UserTabId + || ModuleContext.PortalSettings.ActiveTab.ParentId == ModuleContext.PortalSettings.UserTabId)) + { + //Clicked on breadcrumb - don't know which user + Response.Redirect(Request.IsAuthenticated + ? Globals.NavigateURL(ModuleContext.PortalSettings.ActiveTab.TabID,"", "UserId="+ ModuleContext.PortalSettings.UserId.ToString(CultureInfo.InvariantCulture)) + : GetRedirectUrl(), true); + } + + base.OnInit(e); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/StandardModuleInjectionFilter.cs b/DNN Platform/Library/UI/Modules/StandardModuleInjectionFilter.cs new file mode 100644 index 00000000000..020be5ff901 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/StandardModuleInjectionFilter.cs @@ -0,0 +1,53 @@ +#region Copyright + +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#endregion + +#region Usings + +using System; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Permissions; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public class StandardModuleInjectionFilter : IModuleInjectionFilter + { + #region Implementation of IModuleInjectionFilter + + public bool CanInjectModule(ModuleInfo module, PortalSettings portalSettings) + { + return ModulePermissionController.CanViewModule(module) + && module.IsDeleted == false + && ((module.StartDate < DateTime.Now && module.EndDate > DateTime.Now) + || Globals.IsLayoutMode() + || Globals.IsEditMode() + ); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Modules/WebFormsModuleControlFactory.cs b/DNN Platform/Library/UI/Modules/WebFormsModuleControlFactory.cs new file mode 100644 index 00000000000..2287adb3cd0 --- /dev/null +++ b/DNN Platform/Library/UI/Modules/WebFormsModuleControlFactory.cs @@ -0,0 +1,42 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.Web.UI; + +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.UI.Modules +{ + public class WebFormsModuleControlFactory : IModuleControlFactory + { + #region IModuleControlFactory Members + + public Control CreateModuleControl(TemplateControl containerControl, ModuleInfo moduleConfiguration) + { + return ControlUtilities.LoadControl(containerControl, moduleConfiguration.ModuleControl.ControlSrc); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Navigation.cs b/DNN Platform/Library/UI/Navigation.cs new file mode 100644 index 00000000000..5ee6ec605af --- /dev/null +++ b/DNN Platform/Library/UI/Navigation.cs @@ -0,0 +1,704 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Web.UI; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Security; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Containers; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI +{ + public class Navigation + { + #region NavNodeOptions enum + + public enum NavNodeOptions + { + IncludeSelf = 1, + IncludeParent = 2, + IncludeSiblings = 4, + MarkPendingNodes = 8, + IncludeHiddenNodes = 16 + } + + #endregion + + #region ToolTipSource enum + + public enum ToolTipSource + { + TabName, + Title, + Description, + None + } + + #endregion + + #region Private Shared Methods + + /// ----------------------------------------------------------------------------- + /// + /// Recursive function to add module's actions to the DNNNodeCollection based off of passed in ModuleActions + /// + /// Parent action + /// Parent node + /// ActionControl to base actions off of + /// + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + private static void AddChildActions(ModuleAction parentAction, DNNNode parentNode, IActionControl objActionControl) + { + AddChildActions(parentAction, parentNode, parentNode, objActionControl, -1); + } + + /// ----------------------------------------------------------------------------- + /// + /// Recursive function to add module's actions to the DNNNodeCollection based off of passed in ModuleActions + /// + /// Parent action + /// Parent node + /// Root Node. + /// ActionControl to base actions off of + /// How many levels deep should be populated + /// + /// + /// + /// [Jon Henning] 5/15/2006 Created + /// + /// ----------------------------------------------------------------------------- + private static void AddChildActions(ModuleAction parentAction, DNNNode parentNode, DNNNode rootNode, IActionControl actionControl, int intDepth) + { + //Add Menu Items + foreach (ModuleAction action in parentAction.Actions) + { + bool isActionPending = IsActionPending(parentNode, rootNode, intDepth); + if (action.Title == "~") + { + if (isActionPending == false) + { + //A title (text) of ~ denotes a break + parentNode.DNNNodes.AddBreak(); + } + } + else + { + //if action is visible and user has permission + if (action.Visible && + (action.Secure != SecurityAccessLevel.Anonymous || + (!ModuleHost.IsViewMode(actionControl.ModuleControl.ModuleContext.Configuration, PortalSettings.Current)) + && ModulePermissionController.HasModuleAccess(action.Secure, Null.NullString, actionControl.ModuleControl.ModuleContext.Configuration))) + { + if (isActionPending) + { + parentNode.HasNodes = true; + } + else + { + int i = parentNode.DNNNodes.Add(); + DNNNode node = parentNode.DNNNodes[i]; + node.ID = action.ID.ToString(); + node.Key = action.ID.ToString(); + node.Text = action.Title; //no longer including SPACE in generic node collection, each control must handle how they want to display + if (string.IsNullOrEmpty(action.ClientScript) && string.IsNullOrEmpty(action.Url) && string.IsNullOrEmpty(action.CommandArgument)) + { + node.Enabled = false; + } + else if (!string.IsNullOrEmpty(action.ClientScript)) + { + node.JSFunction = action.ClientScript; + node.ClickAction = eClickAction.None; + } + else + { + node.NavigateURL = action.Url; + if (action.UseActionEvent == false && !String.IsNullOrEmpty(node.NavigateURL)) + { + node.ClickAction = eClickAction.Navigate; + if (action.NewWindow) + { + node.Target = "_blank"; + } + } + else + { + node.ClickAction = eClickAction.PostBack; + } + } + node.Image = action.Icon; + if (action.HasChildren()) //if action has children then call function recursively + { + AddChildActions(action, node, rootNode, actionControl, intDepth); + } + } + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Assigns common properties from passed in tab to newly created DNNNode that is added to the passed in DNNNodeCollection + /// + /// Tab to base DNNNode off of + /// Node collection to append new node to + /// Hashtable of breadcrumb IDs to efficiently determine node's BreadCrumb property + /// Portal settings object to determine if node is selected + /// + /// + /// Logic moved to separate sub to make GetNavigationNodes cleaner + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + private static void AddNode(TabInfo objTab, DNNNodeCollection objNodes, Hashtable objBreadCrumbs, PortalSettings objPortalSettings, ToolTipSource eToolTips) + { + var objNode = new DNNNode(); + if (objTab.Title == "~") //NEW! + { + //A title (text) of ~ denotes a break + objNodes.AddBreak(); + } + else + { + //assign breadcrumb and selected properties + if (objBreadCrumbs.Contains(objTab.TabID)) + { + objNode.BreadCrumb = true; + if (objTab.TabID == objPortalSettings.ActiveTab.TabID) + { + objNode.Selected = true; + } + } + if (objTab.DisableLink) + { + objNode.Enabled = false; + } + objNode.ID = objTab.TabID.ToString(); + objNode.Key = objNode.ID; + objNode.Text = objTab.LocalizedTabName; + objNode.NavigateURL = objTab.FullUrl; + objNode.ClickAction = eClickAction.Navigate; + objNode.Image = objTab.IconFile; + objNode.LargeImage = objTab.IconFileLarge; + switch (eToolTips) + { + case ToolTipSource.TabName: + objNode.ToolTip = objTab.LocalizedTabName; + break; + case ToolTipSource.Title: + objNode.ToolTip = objTab.Title; + break; + case ToolTipSource.Description: + objNode.ToolTip = objTab.Description; + break; + } + bool newWindow = false; + if (objTab.TabSettings["LinkNewWindow"] != null && Boolean.TryParse((string)objTab.TabSettings["LinkNewWindow"], out newWindow) && newWindow) + { + objNode.Target = "_new"; + } + + objNodes.Add(objNode); + } + } + + private static bool IsActionPending(DNNNode objParentNode, DNNNode objRootNode, int intDepth) + { + //if we aren't restricting depth then its never pending + if (intDepth == -1) + { + return false; + } + + //parents level + 1 = current node level + //if current node level - (roots node level) <= the desired depth then not pending + if (objParentNode.Level + 1 - objRootNode.Level <= intDepth) + { + return false; + } + return true; + } + + private static bool IsTabPending(TabInfo objTab, DNNNode objParentNode, DNNNode objRootNode, int intDepth, Hashtable objBreadCrumbs, int intLastBreadCrumbId, bool blnPOD) + { + // + //A + //| + //--B + //| | + //| --B-1 + //| | | + //| | --B-1-1 + //| | | + //| | --B-1-2 + //| | + //| --B-2 + //| | + //| --B-2-1 + //| | + //| --B-2-2 + //| + //--C + // | + // --C-1 + // | | + // | --C-1-1 + // | | + // | --C-1-2 + // | + // --C-2 + // | + // --C-2-1 + // | + // --C-2-2 + + //if we aren't restricting depth then its never pending + if (intDepth == -1) + { + return false; + } + + //parents level + 1 = current node level + //if current node level - (roots node level) <= the desired depth then not pending + if (objParentNode.Level + 1 - objRootNode.Level <= intDepth) + { + return false; + } + + + //--- These checks below are here so tree becomes expands to selected node --- + if (blnPOD) + { + //really only applies to controls with POD enabled, since the root passed in may be some node buried down in the chain + //and the depth something like 1. We need to include the appropriate parent's and parent siblings + //Why is the check for POD required? Well to allow for functionality like RootOnly requests. We do not want any children + //regardless if they are a breadcrumb + + //if tab is in the breadcrumbs then obviously not pending + if (objBreadCrumbs.Contains(objTab.TabID)) + { + return false; + } + + //if parent is in the breadcrumb and it is not the last breadcrumb then not pending + //in tree above say we our breadcrumb is (A, B, B-2) we want our tree containing A, B, B-2 AND B-1 AND C since A and B are expanded + //we do NOT want B-2-1 and B-2-2, thus the check for Last Bread Crumb + if (objBreadCrumbs.Contains(objTab.ParentId) && intLastBreadCrumbId != objTab.ParentId) + { + return false; + } + } + return true; + } + + private static bool IsTabSibling(TabInfo objTab, int intStartTabId, Hashtable objTabLookup) + { + if (intStartTabId == -1) + { + if (objTab.ParentId == -1) + { + return true; + } + else + { + return false; + } + } + else if (objTab.ParentId == ((TabInfo) objTabLookup[intStartTabId]).ParentId) + { + return true; + } + else + { + return false; + } + } + + private static void ProcessTab(DNNNode objRootNode, TabInfo objTab, Hashtable objTabLookup, Hashtable objBreadCrumbs, int intLastBreadCrumbId, ToolTipSource eToolTips, int intStartTabId, + int intDepth, int intNavNodeOptions) + { + PortalSettings objPortalSettings = PortalController.GetCurrentPortalSettings(); + + DNNNodeCollection objRootNodes = objRootNode.DNNNodes; + + bool showHidden = (intNavNodeOptions & (int)NavNodeOptions.IncludeHiddenNodes) == (int)NavNodeOptions.IncludeHiddenNodes; + + if (CanShowTab(objTab, TabPermissionController.CanAdminPage(), true, showHidden)) //based off of tab properties, is it shown + { + DNNNodeCollection objParentNodes; + DNNNode objParentNode = objRootNodes.FindNode(objTab.ParentId.ToString()); + bool blnParentFound = objParentNode != null; + if (objParentNode == null) + { + objParentNode = objRootNode; + } + objParentNodes = objParentNode.DNNNodes; + if (objTab.TabID == intStartTabId) + { + //is this the starting tab + if ((intNavNodeOptions & (int) NavNodeOptions.IncludeParent) != 0) + { + //if we are including parent, make sure there is one, then add + if (objTabLookup[objTab.ParentId] != null) + { + AddNode((TabInfo) objTabLookup[objTab.ParentId], objParentNodes, objBreadCrumbs, objPortalSettings, eToolTips); + objParentNode = objRootNodes.FindNode(objTab.ParentId.ToString()); + objParentNodes = objParentNode.DNNNodes; + } + } + if ((intNavNodeOptions & (int) NavNodeOptions.IncludeSelf) != 0) + { + //if we are including our self (starting tab) then add + AddNode(objTab, objParentNodes, objBreadCrumbs, objPortalSettings, eToolTips); + } + } + else if (((intNavNodeOptions & (int) NavNodeOptions.IncludeSiblings) != 0) && IsTabSibling(objTab, intStartTabId, objTabLookup)) + { + //is this a sibling of the starting node, and we are including siblings, then add it + AddNode(objTab, objParentNodes, objBreadCrumbs, objPortalSettings, eToolTips); + } + else + { + if (blnParentFound) //if tabs parent already in hierarchy (as is the case when we are sending down more than 1 level) + { + //parent will be found for siblings. Check to see if we want them, if we don't make sure tab is not a sibling + if (((intNavNodeOptions & (int) NavNodeOptions.IncludeSiblings) != 0) || IsTabSibling(objTab, intStartTabId, objTabLookup) == false) + { + //determine if tab should be included or marked as pending + bool blnPOD = (intNavNodeOptions & (int) NavNodeOptions.MarkPendingNodes) != 0; + if (IsTabPending(objTab, objParentNode, objRootNode, intDepth, objBreadCrumbs, intLastBreadCrumbId, blnPOD)) + { + if (blnPOD) + { + objParentNode.HasNodes = true; //mark it as a pending node + } + } + else + { + AddNode(objTab, objParentNodes, objBreadCrumbs, objPortalSettings, eToolTips); + } + } + } + else if ((intNavNodeOptions & (int) NavNodeOptions.IncludeSelf) == 0 && objTab.ParentId == intStartTabId) + { + //if not including self and parent is the start id then add + AddNode(objTab, objParentNodes, objBreadCrumbs, objPortalSettings, eToolTips); + } + } + } + } + + #endregion + + #region Public Shared Methods + + public static bool CanShowTab(TabInfo objTab, bool isAdminMode, bool showDisabled) + { + bool showHidden = false; + return CanShowTab(objTab, isAdminMode, showDisabled, showHidden); + } + + public static bool CanShowTab(TabInfo objTab, bool isAdminMode, bool showDisabled, bool showHidden) + { + //if tab is visible, not deleted, not expired (or admin), and user has permission to see it... + if ((objTab.IsVisible || showHidden) && !objTab.IsDeleted && (!objTab.DisableLink || showDisabled) && + (((objTab.StartDate < DateTime.Now || objTab.StartDate == Null.NullDate) && (objTab.EndDate > DateTime.Now || objTab.EndDate == Null.NullDate)) || isAdminMode) && + TabPermissionController.CanNavigateToPage(objTab)) + { + return true; + } + else + { + return false; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Allows for DNNNode object to be easily obtained based off of passed in ID + /// + /// NodeID to retrieve + /// Namespace for node collection (usually control's ClientID) + /// Root Action object used in searching + /// ActionControl to base actions off of + /// DNNNode + /// + /// Primary purpose of this is to obtain the DNNNode needed for the events exposed by the NavigationProvider + /// + /// + /// [Jon Henning] 5/15/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNode GetActionNode(string strID, string strNamespace, ModuleAction objActionRoot, Control objControl) + { + DNNNodeCollection objNodes = GetActionNodes(objActionRoot, objControl, -1); + DNNNode objNode = objNodes.FindNode(strID); + var objReturnNodes = new DNNNodeCollection(strNamespace); + objReturnNodes.Import(objNode); + objReturnNodes[0].ID = strID; + return objReturnNodes[0]; + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the actions associated + /// to a module based off of the current user's context + /// + /// Root module action + /// ActionControl to base actions off of + /// + /// + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetActionNodes(ModuleAction objActionRoot, Control objControl) + { + return GetActionNodes(objActionRoot, objControl, -1); + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the actions associated + /// to a module based off of the current user's context + /// + /// Root module action + /// ActionControl to base actions off of + /// How many levels deep should be populated + /// + /// + /// + /// + /// [Jon Henning] 5/15/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetActionNodes(ModuleAction objActionRoot, Control objControl, int intDepth) + { + var objCol = new DNNNodeCollection(objControl.ClientID); + + var objActionControl = objControl as IActionControl; + if (objActionControl != null) + { + if (objActionRoot.Visible) + { + objCol.Add(); + DNNNode objRoot = objCol[0]; + objRoot.ID = objActionRoot.ID.ToString(); + objRoot.Key = objActionRoot.ID.ToString(); + objRoot.Text = objActionRoot.Title; + objRoot.NavigateURL = objActionRoot.Url; + objRoot.Image = objActionRoot.Icon; + objRoot.Enabled = false; + AddChildActions(objActionRoot, objRoot, objRoot.ParentNode, objActionControl, intDepth); + } + } + return objCol; + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the actions associated + /// to a module based off of the current user's context + /// + /// Root module action + /// Root node on which to populate children + /// ActionControl to base actions off of + /// How many levels deep should be populated + /// + /// + /// + /// + /// [Jon Henning] 5/15/2006 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetActionNodes(ModuleAction objActionRoot, DNNNode objRootNode, Control objControl, int intDepth) + { + DNNNodeCollection objCol = objRootNode.ParentNode.DNNNodes; + var objActionControl = objControl as IActionControl; + if (objActionControl != null) + { + AddChildActions(objActionRoot, objRootNode, objRootNode, objActionControl, intDepth); + } + return objCol; + } + + /// ----------------------------------------------------------------------------- + /// + /// Allows for DNNNode object to be easily obtained based off of passed in ID + /// + /// NodeID to retrieve + /// Namespace for node collection (usually control's ClientID) + /// DNNNode + /// + /// Primary purpose of this is to obtain the DNNNode needed for the events exposed by the NavigationProvider + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNode GetNavigationNode(string strID, string strNamespace) + { + //TODO: FIX THIS MESS! + DNNNodeCollection objNodes = GetNavigationNodes(strNamespace); + DNNNode objNode = objNodes.FindNode(strID); + var objReturnNodes = new DNNNodeCollection(strNamespace); + objReturnNodes.Import(objNode); + objReturnNodes[0].ID = strID; + return objReturnNodes[0]; + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the pages/tabs included in + /// the current context's (user) navigation hierarchy + /// + /// Namespace (typically control's ClientID) of node collection to create + /// Collection of DNNNodes + /// + /// Returns all navigation nodes for a given user + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetNavigationNodes(string strNamespace) + { + return GetNavigationNodes(strNamespace, ToolTipSource.None, -1, -1, 0); + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the pages/tabs included in + /// the current context's (user) navigation hierarchy + /// + /// Namespace (typically control's ClientID) of node collection to create + /// Enumerator to determine what text to display in the tooltips + /// If using Populate On Demand, then this is the tab id of the root element to retrieve (-1 for no POD) + /// If Populate On Demand is enabled, then this parameter determines the number of nodes to retrieve beneath the starting tab passed in (intStartTabId) (-1 for no POD) + /// Bitwise integer containing values to determine what nodes to display (self, siblings, parent) + /// Collection of DNNNodes + /// + /// Returns a subset of navigation nodes based off of passed in starting node id and depth + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetNavigationNodes(string strNamespace, ToolTipSource eToolTips, int intStartTabId, int intDepth, int intNavNodeOptions) + { + var objCol = new DNNNodeCollection(strNamespace); + return GetNavigationNodes(new DNNNode(objCol.XMLNode), eToolTips, intStartTabId, intDepth, intNavNodeOptions); + } + + /// ----------------------------------------------------------------------------- + /// + /// This function provides a central location to obtain a generic node collection of the pages/tabs included in + /// the current context's (user) navigation hierarchy + /// + /// Node in which to add children to + /// Enumerator to determine what text to display in the tooltips + /// If using Populate On Demand, then this is the tab id of the root element to retrieve (-1 for no POD) + /// If Populate On Demand is enabled, then this parameter determines the number of nodes to retrieve beneath the starting tab passed in (intStartTabId) (-1 for no POD) + /// Bitwise integer containing values to determine what nodes to display (self, siblings, parent) + /// Collection of DNNNodes + /// + /// Returns a subset of navigation nodes based off of passed in starting node id and depth + /// + /// + /// [Jon Henning] 8/9/2005 Created + /// + /// ----------------------------------------------------------------------------- + public static DNNNodeCollection GetNavigationNodes(DNNNode objRootNode, ToolTipSource eToolTips, int intStartTabId, int intDepth, int intNavNodeOptions) + { + int i; + PortalSettings objPortalSettings = PortalController.GetCurrentPortalSettings(); + bool blnFoundStart = intStartTabId == -1; + + var objBreadCrumbs = new Hashtable(); + var objTabLookup = new Hashtable(); + DNNNodeCollection objRootNodes = objRootNode.DNNNodes; + int intLastBreadCrumbId = 0; + + //--- cache breadcrumbs in hashtable so we can easily set flag on node denoting it as a breadcrumb node (without looping multiple times) --- + for (i = 0; i <= (objPortalSettings.ActiveTab.BreadCrumbs.Count - 1); i++) + { + objBreadCrumbs.Add(((TabInfo) objPortalSettings.ActiveTab.BreadCrumbs[i]).TabID, 1); + intLastBreadCrumbId = ((TabInfo) objPortalSettings.ActiveTab.BreadCrumbs[i]).TabID; + } + var objTabController = new TabController(); + List portalTabs = TabController.GetTabsBySortOrder(objPortalSettings.PortalId, objPortalSettings.CultureCode, true); + List hostTabs = TabController.GetTabsBySortOrder(Null.NullInteger, Localization.SystemLocale, true); + foreach (TabInfo objTab in portalTabs) + { + objTabLookup.Add(objTab.TabID, objTab); + } + foreach (TabInfo objTab in hostTabs) + { + objTabLookup.Add(objTab.TabID, objTab); + } + foreach (TabInfo objTab in portalTabs) + { + try + { + ProcessTab(objRootNode, objTab, objTabLookup, objBreadCrumbs, intLastBreadCrumbId, eToolTips, intStartTabId, intDepth, intNavNodeOptions); + } + catch (Exception ex) + { + throw ex; + } + } + foreach (TabInfo objTab in hostTabs) + { + try + { + ProcessTab(objRootNode, objTab, objTabLookup, objBreadCrumbs, intLastBreadCrumbId, eToolTips, intStartTabId, intDepth, intNavNodeOptions); + } + catch (Exception ex) + { + throw ex; + } + } + return objRootNodes; + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/Controls/ControlPanel.cs b/DNN Platform/Library/UI/Skins/Controls/ControlPanel.cs new file mode 100644 index 00000000000..9bfb2d77c4d --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Controls/ControlPanel.cs @@ -0,0 +1,68 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.Web.UI.HtmlControls; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Host; +using DotNetNuke.UI.ControlPanels; +using DotNetNuke.Web.Client; +using DotNetNuke.Web.Client.ClientResourceManagement; + +namespace DotNetNuke.UI.Skins.Controls +{ + public class ControlPanel : SkinObjectBase + { + public bool IsDockable { get; set; } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + if (Request.QueryString["dnnprintmode"] != "true" && Request.QueryString["popUp"] != "true") + { + var objControlPanel = ControlUtilities.LoadControl(this, Host.ControlPanel); + var objForm = (HtmlForm)Page.FindControl("Form"); + + if(objControlPanel.IncludeInControlHierarchy) + { + objControlPanel.IsDockable = IsDockable; + if (!Host.ControlPanel.ToLowerInvariant().EndsWith("controlbar.ascx")) + Controls.Add(objControlPanel); + else + { + if (objForm != null) + { + objForm.Controls.AddAt(0, objControlPanel); + } + else + { + Page.Controls.AddAt(0, objControlPanel); + } + } + + //register admin.css + ClientResourceManager.RegisterAdminStylesheet(Page, Globals.HostPath + "admin.css"); + } + } + } + } +} diff --git a/DNN Platform/Library/UI/Skins/Controls/LanguageTokenReplace.cs b/DNN Platform/Library/UI/Skins/Controls/LanguageTokenReplace.cs new file mode 100644 index 00000000000..722dafb1296 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Controls/LanguageTokenReplace.cs @@ -0,0 +1,247 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Specialized; +using System.Globalization; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Security; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Tokens; + +#endregion + +namespace DotNetNuke.UI.Skins.Controls +{ + public class LanguageTokenReplace : TokenReplace + { + //see http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=6505 + public LanguageTokenReplace() + : base(Scope.NoSettings) + { + UseObjectLessExpression = true; + PropertySource[ObjectLessToken] = new LanguagePropertyAccess(this, Globals.GetPortalSettings()); + } + + public string resourceFile { get; set; } + } + + public class LanguagePropertyAccess : IPropertyAccess + { + private readonly PortalSettings objPortal; + public LanguageTokenReplace objParent; + + public LanguagePropertyAccess(LanguageTokenReplace parent, PortalSettings settings) + { + objPortal = settings; + objParent = parent; + } + + #region IPropertyAccess Members + + public string GetProperty(string propertyName, string format, CultureInfo formatProvider, UserInfo AccessingUser, Scope CurrentScope, ref bool PropertyNotFound) + { + switch (propertyName.ToLowerInvariant()) + { + case "url": + return NewUrl(objParent.Language); + case "flagsrc": + return "/" + objParent.Language + ".gif"; + case "selected": + return (objParent.Language == CultureInfo.CurrentCulture.Name).ToString(); + case "label": + return Localization.GetString("Label", objParent.resourceFile); + case "i": + return Globals.ResolveUrl("~/images/Flags"); + case "p": + return Globals.ResolveUrl(PathUtils.Instance.RemoveTrailingSlash(objPortal.HomeDirectory)); + case "s": + return Globals.ResolveUrl(PathUtils.Instance.RemoveTrailingSlash(objPortal.ActiveTab.SkinPath)); + case "g": + return Globals.ResolveUrl("~/portals/" + Globals.glbHostSkinFolder); + default: + PropertyNotFound = true; + return string.Empty; + } + } + + public CacheLevel Cacheability + { + get + { + return CacheLevel.fullyCacheable; + } + } + + #endregion + + #region Private Methods + + + /// + /// getQSParams builds up a new querystring. This is necessary + /// in order to prep for navigateUrl. + /// we don't ever want a tabid, a ctl and a language parameter in the qs + /// also, the portalid param is not allowed when the tab is a supertab + /// (because NavigateUrl adds the portalId param to the qs) + /// + /// Language to switch into + /// + /// + private string[] GetQsParams(string newLanguage, bool isLocalized) + { + string returnValue = ""; + NameValueCollection queryStringCollection = HttpContext.Current.Request.QueryString; + var rawQueryStringCollection = + HttpUtility.ParseQueryString(new Uri(HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.RawUrl).Query); + + PortalSettings settings = PortalController.GetCurrentPortalSettings(); + string[] arrKeys = queryStringCollection.AllKeys; + + for (int i = 0; i <= arrKeys.GetUpperBound(0); i++) + { + if (arrKeys[i] != null) + { + switch (arrKeys[i].ToLowerInvariant()) + { + case "tabid": + case "ctl": + case "language": //skip parameter + break; + case "mid": + case "moduleid": //start of patch (Manzoni Fausto) gemini 14205 + if (isLocalized) + { + string ModuleIdKey = arrKeys[i].ToLowerInvariant(); + int moduleID; + int tabid; + + int.TryParse(queryStringCollection[ModuleIdKey], out moduleID); + int.TryParse(queryStringCollection["tabid"], out tabid); + ModuleInfo localizedModule = new ModuleController().GetModuleByCulture(moduleID, tabid, settings.PortalId, LocaleController.Instance.GetLocale(newLanguage)); + if (localizedModule != null) + { + if (!string.IsNullOrEmpty(returnValue)) + { + returnValue += "&"; + } + returnValue += ModuleIdKey + "=" + localizedModule.ModuleID; + } + } + break; + default: + if ((arrKeys[i].ToLowerInvariant() == "portalid") && objPortal.ActiveTab.IsSuperTab) + { + //skip parameter + //navigateURL adds portalid to querystring if tab is superTab + } + else + { + if (!string.IsNullOrEmpty(rawQueryStringCollection.Get(arrKeys[i]))) + { + //skip parameter as it is part of a querystring param that has the following form + // [friendlyURL]/?param=value + // gemini 25516 + } + else + { + string[] arrValues = queryStringCollection.GetValues(i); + if (arrValues != null) + { + for (int j = 0; j <= arrValues.GetUpperBound(0); j++) + { + if (!String.IsNullOrEmpty(returnValue)) + { + returnValue += "&"; + } + var qsv = arrKeys[i]; + qsv = qsv.Replace("\"", ""); + qsv = qsv.Replace("'", ""); + returnValue += qsv + "=" + HttpUtility.UrlEncode(arrValues[j]); + } + } + } + } + break; + } + } + } + + if (!settings.ContentLocalizationEnabled && LocaleController.Instance.GetLocales(settings.PortalId).Count > 1 && !settings.EnableUrlLanguage) + { + //because useLanguageInUrl is false, navigateUrl won't add a language param, so we need to do that ourselves + if (returnValue != "") + { + returnValue += "&"; + } + returnValue += "language=" + newLanguage.ToLower(); + } + + //return the new querystring as a string array + return returnValue.Split('&'); + } + + /// + /// newUrl returns the new URL based on the new language. + /// Basically it is just a call to NavigateUrl, with stripped qs parameters + /// + /// + /// + /// [erikvb] 20070814 added + /// + private string NewUrl(string newLanguage) + { + var objSecurity = new PortalSecurity(); + Locale newLocale = LocaleController.Instance.GetLocale(newLanguage); + + //Ensure that the current ActiveTab is the culture of the new language + int tabId = objPortal.ActiveTab.TabID; + bool islocalized = false; + + TabInfo localizedTab = new TabController().GetTabByCulture(tabId, objPortal.PortalId, newLocale); + if (localizedTab != null) + { + islocalized = true; + tabId = localizedTab.TabID; + } + + + var rawQueryString = new Uri(HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.RawUrl).Query; + + return + objSecurity.InputFilter( + Globals.NavigateURL(tabId, objPortal.ActiveTab.IsSuperTab, objPortal, HttpContext.Current.Request.QueryString["ctl"], newLanguage, GetQsParams(newLocale.Code, islocalized)) + + rawQueryString, + PortalSecurity.FilterFlag.NoScripting); + } + + #endregion + + } +} diff --git a/DNN Platform/Library/UI/Skins/Controls/ModuleMessage.cs b/DNN Platform/Library/UI/Skins/Controls/ModuleMessage.cs new file mode 100644 index 00000000000..a66f6893f17 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Controls/ModuleMessage.cs @@ -0,0 +1,154 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.Skins.Controls +{ + + /// + /// + /// + /// [cniknet] 10/15/2004 Replaced public members with properties and removed + /// brackets from property names + /// + public class ModuleMessage : SkinObjectBase + { + #region ModuleMessageType enum + + public enum ModuleMessageType + { + GreenSuccess, + YellowWarning, + RedError, + BlueInfo + } + + #endregion + #region "Private Members" + + protected Panel dnnSkinMessage; + protected Label lblHeading; + protected Label lblMessage; + protected Control scrollScript; + + #endregion + + #region "Public Members" + + public string Text { get; set; } + + public string Heading { get; set; } + + public ModuleMessageType IconType { get; set; } + + public string IconImage { get; set; } + + /// + /// Check this message is shown as page message or module message. + /// + public bool IsModuleMessage + { + get + { + return this.Parent.ID == "MessagePlaceHolder"; + } + } + + #endregion + + #region "Protected Methods" + + /// + /// The Page_Load server event handler on this page is used + /// to populate the role information for the page + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + try + { + var strMessage = ""; + + //check to see if a url + //was passed in for an icon + if (!String.IsNullOrEmpty(IconImage)) + { + strMessage += Text; + dnnSkinMessage.CssClass = "dnnFormMessage dnnFormWarning"; + } + else + { + switch (IconType) + { + case ModuleMessageType.GreenSuccess: + strMessage += Text; + dnnSkinMessage.CssClass = "dnnFormMessage dnnFormSuccess"; + break; + case ModuleMessageType.YellowWarning: + strMessage += Text; + dnnSkinMessage.CssClass = "dnnFormMessage dnnFormWarning"; + break; + case ModuleMessageType.BlueInfo: + strMessage += Text; + dnnSkinMessage.CssClass = "dnnFormMessage dnnFormInfo"; + break; + case ModuleMessageType.RedError: + strMessage += Text; + dnnSkinMessage.CssClass = "dnnFormMessage dnnFormValidationSummary"; + break; + } + } + lblMessage.Text = strMessage; + + if (!String.IsNullOrEmpty(Heading)) + { + lblHeading.Visible = true; + lblHeading.Text = Heading; + } + } + catch (Exception exc) //Control failed to load + { + Exceptions.ProcessModuleLoadException(this, exc, false); + } + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + //set the scroll js only shown for module message and in postback mode. + scrollScript.Visible = IsPostBack && IsModuleMessage; + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/Controls/SkinsEditControl.cs b/DNN Platform/Library/UI/Skins/Controls/SkinsEditControl.cs new file mode 100644 index 00000000000..2644f126033 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Controls/SkinsEditControl.cs @@ -0,0 +1,408 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Web.UI; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Icons; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Utilities; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Skins.Controls +{ + /// ----------------------------------------------------------------------------- + /// Project: DotNetNuke + /// Namespace: DotNetNuke.UI.Skins.Controls + /// Class: SkinsEditControl + /// ----------------------------------------------------------------------------- + /// + /// The SkinsEditControl control provides a standard UI component for editing + /// skins. + /// + /// + /// + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + [ToolboxData("<{0}:SkinsEditControl runat=server>")] + public class SkinsEditControl : EditControl, IPostBackEventHandler + { + private string _AddedItem = Null.NullString; + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a SkinsEditControl + /// + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public SkinsEditControl() + { + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a SkinsEditControl + /// + /// The type of the property + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + public SkinsEditControl(string type) + { + SystemType = type; + } + + #endregion + + #region "Protected Properties" + + /// ----------------------------------------------------------------------------- + /// + /// DictionaryValue returns the Dictionary(Of Integer, String) representation of the Value + /// + /// A Dictionary(Of Integer, String) representing the Value + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected Dictionary DictionaryValue + { + get + { + return Value as Dictionary; + } + set + { + Value = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OldDictionaryValue returns the Dictionary(Of Integer, String) representation of the OldValue + /// + /// A Dictionary(Of Integer, String) representing the OldValue + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected Dictionary OldDictionaryValue + { + get + { + return OldValue as Dictionary; + } + set + { + OldValue = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// OldStringValue returns the String representation of the OldValue + /// + /// A String representing the OldValue + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected string OldStringValue + { + get + { + string strValue = Null.NullString; + if (OldDictionaryValue != null) + { + foreach (string Skin in OldDictionaryValue.Values) + { + strValue += Skin + ","; + } + } + return strValue; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// StringValue is the value of the control expressed as a String + /// + /// A string representing the Value + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override string StringValue + { + get + { + string strValue = Null.NullString; + if (DictionaryValue != null) + { + foreach (string Skin in DictionaryValue.Values) + { + strValue += Skin + ","; + } + } + return strValue; + } + set + { + Value = value; + } + } + + protected string AddedItem + { + get + { + return _AddedItem; + } + set + { + _AddedItem = value; + } + } + + #region IPostBackEventHandler Members + + public void RaisePostBackEvent(string eventArgument) + { + PropertyEditorEventArgs args; + switch (eventArgument.Substring(0, 3)) + { + case "Del": + args = new PropertyEditorEventArgs(Name); + args.Value = DictionaryValue; + args.OldValue = OldDictionaryValue; + args.Key = int.Parse(eventArgument.Substring(7)); + args.Changed = true; + base.OnItemDeleted(args); + break; + case "Add": + args = new PropertyEditorEventArgs(Name); + args.Value = AddedItem; + args.StringValue = AddedItem; + args.Changed = true; + base.OnItemAdded(args); + break; + } + } + + #endregion + + #endregion + + #region "Protected Methods" + + /// ----------------------------------------------------------------------------- + /// + /// OnDataChanged runs when the PostbackData has changed. It raises the ValueChanged + /// Event + /// + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnDataChanged(EventArgs e) + { + var args = new PropertyEditorEventArgs(Name); + args.Value = DictionaryValue; + args.OldValue = OldDictionaryValue; + args.StringValue = ""; + args.Changed = true; + base.OnValueChanged(args); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnPreRender runs just before the control is due to be rendered + /// + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + //Register control for PostBack + Page.RegisterRequiresPostBack(this); + } + + /// ----------------------------------------------------------------------------- + /// + /// RenderEditMode renders the Edit mode of the control + /// + /// A HtmlTextWriter. + /// + /// [cnurse] 02/05/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void RenderEditMode(HtmlTextWriter writer) + { + int length = Null.NullInteger; + if ((CustomAttributes != null)) + { + foreach (Attribute attribute in CustomAttributes) + { + if (attribute is MaxLengthAttribute) + { + var lengthAtt = (MaxLengthAttribute) attribute; + length = lengthAtt.Length; + break; + } + } + } + if (DictionaryValue != null) + { + foreach (KeyValuePair kvp in DictionaryValue) + { + //Render Hyperlink + writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, "Delete_" + kvp.Key, false)); + writer.AddAttribute(HtmlTextWriterAttribute.Onclick, "javascript:return confirm('" + ClientAPI.GetSafeJSString(Localization.GetString("DeleteItem")) + "');"); + writer.AddAttribute(HtmlTextWriterAttribute.Title, Localization.GetString("cmdDelete", LocalResourceFile)); + writer.RenderBeginTag(HtmlTextWriterTag.A); + + //Render Image + writer.AddAttribute(HtmlTextWriterAttribute.Src, IconController.IconURL("Delete")); + writer.AddAttribute(HtmlTextWriterAttribute.Border, "0"); + writer.RenderBeginTag(HtmlTextWriterTag.Img); + + //Render end of Image + writer.RenderEndTag(); + + //Render end of Hyperlink + writer.RenderEndTag(); + + ControlStyle.AddAttributesToRender(writer); + writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); + writer.AddAttribute(HtmlTextWriterAttribute.Value, kvp.Value); + if (length > Null.NullInteger) + { + writer.AddAttribute(HtmlTextWriterAttribute.Maxlength, length.ToString()); + } + writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID + "_skin" + kvp.Key); + writer.RenderBeginTag(HtmlTextWriterTag.Input); + writer.RenderEndTag(); + + writer.WriteBreak(); + } + writer.WriteBreak(); + + //Create Add Row + //Render Hyperlink + writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, "Add", false)); + writer.AddAttribute(HtmlTextWriterAttribute.Title, Localization.GetString("cmdAdd", LocalResourceFile)); + writer.RenderBeginTag(HtmlTextWriterTag.A); + + //Render Image + writer.AddAttribute(HtmlTextWriterAttribute.Src, IconController.IconURL("Add")); + writer.AddAttribute(HtmlTextWriterAttribute.Border, "0"); + writer.RenderBeginTag(HtmlTextWriterTag.Img); + + //Render end of Image + writer.RenderEndTag(); + + //Render end of Hyperlink + writer.RenderEndTag(); + + ControlStyle.AddAttributesToRender(writer); + writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); + writer.AddAttribute(HtmlTextWriterAttribute.Value, Null.NullString); + if (length > Null.NullInteger) + { + writer.AddAttribute(HtmlTextWriterAttribute.Maxlength, length.ToString()); + } + writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID + "_skinnew"); + writer.RenderBeginTag(HtmlTextWriterTag.Input); + writer.RenderEndTag(); + writer.WriteBreak(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// RenderViewMode renders the View (readonly) mode of the control + /// + /// A HtmlTextWriter. + /// + /// [cnurse] 02/04/2008 created + /// + /// ----------------------------------------------------------------------------- + protected override void RenderViewMode(HtmlTextWriter writer) + { + if (DictionaryValue != null) + { + foreach (KeyValuePair kvp in DictionaryValue) + { + ControlStyle.AddAttributesToRender(writer); + writer.RenderBeginTag(HtmlTextWriterTag.Span); + writer.Write(kvp.Value); + writer.RenderEndTag(); + writer.WriteBreak(); + } + } + } + + #endregion + + public override bool LoadPostData(string postDataKey, NameValueCollection postCollection) + { + bool dataChanged = false; + string postedValue; + var newDictionaryValue = new Dictionary(); + foreach (KeyValuePair kvp in DictionaryValue) + { + postedValue = postCollection[UniqueID + "_skin" + kvp.Key]; + if (kvp.Value.Equals(postedValue)) + { + newDictionaryValue[kvp.Key] = kvp.Value; + } + else + { + newDictionaryValue[kvp.Key] = postedValue; + dataChanged = true; + } + } + postedValue = postCollection[UniqueID + "_skinnew"]; + if (!string.IsNullOrEmpty(postedValue)) + { + AddedItem = postedValue; + } + DictionaryValue = newDictionaryValue; + return dataChanged; + } + } +} diff --git a/DNN Platform/Library/UI/Skins/Controls/SolPartMenu.cs b/DNN Platform/Library/UI/Skins/Controls/SolPartMenu.cs new file mode 100644 index 00000000000..cefd68c470e --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Controls/SolPartMenu.cs @@ -0,0 +1,1166 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +using DotNetNuke.Common; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Skins.Controls +{ + /// ----------------------------------------------------------------------------- + /// + /// + /// + /// [cniknet] 10/15/2004 Replaced public members with properties and removed + /// brackets from property names + /// + /// ----------------------------------------------------------------------------- + public class SolPartMenu : NavObjectBase + { + #region "Public Members" + + public string SeparateCss { get; set; } + + public string MenuBarCssClass + { + get + { + return CSSControl; + } + set + { + CSSControl = value; + } + } + + public string MenuContainerCssClass + { + get + { + return CSSContainerRoot; + } + set + { + CSSContainerRoot = value; + } + } + + public string MenuItemCssClass + { + get + { + return CSSNode; + } + set + { + CSSNode = value; + } + } + + public string MenuIconCssClass + { + get + { + return CSSIcon; + } + set + { + CSSIcon = value; + } + } + + public string SubMenuCssClass + { + get + { + return CSSContainerSub; + } + set + { + CSSContainerSub = value; + } + } + + public string MenuItemSelCssClass + { + get + { + return CSSNodeHover; + } + set + { + CSSNodeHover = value; + } + } + + public string MenuBreakCssClass + { + get + { + return CSSBreak; + } + set + { + CSSBreak = value; + } + } + + public string MenuArrowCssClass + { + get + { + return CSSIndicateChildSub; + } + set + { + CSSIndicateChildSub = value; + } + } + + public string MenuRootArrowCssClass + { + get + { + return CSSIndicateChildRoot; + } + set + { + CSSIndicateChildRoot = value; + } + } + + public string BackColor + { + get + { + return StyleBackColor; + } + set + { + StyleBackColor = value; + } + } + + public string ForeColor + { + get + { + return StyleForeColor; + } + set + { + StyleForeColor = value; + } + } + + public string HighlightColor + { + get + { + return StyleHighlightColor; + } + set + { + StyleHighlightColor = value; + } + } + + public string IconBackgroundColor + { + get + { + return StyleIconBackColor; + } + set + { + StyleIconBackColor = value; + } + } + + public string SelectedBorderColor + { + get + { + return StyleSelectionBorderColor; + } + set + { + StyleSelectionBorderColor = value; + } + } + + public string SelectedColor + { + get + { + return StyleSelectionColor; + } + set + { + StyleSelectionColor = value; + } + } + + public string SelectedForeColor + { + get + { + return StyleSelectionForeColor; + } + set + { + StyleSelectionForeColor = value; + } + } + + public string Display + { + get + { + return ControlOrientation; + } + set + { + ControlOrientation = value; + } + } + + public string MenuBarHeight + { + get + { + return StyleControlHeight; + } + set + { + StyleControlHeight = value; + } + } + + public string MenuBorderWidth + { + get + { + return StyleBorderWidth; + } + set + { + StyleBorderWidth = value; + } + } + + public string MenuItemHeight + { + get + { + return StyleNodeHeight; + } + set + { + StyleNodeHeight = value; + } + } + + public string Moveable + { + get + { + return string.Empty; + } + set + { + } + } + + public string IconWidth + { + get + { + return StyleIconWidth; + } + set + { + StyleIconWidth = value; + } + } + + public string MenuEffectsShadowColor + { + get + { + return EffectsShadowColor; + } + set + { + EffectsShadowColor = value; + } + } + + public string MenuEffectsMouseOutHideDelay + { + get + { + return MouseOutHideDelay; + } + set + { + MouseOutHideDelay = value; + } + } + + public string MenuEffectsMouseOverDisplay + { + get + { + return MouseOverDisplay; + } + set + { + MouseOverDisplay = value; + } + } + + public string MenuEffectsMouseOverExpand + { + get + { + return MouseOverAction; + } + set + { + MouseOverAction = value; + } + } + + public string MenuEffectsStyle + { + get + { + return EffectsStyle; + } + set + { + EffectsStyle = value; + } + } + + public string FontNames + { + get + { + return StyleFontNames; + } + set + { + StyleFontNames = value; + } + } + + public string FontSize + { + get + { + return StyleFontSize; + } + set + { + StyleFontSize = value; + } + } + + public string FontBold + { + get + { + return StyleFontBold; + } + set + { + StyleFontBold = value; + } + } + + public string MenuEffectsShadowStrength + { + get + { + return EffectsShadowStrength; + } + set + { + EffectsShadowStrength = value; + } + } + + public string MenuEffectsMenuTransition + { + get + { + return EffectsTransition; + } + set + { + EffectsTransition = value; + } + } + + public string MenuEffectsMenuTransitionLength + { + get + { + return EffectsDuration; + } + set + { + EffectsDuration = value; + } + } + + public string MenuEffectsShadowDirection + { + get + { + return EffectsShadowDirection; + } + set + { + EffectsShadowDirection = value; + } + } + + public string ForceFullMenuList + { + get + { + return ForceCrawlerDisplay; + } + set + { + ForceCrawlerDisplay = value; + } + } + + public string UseSkinPathArrowImages { get; set; } + + public string UseRootBreadCrumbArrow { get; set; } + + public string UseSubMenuBreadCrumbArrow { get; set; } + + public string RootMenuItemBreadCrumbCssClass + { + get + { + return CSSBreadCrumbRoot; + } + set + { + CSSBreadCrumbRoot = value; + } + } + + public string SubMenuItemBreadCrumbCssClass + { + get + { + return CSSBreadCrumbSub; + } + set + { + CSSBreadCrumbSub = value; + } + } + + public string RootMenuItemCssClass + { + get + { + return CSSNodeRoot; + } + set + { + CSSNodeRoot = value; + } + } + + public string RootBreadCrumbArrow { get; set; } + + public string SubMenuBreadCrumbArrow { get; set; } + + public string UseArrows + { + get + { + return IndicateChildren; + } + set + { + IndicateChildren = value; + } + } + + public string DownArrow { get; set; } + + public string RightArrow { get; set; } + + public string RootMenuItemActiveCssClass + { + get + { + return CSSNodeSelectedRoot; + } + set + { + CSSNodeSelectedRoot = value; + } + } + + public string SubMenuItemActiveCssClass + { + get + { + return CSSNodeSelectedSub; + } + set + { + CSSNodeSelectedSub = value; + } + } + + public string RootMenuItemSelectedCssClass + { + get + { + return CSSNodeHoverRoot; + } + set + { + CSSNodeHoverRoot = value; + } + } + + public string SubMenuItemSelectedCssClass + { + get + { + return CSSNodeHoverSub; + } + set + { + CSSNodeHoverSub = value; + } + } + + public string Separator + { + get + { + return SeparatorHTML; + } + set + { + SeparatorHTML = value; + } + } + + public string SeparatorCssClass + { + get + { + return CSSSeparator; + } + set + { + CSSSeparator = value; + } + } + + public string RootMenuItemLeftHtml + { + get + { + return NodeLeftHTMLRoot; + } + set + { + NodeLeftHTMLRoot = value; + } + } + + public string RootMenuItemRightHtml + { + get + { + return NodeRightHTMLRoot; + } + set + { + NodeRightHTMLRoot = value; + } + } + + public string SubMenuItemLeftHtml + { + get + { + return NodeLeftHTMLSub; + } + set + { + NodeLeftHTMLSub = value; + } + } + + public string SubMenuItemRightHtml + { + get + { + return NodeRightHTMLSub; + } + set + { + NodeRightHTMLSub = value; + } + } + + public string LeftSeparator + { + get + { + return SeparatorLeftHTML; + } + set + { + SeparatorLeftHTML = value; + } + } + + public string RightSeparator + { + get + { + return SeparatorRightHTML; + } + set + { + SeparatorRightHTML = value; + } + } + + public string LeftSeparatorActive + { + get + { + return SeparatorLeftHTMLActive; + } + set + { + SeparatorLeftHTMLActive = value; + } + } + + public string RightSeparatorActive + { + get + { + return SeparatorRightHTMLActive; + } + set + { + SeparatorRightHTMLActive = value; + } + } + + public string LeftSeparatorBreadCrumb + { + get + { + return SeparatorLeftHTMLBreadCrumb; + } + set + { + SeparatorLeftHTMLBreadCrumb = value; + } + } + + public string RightSeparatorBreadCrumb + { + get + { + return SeparatorRightHTMLBreadCrumb; + } + set + { + SeparatorRightHTMLBreadCrumb = value; + } + } + + public string LeftSeparatorCssClass + { + get + { + return CSSLeftSeparator; + } + set + { + CSSLeftSeparator = value; + } + } + + public string RightSeparatorCssClass + { + get + { + return CSSRightSeparator; + } + set + { + CSSRightSeparator = value; + } + } + + public string LeftSeparatorActiveCssClass + { + get + { + return CSSLeftSeparatorSelection; + } + set + { + CSSLeftSeparatorSelection = value; + } + } + + public string RightSeparatorActiveCssClass + { + get + { + return CSSRightSeparatorSelection; + } + set + { + CSSRightSeparatorSelection = value; + } + } + + public string LeftSeparatorBreadCrumbCssClass + { + get + { + return CSSLeftSeparatorBreadCrumb; + } + set + { + CSSLeftSeparatorBreadCrumb = value; + } + } + + public string RightSeparatorBreadCrumbCssClass + { + get + { + return CSSRightSeparatorBreadCrumb; + } + set + { + CSSRightSeparatorBreadCrumb = value; + } + } + + public string MenuAlignment + { + get + { + return ControlAlignment; + } + set + { + ControlAlignment = value; + } + } + + public string ClearDefaults { get; set; } + + public string DelaySubmenuLoad + { + get + { + return string.Empty; + } + set + { + } + } + + public string RootOnly { get; set; } + + #endregion + + #region "Protected Methods" + + /// + /// The Page_Load server event handler on this page is used + /// to populate the role information for the page + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + + try + { + bool blnUseSkinPathArrowImages = bool.Parse(GetValue(UseSkinPathArrowImages, "False")); + bool blnUseRootBreadcrumbArrow = bool.Parse(GetValue(UseRootBreadCrumbArrow, "True")); + bool blnUseSubMenuBreadcrumbArrow = bool.Parse(GetValue(UseSubMenuBreadCrumbArrow, "False")); + bool blnUseArrows = bool.Parse(GetValue(UseArrows, "True")); + bool blnRootOnly = bool.Parse(GetValue(RootOnly, "False")); + string strRootBreadcrumbArrow; + string strSubMenuBreadcrumbArrow; + string strRightArrow; + string strDownArrow; + if (blnRootOnly) + { + blnUseArrows = false; + PopulateNodesFromClient = false; + StartTabId = -1; + ExpandDepth = 1; + } + var objSkins = new SkinController(); + //image for root menu breadcrumb marking + if (!String.IsNullOrEmpty(RootBreadCrumbArrow)) + { + strRootBreadcrumbArrow = PortalSettings.ActiveTab.SkinPath + RootBreadCrumbArrow; + } + else + { + strRootBreadcrumbArrow = Globals.ApplicationPath + "/images/breadcrumb.gif"; + } + + //image for submenu breadcrumb marking + if (!String.IsNullOrEmpty(SubMenuBreadCrumbArrow)) + { + strSubMenuBreadcrumbArrow = PortalSettings.ActiveTab.SkinPath + SubMenuBreadCrumbArrow; + } + if (blnUseSubMenuBreadcrumbArrow) + { + strSubMenuBreadcrumbArrow = Globals.ApplicationPath + "/images/breadcrumb.gif"; + NodeLeftHTMLBreadCrumbSub = "\"*\""; + } + if (blnUseRootBreadcrumbArrow) + { + NodeLeftHTMLBreadCrumbRoot = "\"*\""; + } + + //image for right facing arrow + if (!String.IsNullOrEmpty(RightArrow)) + { + strRightArrow = RightArrow; + } + else + { + strRightArrow = "breadcrumb.gif"; + } + if (!String.IsNullOrEmpty(DownArrow)) + { + strDownArrow = DownArrow; + } + else + { + strDownArrow = "menu_down.gif"; + } + + //Set correct image path for all separator images + if (!String.IsNullOrEmpty(Separator)) + { + if (Separator.IndexOf("src=") != -1) + { + Separator = Separator.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(LeftSeparator)) + { + if (LeftSeparator.IndexOf("src=") != -1) + { + LeftSeparator = LeftSeparator.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(RightSeparator)) + { + if (RightSeparator.IndexOf("src=") != -1) + { + RightSeparator = RightSeparator.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(LeftSeparatorBreadCrumb)) + { + if (LeftSeparatorBreadCrumb.IndexOf("src=") != -1) + { + LeftSeparatorBreadCrumb = LeftSeparatorBreadCrumb.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(RightSeparatorBreadCrumb)) + { + if (RightSeparatorBreadCrumb.IndexOf("src=") != -1) + { + RightSeparatorBreadCrumb = RightSeparatorBreadCrumb.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(LeftSeparatorActive)) + { + if (LeftSeparatorActive.IndexOf("src=") != -1) + { + LeftSeparatorActive = LeftSeparatorActive.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + if (!String.IsNullOrEmpty(RightSeparatorActive)) + { + if (RightSeparatorActive.IndexOf("src=") != -1) + { + RightSeparatorActive = RightSeparatorActive.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath); + } + } + + //generate dynamic menu + if (blnUseSkinPathArrowImages) + { + PathSystemImage = PortalSettings.ActiveTab.SkinPath; + } + else + { + PathSystemImage = Globals.ApplicationPath + "/images/"; + } + if (String.IsNullOrEmpty(PathImage)) + { + PathImage = PortalSettings.HomeDirectory; + } + if (blnUseArrows) + { + IndicateChildImageSub = strRightArrow; + if (ControlOrientation.ToLower() == "vertical") //NavigationProvider.NavigationProvider.Orientation.Vertical Then + { + IndicateChildImageRoot = strRightArrow; + } + else + { + IndicateChildImageRoot = strDownArrow; + } + } + else + { + PathSystemImage = Globals.ApplicationPath + "/images/"; + IndicateChildImageSub = "spacer.gif"; + } + if (String.IsNullOrEmpty(PathSystemScript)) + { + PathSystemScript = Globals.ApplicationPath + "/controls/SolpartMenu/"; + } + BuildNodes(null); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void BuildNodes(DNNNode objNode) + { + DNNNodeCollection objNodes; + objNodes = GetNavigationNodes(objNode); + Control.ClearNodes(); //since we always bind we need to clear the nodes for providers that maintain their state + Bind(objNodes); + } + + private void SetAttributes() + { + SeparateCss = "1"; + if (bool.Parse(GetValue(ClearDefaults, "False"))) + { + } + else + { + if (String.IsNullOrEmpty(MouseOutHideDelay)) + { + MouseOutHideDelay = "500"; + } + if (String.IsNullOrEmpty(MouseOverAction)) + { + MouseOverAction = true.ToString(); //NavigationProvider.NavigationProvider.HoverAction.Expand + } + if (String.IsNullOrEmpty(StyleBorderWidth)) + { + StyleBorderWidth = "0"; + } + if (String.IsNullOrEmpty(StyleControlHeight)) + { + StyleControlHeight = "16"; + } + if (String.IsNullOrEmpty(StyleNodeHeight)) + { + StyleNodeHeight = "21"; + } + if (String.IsNullOrEmpty(StyleIconWidth)) + { + StyleIconWidth = "0"; + } + if (String.IsNullOrEmpty(StyleSelectionColor)) + { + StyleSelectionColor = "#CCCCCC"; + } + if (String.IsNullOrEmpty(StyleSelectionForeColor)) + { + StyleSelectionForeColor = "White"; + } + if (String.IsNullOrEmpty(StyleHighlightColor)) + { + StyleHighlightColor = "#FF8080"; + } + if (String.IsNullOrEmpty(StyleIconBackColor)) + { + StyleIconBackColor = "#333333"; + } + if (String.IsNullOrEmpty(EffectsShadowColor)) + { + EffectsShadowColor = "#404040"; + } + if (String.IsNullOrEmpty(MouseOverDisplay)) + { + MouseOverDisplay = "highlight"; //NavigationProvider.NavigationProvider.HoverDisplay.Highlight + } + if (String.IsNullOrEmpty(EffectsStyle)) + { + EffectsStyle = "filter:progid:DXImageTransform.Microsoft.Shadow(color='DimGray', Direction=135, Strength=3);"; + } + if (String.IsNullOrEmpty(StyleFontSize)) + { + StyleFontSize = "9"; + } + if (String.IsNullOrEmpty(StyleFontBold)) + { + StyleFontBold = "True"; + } + if (String.IsNullOrEmpty(StyleFontNames)) + { + StyleFontNames = "Tahoma,Arial,Helvetica"; + } + if (String.IsNullOrEmpty(StyleForeColor)) + { + StyleForeColor = "White"; + } + if (String.IsNullOrEmpty(StyleBackColor)) + { + StyleBackColor = "#333333"; + } + if (String.IsNullOrEmpty(PathSystemImage)) + { + PathSystemImage = "/"; + } + } + if (SeparateCss == "1") + { + if (!String.IsNullOrEmpty(MenuBarCssClass)) + { + CSSControl = MenuBarCssClass; + } + else + { + CSSControl = "MainMenu_MenuBar"; + } + if (!String.IsNullOrEmpty(MenuContainerCssClass)) + { + CSSContainerRoot = MenuContainerCssClass; + } + else + { + CSSContainerRoot = "MainMenu_MenuContainer"; + } + if (!String.IsNullOrEmpty(MenuItemCssClass)) + { + CSSNode = MenuItemCssClass; + } + else + { + CSSNode = "MainMenu_MenuItem"; + } + if (!String.IsNullOrEmpty(MenuIconCssClass)) + { + CSSIcon = MenuIconCssClass; + } + else + { + CSSIcon = "MainMenu_MenuIcon"; + } + if (!String.IsNullOrEmpty(SubMenuCssClass)) + { + CSSContainerSub = SubMenuCssClass; + } + else + { + CSSContainerSub = "MainMenu_SubMenu"; + } + if (!String.IsNullOrEmpty(MenuBreakCssClass)) + { + CSSBreak = MenuBreakCssClass; + } + else + { + CSSBreak = "MainMenu_MenuBreak"; + } + if (!String.IsNullOrEmpty(MenuItemSelCssClass)) + { + CSSNodeHover = MenuItemSelCssClass; + } + else + { + CSSNodeHover = "MainMenu_MenuItemSel"; + } + if (!String.IsNullOrEmpty(MenuArrowCssClass)) + { + CSSIndicateChildSub = MenuArrowCssClass; + } + else + { + CSSIndicateChildSub = "MainMenu_MenuArrow"; + } + if (!String.IsNullOrEmpty(MenuRootArrowCssClass)) + { + CSSIndicateChildRoot = MenuRootArrowCssClass; + } + else + { + CSSIndicateChildRoot = "MainMenu_RootMenuArrow"; + } + } + } + + protected override void OnInit(EventArgs e) + { + SetAttributes(); + InitializeNavControl(this, "SolpartMenuNavigationProvider"); + base.OnInit(e); + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/EventListeners/SkinEventArgs.cs b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventArgs.cs new file mode 100644 index 00000000000..025c07029f3 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventArgs.cs @@ -0,0 +1,55 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.UI.Skins.EventListeners +{ + ///----------------------------------------------------------------------------- + /// + /// SkinEventArgs provides a custom EventARgs class for Skin Events + /// + /// + /// + /// [cnurse] 05/19/2009 Created + /// + ///----------------------------------------------------------------------------- + public class SkinEventArgs : EventArgs + { + private readonly Skin _Skin; + + public SkinEventArgs(Skin skin) + { + _Skin = skin; + } + + public Skin Skin + { + get + { + return _Skin; + } + } + } +} diff --git a/DNN Platform/Library/UI/Skins/EventListeners/SkinEventHandler.cs b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventHandler.cs new file mode 100644 index 00000000000..d77dd994e04 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventHandler.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Skins.EventListeners +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinEventHandler delegate defines a custom event handler for a Skin + /// Event. + /// + /// + /// [cnurse] 05/19/2009 Created + /// + /// ----------------------------------------------------------------------------- + public delegate void SkinEventHandler(object sender, SkinEventArgs e); +} diff --git a/DNN Platform/Library/UI/Skins/EventListeners/SkinEventListener.cs b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventListener.cs new file mode 100644 index 00000000000..42af5e52d81 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventListener.cs @@ -0,0 +1,34 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Skins.EventListeners +{ + public class SkinEventListener + { + public SkinEventListener(SkinEventType type, SkinEventHandler e) + { + EventType = type; + SkinEvent = e; + } + + public SkinEventType EventType { get; private set; } + public SkinEventHandler SkinEvent { get; private set; } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/EventListeners/SkinEventType.cs b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventType.cs new file mode 100644 index 00000000000..76ffb83ddc4 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/EventListeners/SkinEventType.cs @@ -0,0 +1,39 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Skins.EventListeners +{ + ///----------------------------------------------------------------------------- + /// + /// SkinEventType provides a custom enum for skin event types + /// + /// + /// + /// [cnurse] 05/19/2009 Created + /// + ///----------------------------------------------------------------------------- + public enum SkinEventType + { + OnSkinInit, + OnSkinLoad, + OnSkinPreRender, + OnSkinUnLoad + } +} diff --git a/DNN Platform/Library/UI/Skins/ISkinControl.cs b/DNN Platform/Library/UI/Skins/ISkinControl.cs new file mode 100644 index 00000000000..08d3a491876 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/ISkinControl.cs @@ -0,0 +1,33 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + public interface ISkinControl + { + IModuleControl ModuleControl { get; set; } + } +} diff --git a/DNN Platform/Library/UI/Skins/NavObjectBase.cs b/DNN Platform/Library/UI/Skins/NavObjectBase.cs new file mode 100644 index 00000000000..bd3a2105c57 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/NavObjectBase.cs @@ -0,0 +1,2721 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Modules.NavigationProvider; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + public class NavObjectBase : SkinObjectBase + { + #region "Private Members" + + private readonly List m_objCustomAttributes = new List(); + private bool m_blnPopulateNodesFromClient = true; + private int m_intExpandDepth = -1; + private int m_intStartTabId = -1; + private NavigationProvider m_objControl; + private string m_strCSSBreadCrumbRoot; + + private string m_strCSSBreadCrumbSub; + private string m_strCSSBreak; + private string m_strCSSContainerRoot; + private string m_strCSSContainerSub; + private string m_strCSSControl; + private string m_strCSSIcon; + private string m_strCSSIndicateChildRoot; + private string m_strCSSIndicateChildSub; + private string m_strCSSLeftSeparator; + private string m_strCSSLeftSeparatorBreadCrumb; + private string m_strCSSLeftSeparatorSelection; + private string m_strCSSNode; + private string m_strCSSNodeHover; + private string m_strCSSNodeHoverRoot; + private string m_strCSSNodeHoverSub; + private string m_strCSSNodeRoot; + private string m_strCSSNodeSelectedRoot; + private string m_strCSSNodeSelectedSub; + private string m_strCSSRightSeparator; + private string m_strCSSRightSeparatorBreadCrumb; + private string m_strCSSRightSeparatorSelection; + private string m_strCSSSeparator; + private string m_strControlAlignment; + private string m_strControlOrientation; + private string m_strEffectsDuration; + private string m_strEffectsShadowColor; + private string m_strEffectsShadowDirection; + private string m_strEffectsShadowStrength; + private string m_strEffectsStyle; + private string m_strEffectsTransition; + private string m_strForceCrawlerDisplay; + private string m_strForceDownLevel; + private string m_strIndicateChildImageExpandedRoot; + private string m_strIndicateChildImageExpandedSub; + private string m_strIndicateChildImageRoot; + private string m_strIndicateChildImageSub; + private string m_strIndicateChildren; + private string m_strLevel = ""; + private string m_strMouseOutHideDelay; + private string m_strMouseOverAction; + private string m_strMouseOverDisplay; + private string m_strNodeLeftHTMLBreadCrumbRoot; + private string m_strNodeLeftHTMLBreadCrumbSub; + private string m_strNodeLeftHTMLRoot; + private string m_strNodeLeftHTMLSub; + private string m_strNodeRightHTMLBreadCrumbRoot; + private string m_strNodeRightHTMLBreadCrumbSub; + private string m_strNodeRightHTMLRoot; + private string m_strNodeRightHTMLSub; + private string m_strPathImage; + private string m_strPathSystemImage; + private string m_strPathSystemScript; + private string m_strProviderName = ""; + private string m_strSeparatorHTML; + private string m_strSeparatorLeftHTML; + private string m_strSeparatorLeftHTMLActive; + private string m_strSeparatorLeftHTMLBreadCrumb; + private string m_strSeparatorRightHTML; + private string m_strSeparatorRightHTMLActive; + private string m_strSeparatorRightHTMLBreadCrumb; + private string m_strStyleBackColor; + private string m_strStyleBorderWidth; + private string m_strStyleControlHeight; + private string m_strStyleFontBold; + private string m_strStyleFontNames; + private string m_strStyleFontSize; + private string m_strStyleForeColor; + private string m_strStyleHighlightColor; + private string m_strStyleIconBackColor; + private string m_strStyleIconWidth; + private string m_strStyleNodeHeight; + private string m_strStyleSelectionBorderColor; + private string m_strStyleSelectionColor; + private string m_strStyleSelectionForeColor; + private string m_strToolTip = ""; + private string m_strWorkImage; + + #endregion + + #region "Public Properties" + //JH - 2/5/07 - support for custom attributes + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty)] + public List CustomAttributes + { + get + { + return m_objCustomAttributes; + } + } + + public bool ShowHiddenTabs { get; set; } + + public string ProviderName + { + get + { + return m_strProviderName; + } + set + { + m_strProviderName = value; + } + } + + protected NavigationProvider Control + { + get + { + return m_objControl; + } + } + + public string Level + { + get + { + return m_strLevel; + } + set + { + m_strLevel = value; + } + } + + public string ToolTip + { + get + { + return m_strToolTip; + } + set + { + m_strToolTip = value; + } + } + + public bool PopulateNodesFromClient + { + get + { + return m_blnPopulateNodesFromClient; + } + set + { + m_blnPopulateNodesFromClient = value; + } + } + + public int ExpandDepth + { + get + { + return m_intExpandDepth; + } + set + { + m_intExpandDepth = value; + } + } + + public int StartTabId + { + get + { + return m_intStartTabId; + } + set + { + m_intStartTabId = value; + } + } + + public string PathSystemImage + { + get + { + if (Control == null) + { + return m_strPathSystemImage; + } + else + { + return Control.PathSystemImage; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strPathSystemImage = value; + } + else + { + Control.PathSystemImage = value; + } + } + } + + public string PathImage + { + get + { + if (Control == null) + { + return m_strPathImage; + } + else + { + return Control.PathImage; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strPathImage = value; + } + else + { + Control.PathImage = value; + } + } + } + + public string WorkImage + { + get + { + if (Control == null) + { + return m_strWorkImage; + } + else + { + return Control.WorkImage; + } + } + set + { + if (Control == null) + { + m_strWorkImage = value; + } + else + { + Control.WorkImage = value; + } + } + } + + public string PathSystemScript + { + get + { + if (Control == null) + { + return m_strPathSystemScript; + } + else + { + return Control.PathSystemScript; + } + } + set + { + if (Control == null) + { + m_strPathSystemScript = value; + } + else + { + Control.PathSystemScript = value; + } + } + } + + public string ControlOrientation + { + get + { + string retValue = ""; + if (Control == null) + { + retValue = m_strControlOrientation; + } + else + { + switch (Control.ControlOrientation) + { + case NavigationProvider.Orientation.Horizontal: + retValue = "Horizontal"; + break; + case NavigationProvider.Orientation.Vertical: + retValue = "Vertical"; + break; + } + } + return retValue; + } + set + { + if (Control == null) + { + m_strControlOrientation = value; + } + else + { + switch (value.ToLower()) + { + case "horizontal": + Control.ControlOrientation = NavigationProvider.Orientation.Horizontal; + break; + case "vertical": + Control.ControlOrientation = NavigationProvider.Orientation.Vertical; + break; + } + } + } + } + + public string ControlAlignment + { + get + { + string retValue = ""; + if (Control == null) + { + retValue = m_strControlAlignment; + } + else + { + switch (Control.ControlAlignment) + { + case NavigationProvider.Alignment.Left: + retValue = "Left"; + break; + case NavigationProvider.Alignment.Right: + retValue = "Right"; + break; + case NavigationProvider.Alignment.Center: + retValue = "Center"; + break; + case NavigationProvider.Alignment.Justify: + retValue = "Justify"; + break; + } + } + return retValue; + } + set + { + if (Control == null) + { + m_strControlAlignment = value; + } + else + { + switch (value.ToLower()) + { + case "left": + Control.ControlAlignment = NavigationProvider.Alignment.Left; + break; + case "right": + Control.ControlAlignment = NavigationProvider.Alignment.Right; + break; + case "center": + Control.ControlAlignment = NavigationProvider.Alignment.Center; + break; + case "justify": + Control.ControlAlignment = NavigationProvider.Alignment.Justify; + break; + } + } + } + } + + public string ForceCrawlerDisplay + { + get + { + if (Control == null) + { + return m_strForceCrawlerDisplay; + } + else + { + return Control.ForceCrawlerDisplay; + } + } + set + { + if (Control == null) + { + m_strForceCrawlerDisplay = value; + } + else + { + Control.ForceCrawlerDisplay = value; + } + } + } + + public string ForceDownLevel + { + get + { + if (Control == null) + { + return m_strForceDownLevel; + } + else + { + return Control.ForceDownLevel; + } + } + set + { + if (Control == null) + { + m_strForceDownLevel = value; + } + else + { + Control.ForceDownLevel = value; + } + } + } + + public string MouseOutHideDelay + { + get + { + if (Control == null) + { + return m_strMouseOutHideDelay; + } + else + { + return Control.MouseOutHideDelay.ToString(); + } + } + set + { + if (Control == null) + { + m_strMouseOutHideDelay = value; + } + else + { + Control.MouseOutHideDelay = Convert.ToDecimal(value); + } + } + } + + public string MouseOverDisplay + { + get + { + string retValue = ""; + if (Control == null) + { + retValue = m_strMouseOverDisplay; + } + else + { + switch (Control.MouseOverDisplay) + { + case NavigationProvider.HoverDisplay.Highlight: + retValue = "Highlight"; + break; + case NavigationProvider.HoverDisplay.None: + retValue = "None"; + break; + case NavigationProvider.HoverDisplay.Outset: + retValue = "Outset"; + break; + } + } + return retValue; + } + set + { + if (Control == null) + { + m_strMouseOverDisplay = value; + } + else + { + switch (value.ToLower()) + { + case "highlight": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.Highlight; + break; + case "outset": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.Outset; + break; + case "none": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.None; + break; + } + } + } + } + + public string MouseOverAction + { + get + { + string retValue = ""; + if (Control == null) + { + retValue = m_strMouseOverAction; + } + else + { + switch (Control.MouseOverAction) + { + case NavigationProvider.HoverAction.Expand: + retValue = "True"; + break; + case NavigationProvider.HoverAction.None: + retValue = "False"; + break; + } + } + return retValue; + } + set + { + if (Control == null) + { + m_strMouseOverAction = value; + } + else + { + if (Convert.ToBoolean(GetValue(value, "True"))) + { + Control.MouseOverAction = NavigationProvider.HoverAction.Expand; + } + else + { + Control.MouseOverAction = NavigationProvider.HoverAction.None; + } + } + } + } + + public string IndicateChildren + { + get + { + if (Control == null) + { + return m_strIndicateChildren; + } + else + { + return Control.IndicateChildren.ToString(); + } + } + set + { + if (Control == null) + { + m_strIndicateChildren = value; + } + else + { + Control.IndicateChildren = Convert.ToBoolean(value); + } + } + } + + public string IndicateChildImageRoot + { + get + { + if (Control == null) + { + return m_strIndicateChildImageRoot; + } + else + { + return Control.IndicateChildImageRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strIndicateChildImageRoot = value; + } + else + { + Control.IndicateChildImageRoot = value; + } + } + } + + public string IndicateChildImageSub + { + get + { + if (Control == null) + { + return m_strIndicateChildImageSub; + } + else + { + return Control.IndicateChildImageSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strIndicateChildImageSub = value; + } + else + { + Control.IndicateChildImageSub = value; + } + } + } + + public string IndicateChildImageExpandedRoot + { + get + { + if (Control == null) + { + return m_strIndicateChildImageExpandedRoot; + } + else + { + return Control.IndicateChildImageExpandedRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strIndicateChildImageExpandedRoot = value; + } + else + { + Control.IndicateChildImageExpandedRoot = value; + } + } + } + + public string IndicateChildImageExpandedSub + { + get + { + if (Control == null) + { + return m_strIndicateChildImageExpandedSub; + } + else + { + return Control.IndicateChildImageExpandedSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strIndicateChildImageExpandedSub = value; + } + else + { + Control.IndicateChildImageExpandedSub = value; + } + } + } + + public string NodeLeftHTMLRoot + { + get + { + if (Control == null) + { + return m_strNodeLeftHTMLRoot; + } + else + { + return Control.NodeLeftHTMLRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeLeftHTMLRoot = value; + } + else + { + Control.NodeLeftHTMLRoot = value; + } + } + } + + public string NodeRightHTMLRoot + { + get + { + if (Control == null) + { + return m_strNodeRightHTMLRoot; + } + else + { + return Control.NodeRightHTMLRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeRightHTMLRoot = value; + } + else + { + Control.NodeRightHTMLRoot = value; + } + } + } + + public string NodeLeftHTMLSub + { + get + { + if (Control == null) + { + return m_strNodeLeftHTMLSub; + } + else + { + return Control.NodeLeftHTMLSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeLeftHTMLSub = value; + } + else + { + Control.NodeLeftHTMLSub = value; + } + } + } + + public string NodeRightHTMLSub + { + get + { + if (Control == null) + { + return m_strNodeRightHTMLSub; + } + else + { + return Control.NodeRightHTMLSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeRightHTMLSub = value; + } + else + { + Control.NodeRightHTMLSub = value; + } + } + } + + public string NodeLeftHTMLBreadCrumbRoot + { + get + { + if (Control == null) + { + return m_strNodeLeftHTMLBreadCrumbRoot; + } + else + { + return Control.NodeLeftHTMLBreadCrumbRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeLeftHTMLBreadCrumbRoot = value; + } + else + { + Control.NodeLeftHTMLBreadCrumbRoot = value; + } + } + } + + public string NodeLeftHTMLBreadCrumbSub + { + get + { + if (Control == null) + { + return m_strNodeLeftHTMLBreadCrumbSub; + } + else + { + return Control.NodeLeftHTMLBreadCrumbSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeLeftHTMLBreadCrumbSub = value; + } + else + { + Control.NodeLeftHTMLBreadCrumbSub = value; + } + } + } + + public string NodeRightHTMLBreadCrumbRoot + { + get + { + if (Control == null) + { + return m_strNodeRightHTMLBreadCrumbRoot; + } + else + { + return Control.NodeRightHTMLBreadCrumbRoot; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeRightHTMLBreadCrumbRoot = value; + } + else + { + Control.NodeRightHTMLBreadCrumbRoot = value; + } + } + } + + public string NodeRightHTMLBreadCrumbSub + { + get + { + if (Control == null) + { + return m_strNodeRightHTMLBreadCrumbSub; + } + else + { + return Control.NodeRightHTMLBreadCrumbSub; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strNodeRightHTMLBreadCrumbSub = value; + } + else + { + Control.NodeRightHTMLBreadCrumbSub = value; + } + } + } + + public string SeparatorHTML + { + get + { + if (Control == null) + { + return m_strSeparatorHTML; + } + else + { + return Control.SeparatorHTML; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorHTML = value; + } + else + { + Control.SeparatorHTML = value; + } + } + } + + public string SeparatorLeftHTML + { + get + { + if (Control == null) + { + return m_strSeparatorLeftHTML; + } + else + { + return Control.SeparatorLeftHTML; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorLeftHTML = value; + } + else + { + Control.SeparatorLeftHTML = value; + } + } + } + + public string SeparatorRightHTML + { + get + { + if (Control == null) + { + return m_strSeparatorRightHTML; + } + else + { + return Control.SeparatorRightHTML; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorRightHTML = value; + } + else + { + Control.SeparatorRightHTML = value; + } + } + } + + public string SeparatorLeftHTMLActive + { + get + { + if (Control == null) + { + return m_strSeparatorLeftHTMLActive; + } + else + { + return Control.SeparatorLeftHTMLActive; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorLeftHTMLActive = value; + } + else + { + Control.SeparatorLeftHTMLActive = value; + } + } + } + + public string SeparatorRightHTMLActive + { + get + { + if (Control == null) + { + return m_strSeparatorRightHTMLActive; + } + else + { + return Control.SeparatorRightHTMLActive; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorRightHTMLActive = value; + } + else + { + Control.SeparatorRightHTMLActive = value; + } + } + } + + public string SeparatorLeftHTMLBreadCrumb + { + get + { + if (Control == null) + { + return m_strSeparatorLeftHTMLBreadCrumb; + } + else + { + return Control.SeparatorLeftHTMLBreadCrumb; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorLeftHTMLBreadCrumb = value; + } + else + { + Control.SeparatorLeftHTMLBreadCrumb = value; + } + } + } + + public string SeparatorRightHTMLBreadCrumb + { + get + { + if (Control == null) + { + return m_strSeparatorRightHTMLBreadCrumb; + } + else + { + return Control.SeparatorRightHTMLBreadCrumb; + } + } + set + { + value = GetPath(value); + if (Control == null) + { + m_strSeparatorRightHTMLBreadCrumb = value; + } + else + { + Control.SeparatorRightHTMLBreadCrumb = value; + } + } + } + + public string CSSControl + { + get + { + if (Control == null) + { + return m_strCSSControl; + } + else + { + return Control.CSSControl; + } + } + set + { + if (Control == null) + { + m_strCSSControl = value; + } + else + { + Control.CSSControl = value; + } + } + } + + public string CSSContainerRoot + { + get + { + if (Control == null) + { + return m_strCSSContainerRoot; + } + else + { + return Control.CSSContainerRoot; + } + } + set + { + if (Control == null) + { + m_strCSSContainerRoot = value; + } + else + { + Control.CSSContainerRoot = value; + } + } + } + + public string CSSNode + { + get + { + if (Control == null) + { + return m_strCSSNode; + } + else + { + return Control.CSSNode; + } + } + set + { + if (Control == null) + { + m_strCSSNode = value; + } + else + { + Control.CSSNode = value; + } + } + } + + public string CSSIcon + { + get + { + if (Control == null) + { + return m_strCSSIcon; + } + else + { + return Control.CSSIcon; + } + } + set + { + if (Control == null) + { + m_strCSSIcon = value; + } + else + { + Control.CSSIcon = value; + } + } + } + + public string CSSContainerSub + { + get + { + if (Control == null) + { + return m_strCSSContainerSub; + } + else + { + return Control.CSSContainerSub; + } + } + set + { + if (Control == null) + { + m_strCSSContainerSub = value; + } + else + { + Control.CSSContainerSub = value; + } + } + } + + public string CSSNodeHover + { + get + { + if (Control == null) + { + return m_strCSSNodeHover; + } + else + { + return Control.CSSNodeHover; + } + } + set + { + if (Control == null) + { + m_strCSSNodeHover = value; + } + else + { + Control.CSSNodeHover = value; + } + } + } + + public string CSSBreak + { + get + { + if (Control == null) + { + return m_strCSSBreak; + } + else + { + return Control.CSSBreak; + } + } + set + { + if (Control == null) + { + m_strCSSBreak = value; + } + else + { + Control.CSSBreak = value; + } + } + } + + public string CSSIndicateChildSub + { + get + { + if (Control == null) + { + return m_strCSSIndicateChildSub; + } + else + { + return Control.CSSIndicateChildSub; + } + } + set + { + if (Control == null) + { + m_strCSSIndicateChildSub = value; + } + else + { + Control.CSSIndicateChildSub = value; + } + } + } + + public string CSSIndicateChildRoot + { + get + { + if (Control == null) + { + return m_strCSSIndicateChildRoot; + } + else + { + return Control.CSSIndicateChildRoot; + } + } + set + { + if (Control == null) + { + m_strCSSIndicateChildRoot = value; + } + else + { + Control.CSSIndicateChildRoot = value; + } + } + } + + public string CSSBreadCrumbRoot + { + get + { + if (Control == null) + { + return m_strCSSBreadCrumbRoot; + } + else + { + return Control.CSSBreadCrumbRoot; + } + } + set + { + if (Control == null) + { + m_strCSSBreadCrumbRoot = value; + } + else + { + Control.CSSBreadCrumbRoot = value; + } + } + } + + public string CSSBreadCrumbSub + { + get + { + if (Control == null) + { + return m_strCSSBreadCrumbSub; + } + else + { + return Control.CSSBreadCrumbSub; + } + } + set + { + if (Control == null) + { + m_strCSSBreadCrumbSub = value; + } + else + { + Control.CSSBreadCrumbSub = value; + } + } + } + + public string CSSNodeRoot + { + get + { + if (Control == null) + { + return m_strCSSNodeRoot; + } + else + { + return Control.CSSNodeRoot; + } + } + set + { + if (Control == null) + { + m_strCSSNodeRoot = value; + } + else + { + Control.CSSNodeRoot = value; + } + } + } + + public string CSSNodeSelectedRoot + { + get + { + if (Control == null) + { + return m_strCSSNodeSelectedRoot; + } + else + { + return Control.CSSNodeSelectedRoot; + } + } + set + { + if (Control == null) + { + m_strCSSNodeSelectedRoot = value; + } + else + { + Control.CSSNodeSelectedRoot = value; + } + } + } + + public string CSSNodeSelectedSub + { + get + { + if (Control == null) + { + return m_strCSSNodeSelectedSub; + } + else + { + return Control.CSSNodeSelectedSub; + } + } + set + { + if (Control == null) + { + m_strCSSNodeSelectedSub = value; + } + else + { + Control.CSSNodeSelectedSub = value; + } + } + } + + public string CSSNodeHoverRoot + { + get + { + if (Control == null) + { + return m_strCSSNodeHoverRoot; + } + else + { + return Control.CSSNodeHoverRoot; + } + } + set + { + if (Control == null) + { + m_strCSSNodeHoverRoot = value; + } + else + { + Control.CSSNodeHoverRoot = value; + } + } + } + + public string CSSNodeHoverSub + { + get + { + if (Control == null) + { + return m_strCSSNodeHoverSub; + } + else + { + return Control.CSSNodeHoverSub; + } + } + set + { + if (Control == null) + { + m_strCSSNodeHoverSub = value; + } + else + { + Control.CSSNodeHoverSub = value; + } + } + } + + public string CSSSeparator + { + get + { + if (Control == null) + { + return m_strCSSSeparator; + } + else + { + return Control.CSSSeparator; + } + } + set + { + if (Control == null) + { + m_strCSSSeparator = value; + } + else + { + Control.CSSSeparator = value; + } + } + } + + public string CSSLeftSeparator + { + get + { + if (Control == null) + { + return m_strCSSLeftSeparator; + } + else + { + return Control.CSSLeftSeparator; + } + } + set + { + if (Control == null) + { + m_strCSSLeftSeparator = value; + } + else + { + Control.CSSLeftSeparator = value; + } + } + } + + public string CSSRightSeparator + { + get + { + if (Control == null) + { + return m_strCSSRightSeparator; + } + else + { + return Control.CSSRightSeparator; + } + } + set + { + if (Control == null) + { + m_strCSSRightSeparator = value; + } + else + { + Control.CSSRightSeparator = value; + } + } + } + + public string CSSLeftSeparatorSelection + { + get + { + if (Control == null) + { + return m_strCSSLeftSeparatorSelection; + } + else + { + return Control.CSSLeftSeparatorSelection; + } + } + set + { + if (Control == null) + { + m_strCSSLeftSeparatorSelection = value; + } + else + { + Control.CSSLeftSeparatorSelection = value; + } + } + } + + public string CSSRightSeparatorSelection + { + get + { + if (Control == null) + { + return m_strCSSRightSeparatorSelection; + } + else + { + return Control.CSSRightSeparatorSelection; + } + } + set + { + if (Control == null) + { + m_strCSSRightSeparatorSelection = value; + } + else + { + Control.CSSRightSeparatorSelection = value; + } + } + } + + public string CSSLeftSeparatorBreadCrumb + { + get + { + if (Control == null) + { + return m_strCSSLeftSeparatorBreadCrumb; + } + else + { + return Control.CSSLeftSeparatorBreadCrumb; + } + } + set + { + if (Control == null) + { + m_strCSSLeftSeparatorBreadCrumb = value; + } + else + { + Control.CSSLeftSeparatorBreadCrumb = value; + } + } + } + + public string CSSRightSeparatorBreadCrumb + { + get + { + if (Control == null) + { + return m_strCSSRightSeparatorBreadCrumb; + } + else + { + return Control.CSSRightSeparatorBreadCrumb; + } + } + set + { + if (Control == null) + { + m_strCSSRightSeparatorBreadCrumb = value; + } + else + { + Control.CSSRightSeparatorBreadCrumb = value; + } + } + } + + public string StyleBackColor + { + get + { + if (Control == null) + { + return m_strStyleBackColor; + } + else + { + return Control.StyleBackColor; + } + } + set + { + if (Control == null) + { + m_strStyleBackColor = value; + } + else + { + Control.StyleBackColor = value; + } + } + } + + public string StyleForeColor + { + get + { + if (Control == null) + { + return m_strStyleForeColor; + } + else + { + return Control.StyleForeColor; + } + } + set + { + if (Control == null) + { + m_strStyleForeColor = value; + } + else + { + Control.StyleForeColor = value; + } + } + } + + public string StyleHighlightColor + { + get + { + if (Control == null) + { + return m_strStyleHighlightColor; + } + else + { + return Control.StyleHighlightColor; + } + } + set + { + if (Control == null) + { + m_strStyleHighlightColor = value; + } + else + { + Control.StyleHighlightColor = value; + } + } + } + + public string StyleIconBackColor + { + get + { + if (Control == null) + { + return m_strStyleIconBackColor; + } + else + { + return Control.StyleIconBackColor; + } + } + set + { + if (Control == null) + { + m_strStyleIconBackColor = value; + } + else + { + Control.StyleIconBackColor = value; + } + } + } + + public string StyleSelectionBorderColor + { + get + { + if (Control == null) + { + return m_strStyleSelectionBorderColor; + } + else + { + return Control.StyleSelectionBorderColor; + } + } + set + { + if (Control == null) + { + m_strStyleSelectionBorderColor = value; + } + else + { + Control.StyleSelectionBorderColor = value; + } + } + } + + public string StyleSelectionColor + { + get + { + if (Control == null) + { + return m_strStyleSelectionColor; + } + else + { + return Control.StyleSelectionColor; + } + } + set + { + if (Control == null) + { + m_strStyleSelectionColor = value; + } + else + { + Control.StyleSelectionColor = value; + } + } + } + + public string StyleSelectionForeColor + { + get + { + if (Control == null) + { + return m_strStyleSelectionForeColor; + } + else + { + return Control.StyleSelectionForeColor; + } + } + set + { + if (Control == null) + { + m_strStyleSelectionForeColor = value; + } + else + { + Control.StyleSelectionForeColor = value; + } + } + } + + public string StyleControlHeight + { + get + { + if (Control == null) + { + return m_strStyleControlHeight; + } + else + { + return Control.StyleControlHeight.ToString(); + } + } + set + { + if (Control == null) + { + m_strStyleControlHeight = value; + } + else + { + Control.StyleControlHeight = Convert.ToDecimal(value); + } + } + } + + public string StyleBorderWidth + { + get + { + if (Control == null) + { + return m_strStyleBorderWidth; + } + else + { + return Control.StyleBorderWidth.ToString(); + } + } + set + { + if (Control == null) + { + m_strStyleBorderWidth = value; + } + else + { + Control.StyleBorderWidth = Convert.ToDecimal(value); + } + } + } + + public string StyleNodeHeight + { + get + { + if (Control == null) + { + return m_strStyleNodeHeight; + } + else + { + return Control.StyleNodeHeight.ToString(); + } + } + set + { + if (Control == null) + { + m_strStyleNodeHeight = value; + } + else + { + Control.StyleNodeHeight = Convert.ToDecimal(value); + } + } + } + + public string StyleIconWidth + { + get + { + if (Control == null) + { + return m_strStyleIconWidth; + } + else + { + return Control.StyleIconWidth.ToString(); + } + } + set + { + if (Control == null) + { + m_strStyleIconWidth = value; + } + else + { + Control.StyleIconWidth = Convert.ToDecimal(value); + } + } + } + + public string StyleFontNames + { + get + { + if (Control == null) + { + return m_strStyleFontNames; + } + else + { + return Control.StyleFontNames; + } + } + set + { + if (Control == null) + { + m_strStyleFontNames = value; + } + else + { + Control.StyleFontNames = value; + } + } + } + + public string StyleFontSize + { + get + { + if (Control == null) + { + return m_strStyleFontSize; + } + else + { + return Control.StyleFontSize.ToString(); + } + } + set + { + if (Control == null) + { + m_strStyleFontSize = value; + } + else + { + Control.StyleFontSize = Convert.ToDecimal(value); + } + } + } + + public string StyleFontBold + { + get + { + if (Control == null) + { + return m_strStyleFontBold; + } + else + { + return Control.StyleFontBold; + } + } + set + { + if (Control == null) + { + m_strStyleFontBold = value; + } + else + { + Control.StyleFontBold = value; + } + } + } + + public string EffectsShadowColor + { + get + { + if (Control == null) + { + return m_strEffectsShadowColor; + } + else + { + return Control.EffectsShadowColor; + } + } + set + { + if (Control == null) + { + m_strEffectsShadowColor = value; + } + else + { + Control.EffectsShadowColor = value; + } + } + } + + public string EffectsStyle + { + get + { + if (Control == null) + { + return m_strEffectsStyle; + } + else + { + return Control.EffectsStyle; + } + } + set + { + if (Control == null) + { + m_strEffectsStyle = value; + } + else + { + Control.EffectsStyle = value; + } + } + } + + public string EffectsShadowStrength + { + get + { + if (Control == null) + { + return m_strEffectsShadowStrength; + } + else + { + return Control.EffectsShadowStrength.ToString(); + } + } + set + { + if (Control == null) + { + m_strEffectsShadowStrength = value; + } + else + { + Control.EffectsShadowStrength = Convert.ToInt32(value); + } + } + } + + public string EffectsTransition + { + get + { + if (Control == null) + { + return m_strEffectsTransition; + } + else + { + return Control.EffectsTransition; + } + } + set + { + if (Control == null) + { + m_strEffectsTransition = value; + } + else + { + Control.EffectsTransition = value; + } + } + } + + public string EffectsDuration + { + get + { + if (Control == null) + { + return m_strEffectsDuration; + } + else + { + return Control.EffectsDuration.ToString(); + } + } + set + { + if (Control == null) + { + m_strEffectsDuration = value; + } + else + { + Control.EffectsDuration = Convert.ToDouble(value); + } + } + } + + public string EffectsShadowDirection + { + get + { + if (Control == null) + { + return m_strEffectsShadowDirection; + } + else + { + return Control.EffectsShadowDirection; + } + } + set + { + if (Control == null) + { + m_strEffectsShadowDirection = value; + } + else + { + Control.EffectsShadowDirection = value; + } + } + } + + #endregion + + #region "Public Methods" + + public DNNNodeCollection GetNavigationNodes(DNNNode objNode) + { + int intRootParent = PortalSettings.ActiveTab.TabID; + DNNNodeCollection objNodes = null; + Navigation.ToolTipSource eToolTips; + int intNavNodeOptions = 0; + int intDepth = ExpandDepth; + switch (Level.ToLower()) + { + case "child": + break; + case "parent": + intNavNodeOptions = (int) Navigation.NavNodeOptions.IncludeParent + (int) Navigation.NavNodeOptions.IncludeSelf; + break; + case "same": + intNavNodeOptions = (int) Navigation.NavNodeOptions.IncludeSiblings + (int) Navigation.NavNodeOptions.IncludeSelf; + break; + default: + intRootParent = -1; + intNavNodeOptions = (int) Navigation.NavNodeOptions.IncludeSiblings + (int) Navigation.NavNodeOptions.IncludeSelf; + break; + } + + if (ShowHiddenTabs) intNavNodeOptions += (int) Navigation.NavNodeOptions.IncludeHiddenNodes; + + switch (ToolTip.ToLower()) + { + case "name": + eToolTips = Navigation.ToolTipSource.TabName; + break; + case "title": + eToolTips = Navigation.ToolTipSource.Title; + break; + case "description": + eToolTips = Navigation.ToolTipSource.Description; + break; + default: + eToolTips = Navigation.ToolTipSource.None; + break; + } + if (PopulateNodesFromClient && Control.SupportsPopulateOnDemand) + { + intNavNodeOptions += (int) Navigation.NavNodeOptions.MarkPendingNodes; + } + if (PopulateNodesFromClient && Control.SupportsPopulateOnDemand == false) + { + ExpandDepth = -1; + } + if (StartTabId != -1) + { + intRootParent = StartTabId; + } + if (objNode != null) + { + intRootParent = Convert.ToInt32(objNode.ID); + intNavNodeOptions = (int) Navigation.NavNodeOptions.MarkPendingNodes; + objNodes = Navigation.GetNavigationNodes(objNode, eToolTips, intRootParent, intDepth, intNavNodeOptions); + } + else + { + objNodes = Navigation.GetNavigationNodes(Control.ClientID, eToolTips, intRootParent, intDepth, intNavNodeOptions); + } + return objNodes; + } + + #endregion + + #region "Protected Methods" + + protected string GetValue(string strVal, string strDefault) + { + if (String.IsNullOrEmpty(strVal)) + { + return strDefault; + } + else + { + return strVal; + } + } + + protected void InitializeNavControl(Control objParent, string strDefaultProvider) + { + if (String.IsNullOrEmpty(ProviderName)) + { + ProviderName = strDefaultProvider; + } + m_objControl = NavigationProvider.Instance(ProviderName); + Control.ControlID = "ctl" + ID; + Control.Initialize(); + AssignControlProperties(); + objParent.Controls.Add(Control.NavigationControl); + } + + #endregion + + #region "Private Methods" + + private void AssignControlProperties() + { + if (!String.IsNullOrEmpty(m_strPathSystemImage)) + { + Control.PathSystemImage = m_strPathSystemImage; + } + if (!String.IsNullOrEmpty(m_strPathImage)) + { + Control.PathImage = m_strPathImage; + } + if (!String.IsNullOrEmpty(m_strPathSystemScript)) + { + Control.PathSystemScript = m_strPathSystemScript; + } + if (!String.IsNullOrEmpty(m_strWorkImage)) + { + Control.WorkImage = m_strWorkImage; + } + if (!String.IsNullOrEmpty(m_strControlOrientation)) + { + switch (m_strControlOrientation.ToLower()) + { + case "horizontal": + Control.ControlOrientation = NavigationProvider.Orientation.Horizontal; + break; + case "vertical": + Control.ControlOrientation = NavigationProvider.Orientation.Vertical; + break; + } + } + if (!String.IsNullOrEmpty(m_strControlAlignment)) + { + switch (m_strControlAlignment.ToLower()) + { + case "left": + Control.ControlAlignment = NavigationProvider.Alignment.Left; + break; + case "right": + Control.ControlAlignment = NavigationProvider.Alignment.Right; + break; + case "center": + Control.ControlAlignment = NavigationProvider.Alignment.Center; + break; + case "justify": + Control.ControlAlignment = NavigationProvider.Alignment.Justify; + break; + } + } + Control.ForceCrawlerDisplay = GetValue(m_strForceCrawlerDisplay, "False"); + Control.ForceDownLevel = GetValue(m_strForceDownLevel, "False"); + if (!String.IsNullOrEmpty(m_strMouseOutHideDelay)) + { + Control.MouseOutHideDelay = Convert.ToDecimal(m_strMouseOutHideDelay); + } + if (!String.IsNullOrEmpty(m_strMouseOverDisplay)) + { + switch (m_strMouseOverDisplay.ToLower()) + { + case "highlight": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.Highlight; + break; + case "outset": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.Outset; + break; + case "none": + Control.MouseOverDisplay = NavigationProvider.HoverDisplay.None; + break; + } + } + if (Convert.ToBoolean(GetValue(m_strMouseOverAction, "True"))) + { + Control.MouseOverAction = NavigationProvider.HoverAction.Expand; + } + else + { + Control.MouseOverAction = NavigationProvider.HoverAction.None; + } + Control.IndicateChildren = Convert.ToBoolean(GetValue(m_strIndicateChildren, "True")); + if (!String.IsNullOrEmpty(m_strIndicateChildImageRoot)) + { + Control.IndicateChildImageRoot = m_strIndicateChildImageRoot; + } + if (!String.IsNullOrEmpty(m_strIndicateChildImageSub)) + { + Control.IndicateChildImageSub = m_strIndicateChildImageSub; + } + if (!String.IsNullOrEmpty(m_strIndicateChildImageExpandedRoot)) + { + Control.IndicateChildImageExpandedRoot = m_strIndicateChildImageExpandedRoot; + } + if (!String.IsNullOrEmpty(m_strIndicateChildImageExpandedSub)) + { + Control.IndicateChildImageExpandedSub = m_strIndicateChildImageExpandedSub; + } + if (!String.IsNullOrEmpty(m_strNodeLeftHTMLRoot)) + { + Control.NodeLeftHTMLRoot = m_strNodeLeftHTMLRoot; + } + if (!String.IsNullOrEmpty(m_strNodeRightHTMLRoot)) + { + Control.NodeRightHTMLRoot = m_strNodeRightHTMLRoot; + } + if (!String.IsNullOrEmpty(m_strNodeLeftHTMLSub)) + { + Control.NodeLeftHTMLSub = m_strNodeLeftHTMLSub; + } + if (!String.IsNullOrEmpty(m_strNodeRightHTMLSub)) + { + Control.NodeRightHTMLSub = m_strNodeRightHTMLSub; + } + if (!String.IsNullOrEmpty(m_strNodeLeftHTMLBreadCrumbRoot)) + { + Control.NodeLeftHTMLBreadCrumbRoot = m_strNodeLeftHTMLBreadCrumbRoot; + } + if (!String.IsNullOrEmpty(m_strNodeLeftHTMLBreadCrumbSub)) + { + Control.NodeLeftHTMLBreadCrumbSub = m_strNodeLeftHTMLBreadCrumbSub; + } + if (!String.IsNullOrEmpty(m_strNodeRightHTMLBreadCrumbRoot)) + { + Control.NodeRightHTMLBreadCrumbRoot = m_strNodeRightHTMLBreadCrumbRoot; + } + if (!String.IsNullOrEmpty(m_strNodeRightHTMLBreadCrumbSub)) + { + Control.NodeRightHTMLBreadCrumbSub = m_strNodeRightHTMLBreadCrumbSub; + } + if (!String.IsNullOrEmpty(m_strSeparatorHTML)) + { + Control.SeparatorHTML = m_strSeparatorHTML; + } + if (!String.IsNullOrEmpty(m_strSeparatorLeftHTML)) + { + Control.SeparatorLeftHTML = m_strSeparatorLeftHTML; + } + if (!String.IsNullOrEmpty(m_strSeparatorRightHTML)) + { + Control.SeparatorRightHTML = m_strSeparatorRightHTML; + } + if (!String.IsNullOrEmpty(m_strSeparatorLeftHTMLActive)) + { + Control.SeparatorLeftHTMLActive = m_strSeparatorLeftHTMLActive; + } + if (!String.IsNullOrEmpty(m_strSeparatorRightHTMLActive)) + { + Control.SeparatorRightHTMLActive = m_strSeparatorRightHTMLActive; + } + if (!String.IsNullOrEmpty(m_strSeparatorLeftHTMLBreadCrumb)) + { + Control.SeparatorLeftHTMLBreadCrumb = m_strSeparatorLeftHTMLBreadCrumb; + } + if (!String.IsNullOrEmpty(m_strSeparatorRightHTMLBreadCrumb)) + { + Control.SeparatorRightHTMLBreadCrumb = m_strSeparatorRightHTMLBreadCrumb; + } + if (!String.IsNullOrEmpty(m_strCSSControl)) + { + Control.CSSControl = m_strCSSControl; + } + if (!String.IsNullOrEmpty(m_strCSSContainerRoot)) + { + Control.CSSContainerRoot = m_strCSSContainerRoot; + } + if (!String.IsNullOrEmpty(m_strCSSNode)) + { + Control.CSSNode = m_strCSSNode; + } + if (!String.IsNullOrEmpty(m_strCSSIcon)) + { + Control.CSSIcon = m_strCSSIcon; + } + if (!String.IsNullOrEmpty(m_strCSSContainerSub)) + { + Control.CSSContainerSub = m_strCSSContainerSub; + } + if (!String.IsNullOrEmpty(m_strCSSNodeHover)) + { + Control.CSSNodeHover = m_strCSSNodeHover; + } + if (!String.IsNullOrEmpty(m_strCSSBreak)) + { + Control.CSSBreak = m_strCSSBreak; + } + if (!String.IsNullOrEmpty(m_strCSSIndicateChildSub)) + { + Control.CSSIndicateChildSub = m_strCSSIndicateChildSub; + } + if (!String.IsNullOrEmpty(m_strCSSIndicateChildRoot)) + { + Control.CSSIndicateChildRoot = m_strCSSIndicateChildRoot; + } + if (!String.IsNullOrEmpty(m_strCSSBreadCrumbRoot)) + { + Control.CSSBreadCrumbRoot = m_strCSSBreadCrumbRoot; + } + if (!String.IsNullOrEmpty(m_strCSSBreadCrumbSub)) + { + Control.CSSBreadCrumbSub = m_strCSSBreadCrumbSub; + } + if (!String.IsNullOrEmpty(m_strCSSNodeRoot)) + { + Control.CSSNodeRoot = m_strCSSNodeRoot; + } + if (!String.IsNullOrEmpty(m_strCSSNodeSelectedRoot)) + { + Control.CSSNodeSelectedRoot = m_strCSSNodeSelectedRoot; + } + if (!String.IsNullOrEmpty(m_strCSSNodeSelectedSub)) + { + Control.CSSNodeSelectedSub = m_strCSSNodeSelectedSub; + } + if (!String.IsNullOrEmpty(m_strCSSNodeHoverRoot)) + { + Control.CSSNodeHoverRoot = m_strCSSNodeHoverRoot; + } + if (!String.IsNullOrEmpty(m_strCSSNodeHoverSub)) + { + Control.CSSNodeHoverSub = m_strCSSNodeHoverSub; + } + if (!String.IsNullOrEmpty(m_strCSSSeparator)) + { + Control.CSSSeparator = m_strCSSSeparator; + } + if (!String.IsNullOrEmpty(m_strCSSLeftSeparator)) + { + Control.CSSLeftSeparator = m_strCSSLeftSeparator; + } + if (!String.IsNullOrEmpty(m_strCSSRightSeparator)) + { + Control.CSSRightSeparator = m_strCSSRightSeparator; + } + if (!String.IsNullOrEmpty(m_strCSSLeftSeparatorSelection)) + { + Control.CSSLeftSeparatorSelection = m_strCSSLeftSeparatorSelection; + } + if (!String.IsNullOrEmpty(m_strCSSRightSeparatorSelection)) + { + Control.CSSRightSeparatorSelection = m_strCSSRightSeparatorSelection; + } + if (!String.IsNullOrEmpty(m_strCSSLeftSeparatorBreadCrumb)) + { + Control.CSSLeftSeparatorBreadCrumb = m_strCSSLeftSeparatorBreadCrumb; + } + if (!String.IsNullOrEmpty(m_strCSSRightSeparatorBreadCrumb)) + { + Control.CSSRightSeparatorBreadCrumb = m_strCSSRightSeparatorBreadCrumb; + } + if (!String.IsNullOrEmpty(m_strStyleBackColor)) + { + Control.StyleBackColor = m_strStyleBackColor; + } + if (!String.IsNullOrEmpty(m_strStyleForeColor)) + { + Control.StyleForeColor = m_strStyleForeColor; + } + if (!String.IsNullOrEmpty(m_strStyleHighlightColor)) + { + Control.StyleHighlightColor = m_strStyleHighlightColor; + } + if (!String.IsNullOrEmpty(m_strStyleIconBackColor)) + { + Control.StyleIconBackColor = m_strStyleIconBackColor; + } + if (!String.IsNullOrEmpty(m_strStyleSelectionBorderColor)) + { + Control.StyleSelectionBorderColor = m_strStyleSelectionBorderColor; + } + if (!String.IsNullOrEmpty(m_strStyleSelectionColor)) + { + Control.StyleSelectionColor = m_strStyleSelectionColor; + } + if (!String.IsNullOrEmpty(m_strStyleSelectionForeColor)) + { + Control.StyleSelectionForeColor = m_strStyleSelectionForeColor; + } + if (!String.IsNullOrEmpty(m_strStyleControlHeight)) + { + Control.StyleControlHeight = Convert.ToDecimal(m_strStyleControlHeight); + } + if (!String.IsNullOrEmpty(m_strStyleBorderWidth)) + { + Control.StyleBorderWidth = Convert.ToDecimal(m_strStyleBorderWidth); + } + if (!String.IsNullOrEmpty(m_strStyleNodeHeight)) + { + Control.StyleNodeHeight = Convert.ToDecimal(m_strStyleNodeHeight); + } + if (!String.IsNullOrEmpty(m_strStyleIconWidth)) + { + Control.StyleIconWidth = Convert.ToDecimal(m_strStyleIconWidth); + } + if (!String.IsNullOrEmpty(m_strStyleFontNames)) + { + Control.StyleFontNames = m_strStyleFontNames; + } + if (!String.IsNullOrEmpty(m_strStyleFontSize)) + { + Control.StyleFontSize = Convert.ToDecimal(m_strStyleFontSize); + } + if (!String.IsNullOrEmpty(m_strStyleFontBold)) + { + Control.StyleFontBold = m_strStyleFontBold; + } + if (!String.IsNullOrEmpty(m_strEffectsShadowColor)) + { + Control.EffectsShadowColor = m_strEffectsShadowColor; + } + if (!String.IsNullOrEmpty(m_strEffectsStyle)) + { + Control.EffectsStyle = m_strEffectsStyle; + } + if (!String.IsNullOrEmpty(m_strEffectsShadowStrength)) + { + Control.EffectsShadowStrength = Convert.ToInt32(m_strEffectsShadowStrength); + } + if (!String.IsNullOrEmpty(m_strEffectsTransition)) + { + Control.EffectsTransition = m_strEffectsTransition; + } + if (!String.IsNullOrEmpty(m_strEffectsDuration)) + { + Control.EffectsDuration = Convert.ToDouble(m_strEffectsDuration); + } + if (!String.IsNullOrEmpty(m_strEffectsShadowDirection)) + { + Control.EffectsShadowDirection = m_strEffectsShadowDirection; + } + Control.CustomAttributes = CustomAttributes; + } + + protected void Bind(DNNNodeCollection objNodes) + { + Control.Bind(objNodes); + } + + private string GetPath(string strPath) + { + if (strPath.IndexOf("[SKINPATH]") > -1) + { + return strPath.Replace("[SKINPATH]", PortalSettings.ActiveTab.SkinPath); + } + else if (strPath.IndexOf("[APPIMAGEPATH]") > -1) + { + return strPath.Replace("[APPIMAGEPATH]", Globals.ApplicationPath + "/images/"); + } + else if (strPath.IndexOf("[HOMEDIRECTORY]") > -1) + { + return strPath.Replace("[HOMEDIRECTORY]", PortalSettings.HomeDirectory); + } + else + { + if (strPath.StartsWith("~")) + { + return ResolveUrl(strPath); + } + } + return strPath; + } + + #endregion + } + + public class CustomAttribute + { + public string Name; + public string Value; + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/Pane.cs b/DNN Platform/Library/UI/Skins/Pane.cs new file mode 100644 index 00000000000..8c8ec7135de --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Pane.cs @@ -0,0 +1,635 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.UI.Containers; +using DotNetNuke.UI.Utilities; +using DotNetNuke.UI.WebControls; + +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Skins + /// Class : Pane + /// ----------------------------------------------------------------------------- + /// + /// The Pane class represents a Pane within the Skin + /// + /// + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public class Pane + { + #region Private Members + + private const string CPaneOutline = "paneOutline"; + private HtmlGenericControl _containerWrapperControl; + private Dictionary _containers; + + #endregion + + #region Constructors + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new Pane object from the Control in the Skin + /// + /// The HtmlContainerControl in the Skin. + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public Pane(HtmlContainerControl pane) + { + PaneControl = pane; + Name = pane.ID; + } + + /// ----------------------------------------------------------------------------- + /// + /// Constructs a new Pane object from the Control in the Skin + /// + /// The name (ID) of the HtmlContainerControl + /// The HtmlContainerControl in the Skin. + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + public Pane(string name, HtmlContainerControl pane) + { + PaneControl = pane; + Name = name; + } + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Containers. + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + protected Dictionary Containers + { + get + { + return _containers ?? (_containers = new Dictionary()); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the name (ID) of the Pane + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + protected string Name { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the HtmlContainerControl + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + protected HtmlContainerControl PaneControl { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the PortalSettings of the Portal + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + protected PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + private bool CanCollapsePane() + { + //This section sets the width to "0" on panes that have no modules. + //This preserves the integrity of the HTML syntax so we don't have to set + //the visiblity of a pane to false. Setting the visibility of a pane to + //false where there are colspans and rowspans can render the skin incorrectly. + bool canCollapsePane = true; + if (Containers.Count > 0) + { + canCollapsePane = false; + } + else if (PaneControl.Controls.Count == 1) + { + //Pane contains 1 control + canCollapsePane = false; + var literal = PaneControl.Controls[0] as LiteralControl; + if (literal != null) + { + //Check if the literal control is just whitespace - if so we can collapse panes + if (String.IsNullOrEmpty(HtmlUtils.StripWhiteSpace(literal.Text, false))) + { + canCollapsePane = true; + } + } + } + else if (PaneControl.Controls.Count > 1) + { + //Pane contains more than 1 control + canCollapsePane = false; + } + return canCollapsePane; + } + + #endregion + + #region Private Methods + + /// ----------------------------------------------------------------------------- + /// + /// LoadContainerByPath gets the Container from its Url(Path) + /// + /// The Url to the Container control + /// A Container + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private Containers.Container LoadContainerByPath(string containerPath) + { + if (containerPath.ToLower().IndexOf("/skins/") != -1 || containerPath.ToLower().IndexOf("/skins\\") != -1 || containerPath.ToLower().IndexOf("\\skins\\") != -1 || + containerPath.ToLower().IndexOf("\\skins/") != -1) + { + throw new Exception(); + } + + Containers.Container container = null; + + try + { + string containerSrc = containerPath; + if (containerPath.IndexOf(Globals.ApplicationPath, StringComparison.InvariantCultureIgnoreCase) != -1) + { + containerPath = containerPath.Remove(0, Globals.ApplicationPath.Length); + } + container = ControlUtilities.LoadControl(PaneControl.Page, containerPath); + container.ContainerSrc = containerSrc; + //call databind so that any server logic in the container is executed + container.DataBind(); + } + catch (Exception exc) + { + //could not load user control + var lex = new ModuleLoadException(Skin.MODULELOAD_ERROR, exc); + if (TabPermissionController.CanAdminPage()) + { + //only display the error to administrators + _containerWrapperControl.Controls.Add(new ErrorContainer(PortalSettings, string.Format(Skin.CONTAINERLOAD_ERROR, containerPath), lex).Container); + } + Exceptions.LogException(lex); + } + return container; + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadModuleContainer gets the Container for cookie + /// + /// Current Http Request. + /// A Container + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + private Containers.Container LoadContainerFromCookie(HttpRequest request) + { + Containers.Container container = null; + HttpCookie cookie = request.Cookies["_ContainerSrc" + PortalSettings.PortalId]; + if (cookie != null) + { + if (!String.IsNullOrEmpty(cookie.Value)) + { + container = LoadContainerByPath(SkinController.FormatSkinSrc(cookie.Value + ".ascx", PortalSettings)); + } + } + return container; + } + + private Containers.Container LoadContainerFromPane() + { + Containers.Container container = null; + string containerSrc; + var validSrc = false; + + if ((PaneControl.Attributes["ContainerType"] != null) && (PaneControl.Attributes["ContainerName"] != null)) + { + containerSrc = "[" + PaneControl.Attributes["ContainerType"] + "]" + SkinController.RootContainer + "/" + PaneControl.Attributes["ContainerName"] + "/" + + PaneControl.Attributes["ContainerSrc"]; + validSrc = true; + } + else + { + containerSrc = PaneControl.Attributes["ContainerSrc"]; + if (containerSrc.Contains("/") && !(containerSrc.ToLower().StartsWith("[g]") || containerSrc.ToLower().StartsWith("[l]"))) + { + containerSrc = string.Format(SkinController.IsGlobalSkin(PortalSettings.ActiveTab.SkinSrc) ? "[G]containers/{0}" : "[L]containers/{0}", containerSrc.TrimStart('/')); + validSrc = true; + } + } + + if (validSrc) + { + containerSrc = SkinController.FormatSkinSrc(containerSrc, PortalSettings); + container = LoadContainerByPath(containerSrc); + } + return container; + } + + private Containers.Container LoadContainerFromQueryString(ModuleInfo module, HttpRequest request) + { + Containers.Container container = null; + int previewModuleId = -1; + if (request.QueryString["ModuleId"] != null) + { + Int32.TryParse(request.QueryString["ModuleId"], out previewModuleId); + } + + //load user container ( based on cookie ) + if ((request.QueryString["ContainerSrc"] != null) && (module.ModuleID == previewModuleId || previewModuleId == -1)) + { + string containerSrc = SkinController.FormatSkinSrc(Globals.QueryStringDecode(request.QueryString["ContainerSrc"]) + ".ascx", PortalSettings); + container = LoadContainerByPath(containerSrc); + } + return container; + } + + private Containers.Container LoadNoContainer(ModuleInfo module) + { + string noContainerSrc = "[G]" + SkinController.RootContainer + "/_default/No Container.ascx"; + Containers.Container container = null; + + //if the module specifies that no container should be used + if (module.DisplayTitle == false) + { + //always display container if the current user is the administrator or the module is being used in an admin case + bool displayTitle = ModulePermissionController.CanEditModuleContent(module) || Globals.IsAdminSkin(); + //unless the administrator is in view mode + if (displayTitle) + { + displayTitle = (PortalSettings.UserMode != PortalSettings.Mode.View); + } + + if (displayTitle == false) + { + container = LoadContainerByPath(SkinController.FormatSkinSrc(noContainerSrc, PortalSettings)); + } + } + return container; + } + + private Containers.Container LoadModuleContainer(ModuleInfo module) + { + var containerSrc = Null.NullString; + var request = PaneControl.Page.Request; + Containers.Container container = null; + + if (PortalSettings.EnablePopUps && request.Url.ToString().Contains("popUp=true")) + { + containerSrc = module.ContainerPath + "popUpContainer.ascx"; + //Check Skin for a popup Container + if (module.ContainerSrc == PortalSettings.ActiveTab.ContainerSrc) + { + if (File.Exists(HttpContext.Current.Server.MapPath(containerSrc))) + { + container = LoadContainerByPath(containerSrc); + } + } + + //error loading container - load default popup container + if (container == null) + { + containerSrc = Globals.HostPath + "Containers/_default/popUpContainer.ascx"; + container = LoadContainerByPath(containerSrc); + } + } + else + { + container = (LoadContainerFromQueryString(module, request) ?? LoadContainerFromCookie(request)) ?? LoadNoContainer(module); + if (container == null) + { + //Check Skin for Container + var masterModules = PortalSettings.ActiveTab.ChildModules; + if (masterModules.ContainsKey(module.ModuleID) && string.IsNullOrEmpty(masterModules[module.ModuleID].ContainerSrc)) + { + //look for a container specification in the skin pane + if (PaneControl != null) + { + if ((PaneControl.Attributes["ContainerSrc"] != null)) + { + container = LoadContainerFromPane(); + } + } + } + } + + //else load assigned container + if (container == null) + { + containerSrc = module.ContainerSrc; + if (!String.IsNullOrEmpty(containerSrc)) + { + containerSrc = SkinController.FormatSkinSrc(containerSrc, PortalSettings); + container = LoadContainerByPath(containerSrc); + } + } + + //error loading container - load default + if (container == null) + { + containerSrc = SkinController.FormatSkinSrc(SkinController.GetDefaultPortalContainer(), PortalSettings); + container = LoadContainerByPath(containerSrc); + } + } + + //Set container path + module.ContainerPath = SkinController.FormatSkinPath(containerSrc); + + //set container id to an explicit short name to reduce page payload + container.ID = "ctr"; + //make the container id unique for the page + if (module.ModuleID > -1) + { + container.ID += module.ModuleID.ToString(); + } + return container; + } + + /// ----------------------------------------------------------------------------- + /// + /// ModuleMoveToPanePostBack excutes when a module is moved by Drag-and-Drop + /// + /// A ClientAPIPostBackEventArgs object + /// + /// [cnurse] 12/05/2007 Moved from Skin.vb + /// + /// ----------------------------------------------------------------------------- + private void ModuleMoveToPanePostBack(ClientAPIPostBackEventArgs args) + { + var portalSettings = (PortalSettings)HttpContext.Current.Items["PortalSettings"]; + if (TabPermissionController.CanAdminPage()) + { + var moduleId = Convert.ToInt32(args.EventArguments["moduleid"]); + var paneName = Convert.ToString(args.EventArguments["pane"]); + var moduleOrder = Convert.ToInt32(args.EventArguments["order"]); + + var moduleController = new ModuleController(); + moduleController.UpdateModuleOrder(portalSettings.ActiveTab.TabID, moduleId, moduleOrder, paneName); + moduleController.UpdateTabModuleOrder(portalSettings.ActiveTab.TabID); + + //Redirect to the same page to pick up changes + PaneControl.Page.Response.Redirect(PaneControl.Page.Request.RawUrl, true); + } + } + + #endregion + + #region Public Methods + + /// ----------------------------------------------------------------------------- + /// + /// InjectModule injects a Module (and its container) into the Pane + /// + /// The Module + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + public void InjectModule(ModuleInfo module) + { + _containerWrapperControl = new HtmlGenericControl("div"); + PaneControl.Controls.Add(_containerWrapperControl); + + //inject module classes + const string classFormatString = "DnnModule DnnModule-{0} DnnModule-{1}"; + string sanitizedModuleName = Null.NullString; + + if (!String.IsNullOrEmpty(module.DesktopModule.ModuleName)) + { + sanitizedModuleName = Globals.CreateValidClass(module.DesktopModule.ModuleName, false); + } + + _containerWrapperControl.Attributes["class"] = String.Format(classFormatString, sanitizedModuleName, module.ModuleID); + + try + { + if (!Globals.IsAdminControl()) + { + _containerWrapperControl.Controls.Add(new LiteralControl("")); + } + + //Load container control + Containers.Container container = LoadModuleContainer(module); + + //Add Container to Dictionary + Containers.Add(container.ID, container); + + // hide anything of type ActionsMenu - as we're injecting our own menu now. + container.InjectActionMenu = (container.Controls.OfType().Count() == 0); + if (!container.InjectActionMenu) + { + foreach (var actionControl in container.Controls.OfType()) + { + if (actionControl is ActionsMenu || actionControl is SolPartActions) + { + Control control = actionControl as Control; + if (control != null) + { + control.Visible = false; + container.InjectActionMenu = true; + } + } + } + } + + if (Globals.IsLayoutMode() && Globals.IsAdminControl() == false) + { + //provide Drag-N-Drop capabilities + var dragDropContainer = new Panel(); + Control title = container.FindControl("dnnTitle"); + //Assume that the title control is named dnnTitle. If this becomes an issue we could loop through the controls looking for the title type of skin object + dragDropContainer.ID = container.ID + "_DD"; + _containerWrapperControl.Controls.Add(dragDropContainer); + + //inject the container into the page pane - this triggers the Pre_Init() event for the user control + dragDropContainer.Controls.Add(container); + + if (title != null) + { + if (title.Controls.Count > 0) + { + title = title.Controls[0]; + } + } + + //enable drag and drop + if (title != null) + { + //The title ID is actually the first child so we need to make sure at least one child exists + DNNClientAPI.EnableContainerDragAndDrop(title, dragDropContainer, module.ModuleID); + ClientAPI.RegisterPostBackEventHandler(PaneControl, "MoveToPane", ModuleMoveToPanePostBack, false); + } + } + else + { + _containerWrapperControl.Controls.Add(container); + } + + //Attach Module to Container + container.SetModuleConfiguration(module); + + //display collapsible page panes + if (PaneControl.Visible == false) + { + PaneControl.Visible = true; + } + } + catch (Exception exc) + { + var lex = new ModuleLoadException(string.Format(Skin.MODULEADD_ERROR, PaneControl.ID), exc); + if (TabPermissionController.CanAdminPage()) + { + //only display the error to administrators + _containerWrapperControl.Controls.Add(new ErrorContainer(PortalSettings, Skin.MODULELOAD_ERROR, lex).Container); + } + Exceptions.LogException(exc); + throw lex; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// ProcessPane processes the Attributes for the PaneControl + /// + /// + /// [cnurse] 12/05/2007 Created + /// + /// ----------------------------------------------------------------------------- + public void ProcessPane() + { + if (PaneControl != null) + { + //remove excess skin non-validating attributes + PaneControl.Attributes.Remove("ContainerType"); + PaneControl.Attributes.Remove("ContainerName"); + PaneControl.Attributes.Remove("ContainerSrc"); + + if (Globals.IsLayoutMode()) + { + PaneControl.Visible = true; + + //display pane border + string cssclass = PaneControl.Attributes["class"]; + if (string.IsNullOrEmpty(cssclass)) + { + PaneControl.Attributes["class"] = CPaneOutline; + } + else + { + PaneControl.Attributes["class"] = cssclass.Replace(CPaneOutline, "").Trim().Replace(" ", " ") + " " + CPaneOutline; + } + //display pane name + var ctlLabel = new Label { Text = "
    " + Name + "

    ", CssClass = "SubHead" }; + PaneControl.Controls.AddAt(0, ctlLabel); + } + else + { + if (TabPermissionController.CanAddContentToPage() && PaneControl.Visible == false) + { + PaneControl.Visible = true; + } + + if (CanCollapsePane()) + { + //This pane has no controls so set the width to 0 + if (PaneControl.Attributes["style"] != null) + { + PaneControl.Attributes.Remove("style"); + } + if (PaneControl.Attributes["class"] != null) + { + PaneControl.Attributes["class"] = PaneControl.Attributes["class"] + " DNNEmptyPane"; + } + else + { + PaneControl.Attributes["class"] = "DNNEmptyPane"; + } + } + + //Add support for drag and drop + if (TabPermissionController.CanAddContentToPage() && Globals.IsEditMode()) + { + if (PaneControl.Attributes["class"] != null) + { + PaneControl.Attributes["class"] = PaneControl.Attributes["class"] + " dnnSortable"; + } + else + { + PaneControl.Attributes["class"] = "dnnSortable"; + } + } + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/Skin.cs b/DNN Platform/Library/UI/Skins/Skin.cs new file mode 100644 index 00000000000..b1a9477cadf --- /dev/null +++ b/DNN Platform/Library/UI/Skins/Skin.cs @@ -0,0 +1,1009 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Application; +using DotNetNuke.Collections.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Modules.Communications; +using DotNetNuke.Framework; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.ControlPanels; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.Skins.Controls; +using DotNetNuke.UI.Skins.EventListeners; +using DotNetNuke.Web.Client; +using DotNetNuke.Web.Client.ClientResourceManagement; + +using Microsoft.VisualBasic; + +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Namespace: DotNetNuke.UI.Skins + /// Class : Skin + /// ----------------------------------------------------------------------------- + /// + /// Skin is the base for the Skins + /// + /// + /// + /// + /// [cnurse] 07/04/2005 Documented + /// + /// ----------------------------------------------------------------------------- + public class Skin : UserControlBase + { + #region Public Constants + + // ReSharper disable InconsistentNaming + public static string MODULELOAD_ERROR = Localization.GetString("ModuleLoad.Error"); + public static string CONTAINERLOAD_ERROR = Localization.GetString("ContainerLoad.Error"); + public static string MODULEADD_ERROR = Localization.GetString("ModuleAdd.Error"); + + public const string OnInitMessage = "Skin_InitMessage"; + public const string OnInitMessageType = "Skin_InitMessageType"; + + private readonly ModuleCommunicate _communicator = new ModuleCommunicate(); + // ReSharper restore InconsistentNaming + + #endregion + + #region Private Members + + private ArrayList _actionEventListeners; + private Control _controlPanel; + private Dictionary _panes; + + #endregion + + #region Protected Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ControlPanel container. + /// + /// + /// + /// + /// [cnurse] 12/04/2007 created + /// [cnurse] 04/17/2009 Refactored from Skin + /// + /// ----------------------------------------------------------------------------- + internal Control ControlPanel + { + get + { + return _controlPanel ?? (_controlPanel = FindControl("ControlPanel")); + } + } + + #endregion + + #region Friend Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets the ModuleCommunicate instance for the skin + /// + /// The ModuleCommunicate instance for the Skin + /// + /// [cnurse] 01/12/2009 created + /// + internal ModuleCommunicate Communicator + { + get + { + return _communicator; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets a Dictionary of Panes. + /// + /// + /// + /// + /// [cnurse] 12/04/2007 created + /// + /// ----------------------------------------------------------------------------- + internal Dictionary Panes + { + get + { + return _panes ?? (_panes = new Dictionary()); + } + } + + #endregion + + #region Public Properties + + /// ----------------------------------------------------------------------------- + /// + /// Gets an ArrayList of ActionEventListeners + /// + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public ArrayList ActionEventListeners + { + get + { + return _actionEventListeners ?? (_actionEventListeners = new ArrayList()); + } + set + { + _actionEventListeners = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Path for this skin + /// + /// A String + /// + /// [cnurse] 12/05/2007 documented + /// + /// ----------------------------------------------------------------------------- + public string SkinPath + { + get + { + return TemplateSourceDirectory + "/"; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets the Source for this skin + /// + /// A String + /// + /// [cnurse] 12/05/2007 documented + /// + /// ----------------------------------------------------------------------------- + public string SkinSrc { get; set; } + + #endregion + + #region Private Methods + + private static void AddModuleMessage(Control control, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType, string iconSrc) + { + if (control != null) + { + if (!String.IsNullOrEmpty(message)) + { + var messagePlaceHolder = ControlUtilities.FindControl(control, "MessagePlaceHolder", true); + if (messagePlaceHolder != null) + { + messagePlaceHolder.Visible = true; + ModuleMessage moduleMessage = GetModuleMessageControl(heading, message, moduleMessageType, iconSrc); + messagePlaceHolder.Controls.Add(moduleMessage); + } + } + } + } + + private static void AddPageMessage(Control control, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType, string iconSrc) + { + if (!String.IsNullOrEmpty(message)) + { + Control contentPane = control.FindControl(Globals.glbDefaultPane); + if (contentPane != null) + { + ModuleMessage moduleMessage = GetModuleMessageControl(heading, message, moduleMessageType, iconSrc); + contentPane.Controls.AddAt(0, moduleMessage); + } + } + } + + private bool CheckExpired() + { + bool blnExpired = false; + if (PortalSettings.ExpiryDate != Null.NullDate) + { + if (Convert.ToDateTime(PortalSettings.ExpiryDate) < DateTime.Now && !Globals.IsHostTab(PortalSettings.ActiveTab.TabID)) + { + blnExpired = true; + } + } + return blnExpired; + } + + private Pane GetPane(ModuleInfo module) + { + Pane pane; + bool found = Panes.TryGetValue(module.PaneName.ToLowerInvariant(), out pane); + + if (!found) + { + Panes.TryGetValue(Globals.glbDefaultPane.ToLowerInvariant(), out pane); + } + + return pane; + } + + private void InjectControlPanel() + { + //if querystring dnnprintmode=true, controlpanel will not be shown + if (Request.QueryString["dnnprintmode"] != "true" && Request.QueryString["popUp"] != "true") + { + //ControlPanel processing + var objControlPanel = ControlUtilities.LoadControl(this, Host.ControlPanel); + var objForm = (HtmlForm)Parent.FindControl("Form"); + + if(objControlPanel.IncludeInControlHierarchy) + { + //inject ControlPanel control into skin + if (ControlPanel == null) + { + if (objForm != null) + { + objForm.Controls.AddAt(0, objControlPanel); + } + else + { + Page.Controls.AddAt(0, objControlPanel); + } + } + else + { + if (objForm != null) + { + if (Host.ControlPanel.ToLowerInvariant().EndsWith("controlbar.ascx")) + { + objForm.Controls.AddAt(0, objControlPanel); + } + else + { + ControlPanel.Controls.Add(objControlPanel); + } + } + else + { + if (Host.ControlPanel.ToLowerInvariant().EndsWith("controlbar.ascx")) + { + Page.Controls.AddAt(0, objControlPanel); + } + else + { + ControlPanel.Controls.Add(objControlPanel); + } + } + } + + //register admin.css + ClientResourceManager.RegisterAdminStylesheet(Page, Globals.HostPath + "admin.css"); + } + } + } + + private void InvokeSkinEvents(SkinEventType skinEventType) + { + SharedList list = ((NaiveLockingList)DotNetNukeContext.Current.SkinEventListeners).SharedList; + + using (list.GetReadLock()) + { + foreach (var listener in list.Where(x => x.EventType == skinEventType)) + { + listener.SkinEvent.Invoke(this, new SkinEventArgs(this)); + } + } + } + + private void LoadPanes() + { + //iterate page controls + foreach (Control ctlControl in Controls) + { + var objPaneControl = ctlControl as HtmlContainerControl; + + //Panes must be runat=server controls so they have to have an ID + if (objPaneControl != null && !string.IsNullOrEmpty(objPaneControl.ID)) + { + //load the skin panes + switch (objPaneControl.TagName.ToLowerInvariant()) + { + case "td": + case "div": + case "span": + case "p": + //content pane + if (objPaneControl.ID.ToLower() != "controlpanel") + { + //Add to the PortalSettings (for use in the Control Panel) + PortalSettings.ActiveTab.Panes.Add(objPaneControl.ID); + + //Add to the Panes collection + Panes.Add(objPaneControl.ID.ToLowerInvariant(), new Pane(objPaneControl)); + } + else + { + //Control Panel pane + _controlPanel = objPaneControl; + } + break; + } + } + } + } + + private static Skin LoadSkin(PageBase page, string skinPath) + { + Skin ctlSkin = null; + try + { + string skinSrc = skinPath; + if (skinPath.ToLower().IndexOf(Globals.ApplicationPath) != -1) + { + skinPath = skinPath.Remove(0, Globals.ApplicationPath.Length); + } + ctlSkin = ControlUtilities.LoadControl(page, skinPath); + ctlSkin.SkinSrc = skinSrc; + //call databind so that any server logic in the skin is executed + ctlSkin.DataBind(); + } + catch (Exception exc) + { + //could not load user control + var lex = new PageLoadException("Unhandled error loading page.", exc); + if (TabPermissionController.CanAdminPage()) + { + //only display the error to administrators + var skinError = (Label)page.FindControl("SkinError"); + skinError.Text = string.Format(Localization.GetString("SkinLoadError", Localization.GlobalResourceFile), skinPath, page.Server.HtmlEncode(exc.Message)); + skinError.Visible = true; + } + Exceptions.LogException(lex); + } + return ctlSkin; + } + + private bool ProcessModule(ModuleInfo module) + { + bool success = true; + if (ModuleInjectionManager.CanInjectModule(module, PortalSettings)) + { + Pane pane = GetPane(module); + + if (pane != null) + { + success = InjectModule(pane, module); + } + else + { + var lex = new ModuleLoadException(Localization.GetString("PaneNotFound.Error")); + Controls.Add(new ErrorContainer(PortalSettings, MODULELOAD_ERROR, lex).Container); + Exceptions.LogException(lex); + } + } + return success; + } + + private bool ProcessMasterModules() + { + bool success = true; + if (TabPermissionController.CanViewPage()) + { + //check portal expiry date + if (!CheckExpired()) + { + if ((PortalSettings.ActiveTab.StartDate < DateAndTime.Now && PortalSettings.ActiveTab.EndDate > DateAndTime.Now) || TabPermissionController.CanAdminPage() || Globals.IsLayoutMode()) + { + //dynamically populate the panes with modules + if (PortalSettings.ActiveTab.Modules.Count > 0) + { + foreach (ModuleInfo objModule in PortalSettings.ActiveTab.Modules) + { + success = ProcessModule(objModule); + } + } + } + else + { + AddPageMessage(this, "", Localization.GetString("TabAccess.Error"), ModuleMessage.ModuleMessageType.YellowWarning); + } + } + else + { + AddPageMessage(this, + "", + string.Format(Localization.GetString("ContractExpired.Error"), PortalSettings.PortalName, Globals.GetMediumDate(PortalSettings.ExpiryDate.ToString()), PortalSettings.Email), + ModuleMessage.ModuleMessageType.RedError); + } + } + else + { + Response.Redirect(Globals.AccessDeniedURL(Localization.GetString("TabAccess.Error")), true); + } + return success; + } + + private void ProcessPanes() + { + foreach (KeyValuePair kvp in Panes) + { + kvp.Value.ProcessPane(); + } + } + + private bool ProcessSlaveModule() + { + var success = true; + var key = UIUtilities.GetControlKey(); + var moduleId = UIUtilities.GetModuleId(key); + var slaveModule = UIUtilities.GetSlaveModule(moduleId, key, PortalSettings.ActiveTab.TabID); + + Pane pane; + Panes.TryGetValue(Globals.glbDefaultPane.ToLowerInvariant(), out pane); + slaveModule.PaneName = Globals.glbDefaultPane; + slaveModule.ContainerSrc = PortalSettings.ActiveTab.ContainerSrc; + if (String.IsNullOrEmpty(slaveModule.ContainerSrc)) + { + slaveModule.ContainerSrc = PortalSettings.DefaultPortalContainer; + } + slaveModule.ContainerSrc = SkinController.FormatSkinSrc(slaveModule.ContainerSrc, PortalSettings); + slaveModule.ContainerPath = SkinController.FormatSkinPath(slaveModule.ContainerSrc); + + var moduleControl = ModuleControlController.GetModuleControlByControlKey(key, slaveModule.ModuleDefID); + if (moduleControl != null) + { + slaveModule.ModuleControlId = moduleControl.ModuleControlID; + slaveModule.IconFile = moduleControl.IconFile; + if (ModulePermissionController.HasModuleAccess(slaveModule.ModuleControl.ControlType, Null.NullString, slaveModule)) + { + success = InjectModule(pane, slaveModule); + } + else + { + Response.Redirect(Globals.AccessDeniedURL(Localization.GetString("ModuleAccess.Error")), true); + } + } + + return success; + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// OnInit runs when the Skin is initialised. + /// + /// + /// [cnurse] 07/04/2005 Documented + /// [cnurse] 12/05/2007 Refactored + /// [cnurse] 04/17/2009 Refactored to use SkinAdapter + /// + /// ----------------------------------------------------------------------------- + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + //Load the Panes + LoadPanes(); + + bool success; + //Load the Module Control(s) + success = Globals.IsAdminControl() ? ProcessSlaveModule() : ProcessMasterModules(); + + //Load the Control Panel + InjectControlPanel(); + + //Register any error messages on the Skin + if (Request.QueryString["error"] != null) + { + AddPageMessage(this, Localization.GetString("CriticalError.Error"), Server.HtmlEncode(Request.QueryString["error"]), ModuleMessage.ModuleMessageType.RedError); + } + + if (!TabPermissionController.CanAdminPage() && !success) + { + //only display the warning to non-administrators (administrators will see the errors) + AddPageMessage(this, Localization.GetString("ModuleLoadWarning.Error"), string.Format(Localization.GetString("ModuleLoadWarning.Text"), PortalSettings.Email), ModuleMessage.ModuleMessageType.YellowWarning); + } + + InvokeSkinEvents(SkinEventType.OnSkinInit); + + if (HttpContext.Current != null && HttpContext.Current.Items.Contains(OnInitMessage)) + { + var messageType = ModuleMessage.ModuleMessageType.YellowWarning; + if (HttpContext.Current.Items.Contains(OnInitMessageType)) + { + messageType = (ModuleMessage.ModuleMessageType)Enum.Parse(typeof (ModuleMessage.ModuleMessageType), HttpContext.Current.Items[OnInitMessageType].ToString(), true); + } + AddPageMessage(this, string.Empty, HttpContext.Current.Items[OnInitMessage].ToString(), messageType); + } + + //Process the Panes attributes + ProcessPanes(); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnLoad runs when the Skin is loaded. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + InvokeSkinEvents(SkinEventType.OnSkinLoad); + } + + /// ----------------------------------------------------------------------------- + /// + /// OnLoad runs just before the Skin is rendered. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + + InvokeSkinEvents(SkinEventType.OnSkinPreRender); + + if(TabPermissionController.CanAddContentToPage() && Globals.IsEditMode() && !HttpContext.Current.Request.Url.ToString().Contains("popUp=true")) + { + //Register Drag and Drop plugin + jQuery.RegisterDnnJQueryPlugins(Page); + ClientResourceManager.RegisterStyleSheet(Page, "~/resources/shared/stylesheets/dnn.dragDrop.css", FileOrder.Css.FeatureCss); + ClientResourceManager.RegisterScript(Page, "~/resources/shared/scripts/dnn.dragDrop.js"); + + //Register Client Script + var sb = new StringBuilder(); + sb.AppendLine(" (function ($) {"); + sb.AppendLine(" $(document).ready(function () {"); + sb.AppendLine(" $('.dnnSortable').dnnModuleDragDrop({"); + sb.AppendLine(" tabId: " + PortalSettings.ActiveTab.TabID + ","); + sb.AppendLine(" draggingHintText: '" + Localization.GetSafeJSString("DraggingHintText", Localization.GlobalResourceFile) + "',"); + sb.AppendLine(" dragHintText: '" + Localization.GetSafeJSString("DragModuleHint", Localization.GlobalResourceFile) + "',"); + sb.AppendLine(" dropHintText: '" + Localization.GetSafeJSString("DropModuleHint", Localization.GlobalResourceFile) + "',"); + sb.AppendLine(" dropTargetText: '" + Localization.GetSafeJSString("DropModuleTarget", Localization.GlobalResourceFile) + "'"); + sb.AppendLine(" });"); + sb.AppendLine(" });"); + sb.AppendLine(" } (jQuery));"); + + var script = sb.ToString(); + if (ScriptManager.GetCurrent(Page) != null) + { + // respect MS AJAX + ScriptManager.RegisterStartupScript(Page, GetType(), "DragAndDrop", script, true); + } + else + { + Page.ClientScript.RegisterStartupScript(GetType(), "DragAndDrop", script, true); + } + } + + } + + /// ----------------------------------------------------------------------------- + /// + /// OnUnLoad runs when the Skin is unloaded. + /// + /// + /// [cnurse] 04/17/2009 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnUnload(EventArgs e) + { + base.OnUnload(e); + + InvokeSkinEvents(SkinEventType.OnSkinUnLoad); + } + + #endregion + + #region Public Methods + + public static void AddModuleMessage(PortalModuleBase control, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddModuleMessage(control, "", message, moduleMessageType, Null.NullString); + } + + public static void AddModuleMessage(PortalModuleBase control, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddModuleMessage(control, heading, message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleMessage adds a Moduel Message control to the Skin + /// + /// The Message Text + /// The current control + /// The type of the message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddModuleMessage(Control control, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddModuleMessage(control, "", message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddModuleMessage adds a Moduel Message control to the Skin + /// + /// The Message Heading + /// The Message Text + /// The current control + /// The type of the message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddModuleMessage(Control control, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddModuleMessage(control, heading, message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPageMessage adds a Page Message control to the Skin + /// + /// The Message Heading + /// The Icon to diplay + /// The Message Text + /// The Page + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddPageMessage(Page page, string heading, string message, string iconSrc) + { + AddPageMessage(page, heading, message, ModuleMessage.ModuleMessageType.GreenSuccess, iconSrc); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPageMessage adds a Page Message control to the Skin + /// + /// The Message Heading + /// The Icon to diplay + /// The Message Text + /// The skin + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddPageMessage(Skin skin, string heading, string message, string iconSrc) + { + AddPageMessage(skin, heading, message, ModuleMessage.ModuleMessageType.GreenSuccess, iconSrc); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPageMessage adds a Page Message control to the Skin + /// + /// The Message Heading + /// The Message Text + /// The skin + /// The type of the message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddPageMessage(Skin skin, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddPageMessage(skin, heading, message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddPageMessage adds a Page Message control to the Skin + /// + /// The Message Heading + /// The Message Text + /// The Page + /// The type of the message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static void AddPageMessage(Page page, string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + AddPageMessage(page, heading, message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleMessageControl gets an existing Message Control and sets its properties + /// + /// The Message Heading + /// The Message Text + /// The Message Icon + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static ModuleMessage GetModuleMessageControl(string heading, string message, string iconImage) + { + return GetModuleMessageControl(heading, message, ModuleMessage.ModuleMessageType.GreenSuccess, iconImage); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleMessageControl gets an existing Message Control and sets its properties + /// + /// The Message Heading + /// The Message Text + /// The type of message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static ModuleMessage GetModuleMessageControl(string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType) + { + return GetModuleMessageControl(heading, message, moduleMessageType, Null.NullString); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetModuleMessageControl gets an existing Message Control and sets its properties + /// + /// The Message Heading + /// The Message Text + /// The Message Icon + /// The type of message + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static ModuleMessage GetModuleMessageControl(string heading, string message, ModuleMessage.ModuleMessageType moduleMessageType, string iconImage) + { + + //Use this to get a module message control + //with a standard DotNetNuke icon + var s = new Skin(); + var moduleMessage = (ModuleMessage)s.LoadControl("~/admin/skins/ModuleMessage.ascx"); + moduleMessage.Heading = heading; + moduleMessage.Text = message; + moduleMessage.IconImage = iconImage; + moduleMessage.IconType = moduleMessageType; + return moduleMessage; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetParentSkin gets the Parent Skin for a control + /// + /// The control whose Parent Skin is requested + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static Skin GetParentSkin(PortalModuleBase module) + { + return GetParentSkin(module as Control); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetParentSkin gets the Parent Skin for a control + /// + /// The control whose Parent Skin is requested + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static Skin GetParentSkin(Control control) + { + return ControlUtilities.FindParentControl(control); + } + + /// ----------------------------------------------------------------------------- + /// + /// GetPopUpSkin gets the Skin that is used in modal popup. + /// + /// The Page + /// + /// [vnguyen] 06/07/2011 Created + /// + /// ----------------------------------------------------------------------------- + public static Skin GetPopUpSkin(PageBase page) + { + Skin skin = null; + var skinSource = Null.NullString; + + //attempt to find and load a popup skin from the assigned skinned source + skinSource = Globals.IsAdminSkin() ? SkinController.FormatSkinSrc(page.PortalSettings.DefaultAdminSkin, page.PortalSettings) : page.PortalSettings.ActiveTab.SkinSrc; + if (!String.IsNullOrEmpty(skinSource)) + { + skinSource = SkinController.FormatSkinSrc(SkinController.FormatSkinPath(skinSource) + "popUpSkin.ascx", page.PortalSettings); + + if (File.Exists(HttpContext.Current.Server.MapPath(SkinController.FormatSkinSrc(skinSource, page.PortalSettings)))) + { + skin = LoadSkin(page, skinSource); + } + } + + //error loading popup skin - load default popup skin + if (skin == null) + { + skinSource = Globals.HostPath + "Skins/_default/popUpSkin.ascx"; + skin = LoadSkin(page, skinSource); + } + + //set skin path + page.PortalSettings.ActiveTab.SkinPath = SkinController.FormatSkinPath(skinSource); + + //set skin id to an explicit short name to reduce page payload and make it standards compliant + skin.ID = "dnn"; + + return skin; + } + + /// ----------------------------------------------------------------------------- + /// + /// GetSkin gets the Skin + /// + /// The Page + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public static Skin GetSkin(PageBase page) + { + Skin skin = null; + string skinSource = Null.NullString; + + //skin preview + if ((page.Request.QueryString["SkinSrc"] != null)) + { + skinSource = SkinController.FormatSkinSrc(Globals.QueryStringDecode(page.Request.QueryString["SkinSrc"]) + ".ascx", page.PortalSettings); + skin = LoadSkin(page, skinSource); + } + + //load user skin ( based on cookie ) + if (skin == null) + { + HttpCookie skinCookie = page.Request.Cookies["_SkinSrc" + page.PortalSettings.PortalId]; + if (skinCookie != null) + { + if (!String.IsNullOrEmpty(skinCookie.Value)) + { + skinSource = SkinController.FormatSkinSrc(skinCookie.Value + ".ascx", page.PortalSettings); + skin = LoadSkin(page, skinSource); + } + } + } + + //load assigned skin + if (skin == null) + { + skinSource = Globals.IsAdminSkin() ? SkinController.FormatSkinSrc(page.PortalSettings.DefaultAdminSkin, page.PortalSettings) : page.PortalSettings.ActiveTab.SkinSrc; + if (!String.IsNullOrEmpty(skinSource)) + { + skinSource = SkinController.FormatSkinSrc(skinSource, page.PortalSettings); + skin = LoadSkin(page, skinSource); + } + } + + //error loading skin - load default + if (skin == null) + { + skinSource = SkinController.FormatSkinSrc(SkinController.GetDefaultPortalSkin(), page.PortalSettings); + skin = LoadSkin(page, skinSource); + } + + //set skin path + page.PortalSettings.ActiveTab.SkinPath = SkinController.FormatSkinPath(skinSource); + + //set skin id to an explicit short name to reduce page payload and make it standards compliant + skin.ID = "dnn"; + + return skin; + } + + /// ----------------------------------------------------------------------------- + /// + /// InjectModule injects the module into the Pane + /// + /// The module to inject + /// The pane + /// + /// [cnurse] 12/04/2007 created + /// [cnurse] 04/17/2009 Refactored to use SkinAdapter + /// + /// ----------------------------------------------------------------------------- + public bool InjectModule(Pane pane, ModuleInfo module) + { + bool bSuccess = true; + + //try to inject the module into the pane + try + { + if(PortalSettings.ActiveTab.TabID == PortalSettings.UserTabId || PortalSettings.ActiveTab.ParentId == PortalSettings.UserTabId) + { + var profileModule = ModuleControlFactory.LoadModuleControl(Page, module) as IProfileModule; + if (profileModule == null || profileModule.DisplayModule) + { + pane.InjectModule(module); + } + } + else + { + pane.InjectModule(module); + } + + } + catch (Exception ex) + { + Exceptions.LogException(ex); + bSuccess = false; + } + return bSuccess; + } + + /// ----------------------------------------------------------------------------- + /// + /// RegisterModuleActionEvent registers a Module Action Event + /// + /// The ID of the module + /// An Action Event Handler + /// + /// [cnurse] 12/04/2007 documented + /// + /// ----------------------------------------------------------------------------- + public void RegisterModuleActionEvent(int moduleId, ActionEventHandler e) + { + ActionEventListeners.Add(new ModuleActionEventListener(moduleId, e)); + } + + + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/SkinControl.cs b/DNN Platform/Library/UI/Skins/SkinControl.cs new file mode 100644 index 00000000000..4e98b51fd04 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinControl.cs @@ -0,0 +1,284 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + public class SkinControl : UserControlBase + { + #region "Private Members" + + private string _DefaultKey = "System"; + private string _SkinRoot; + private string _SkinSrc; + private string _Width = ""; + private string _localResourceFile; + private PortalInfo _objPortal; + protected DropDownList cboSkin; + protected CommandButton cmdPreview; + protected RadioButton optHost; + protected RadioButton optSite; + + #endregion + + #region "Public Properties" + + public string DefaultKey + { + get + { + return _DefaultKey; + } + set + { + _DefaultKey = value; + } + } + + public string Width + { + get + { + return Convert.ToString(ViewState["SkinControlWidth"]); + } + set + { + _Width = value; + } + } + + public string SkinRoot + { + get + { + return Convert.ToString(ViewState["SkinRoot"]); + } + set + { + _SkinRoot = value; + } + } + + public string SkinSrc + { + get + { + if (cboSkin.SelectedItem != null) + { + return cboSkin.SelectedItem.Value; + } + else + { + return ""; + } + } + set + { + _SkinSrc = value; + } + } + + public string LocalResourceFile + { + get + { + string fileRoot; + if (String.IsNullOrEmpty(_localResourceFile)) + { + fileRoot = TemplateSourceDirectory + "/" + Localization.LocalResourceDirectory + "/SkinControl.ascx"; + } + else + { + fileRoot = _localResourceFile; + } + return fileRoot; + } + set + { + _localResourceFile = value; + } + } + + #endregion + + #region "Private Methods" + + private void LoadSkins() + { + cboSkin.Items.Clear(); + + if (optHost.Checked) + { + // load host skins + foreach (KeyValuePair Skin in SkinController.GetSkins(_objPortal, SkinRoot, SkinScope.Host)) + { + cboSkin.Items.Add(new ListItem(Skin.Key, Skin.Value)); + } + } + + if (optSite.Checked) + { + // load portal skins + foreach (KeyValuePair Skin in SkinController.GetSkins(_objPortal, SkinRoot, SkinScope.Site)) + { + cboSkin.Items.Add(new ListItem(Skin.Key, Skin.Value)); + } + } + + cboSkin.Items.Insert(0, new ListItem("<" + Localization.GetString(DefaultKey, LocalResourceFile) + ">", "")); + + + // select current skin + for (int intIndex = 0; intIndex < cboSkin.Items.Count; intIndex++) + { + if (cboSkin.Items[intIndex].Value.ToLower() == Convert.ToString(ViewState["SkinSrc"]).ToLower()) + { + cboSkin.Items[intIndex].Selected = true; + break; + } + } + } + + #endregion + + #region "Event Handlers" + + /// + /// The Page_Load server event handler on this page is used + /// to populate the role information for the page + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + #region Bind Handles + + optHost.CheckedChanged += optHost_CheckedChanged; + optSite.CheckedChanged += optSite_CheckedChanged; + cmdPreview.Click += cmdPreview_Click; + + #endregion + + try + { + var objPortals = new PortalController(); + if (Request.QueryString["pid"] != null && (Globals.IsHostTab(PortalSettings.ActiveTab.TabID) || UserController.GetCurrentUserInfo().IsSuperUser)) + { + _objPortal = objPortals.GetPortal(Int32.Parse(Request.QueryString["pid"])); + } + else + { + _objPortal = objPortals.GetPortal(PortalSettings.PortalId); + } + if (!Page.IsPostBack) + { + //save persistent values + ViewState["SkinControlWidth"] = _Width; + ViewState["SkinRoot"] = _SkinRoot; + ViewState["SkinSrc"] = _SkinSrc; + + //set width of control + if (!String.IsNullOrEmpty(_Width)) + { + cboSkin.Width = Unit.Parse(_Width); + } + + //set selected skin + if (!String.IsNullOrEmpty(_SkinSrc)) + { + switch (_SkinSrc.Substring(0, 3)) + { + case "[L]": + optHost.Checked = false; + optSite.Checked = true; + break; + case "[G]": + optSite.Checked = false; + optHost.Checked = true; + break; + } + } + else + { + //no skin selected, initialized to site skin if any exists + string strRoot = _objPortal.HomeDirectoryMapPath + SkinRoot; + if (Directory.Exists(strRoot) && Directory.GetDirectories(strRoot).Length > 0) + { + optHost.Checked = false; + optSite.Checked = true; + } + } + LoadSkins(); + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void optHost_CheckedChanged(object sender, EventArgs e) + { + LoadSkins(); + } + + protected void optSite_CheckedChanged(object sender, EventArgs e) + { + LoadSkins(); + } + + protected void cmdPreview_Click(object sender, EventArgs e) + { + if (!String.IsNullOrEmpty(SkinSrc)) + { + string strType = SkinRoot.Substring(0, SkinRoot.Length - 1); + + string strURL = Globals.ApplicationURL() + "&" + strType + "Src=" + Globals.QueryStringEncode(SkinSrc.Replace(".ascx", "")); + + if (SkinRoot == SkinController.RootContainer) + { + if (Request.QueryString["ModuleId"] != null) + { + strURL += "&ModuleId=" + Request.QueryString["ModuleId"]; + } + } + Response.Redirect(strURL, true); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinController.cs b/DNN Platform/Library/UI/Skins/SkinController.cs new file mode 100644 index 00000000000..1c15b382e9e --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinController.cs @@ -0,0 +1,595 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Users; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; + +using ICSharpCode.SharpZipLib.Zip; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinController + /// + /// ----------------------------------------------------------------------------- + /// + /// Handles the Business Control Layer for Skins + /// + /// + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public class SkinController + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SkinController)); + #region Public Shared Properties + + public static string RootSkin + { + get + { + return "Skins"; + } + } + + public static string RootContainer + { + get + { + return "Containers"; + } + } + + #endregion + + #region Public Shared Methods + + private static void AddSkinFiles(List> skins, string skinRoot, string skinFolder, bool isPortal) + { + foreach (string skinFile in Directory.GetFiles(skinFolder, "*.ascx")) + { + string folder = skinFolder.Substring(skinFolder.LastIndexOf("\\") + 1); + + string key = ((isPortal) ? "Site: " : "Host: ") + FormatSkinName(folder, Path.GetFileNameWithoutExtension(skinFile)); + string prefix = (isPortal) ? "[L]" : "[G]"; + string value = prefix + skinRoot + "/" + folder + "/" + Path.GetFileName(skinFile); + skins.Add(new KeyValuePair(key, value)); + } + } + + private static List> GetHostSkins(string skinRoot) + { + var skins = new List>(); + + string root = Globals.HostMapPath + skinRoot; + if (Directory.Exists(root)) + { + foreach (string skinFolder in Directory.GetDirectories(root)) + { + if (!skinFolder.EndsWith(Globals.glbHostSkinFolder)) + { + AddSkinFiles(skins, skinRoot, skinFolder, false); + } + } + } + return skins; + } + + private static List> GetPortalSkins(PortalInfo portalInfo, string skinRoot) + { + var skins = new List>(); + + if (portalInfo != null) + { + string rootFolder = portalInfo.HomeDirectoryMapPath + skinRoot; + if (Directory.Exists(rootFolder)) + { + foreach (string skinFolder in Directory.GetDirectories(rootFolder)) + { + AddSkinFiles(skins, skinRoot, skinFolder, true); + } + } + } + return skins; + } + + + public static int AddSkin(int skinPackageID, string skinSrc) + { + return DataProvider.Instance().AddSkin(skinPackageID, skinSrc); + } + + public static int AddSkinPackage(SkinPackageInfo skinPackage) + { + var eventLogController = new EventLogController(); + eventLogController.AddLog(skinPackage, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINPACKAGE_CREATED); + return DataProvider.Instance().AddSkinPackage(skinPackage.PackageID, skinPackage.PortalID, skinPackage.SkinName, skinPackage.SkinType, UserController.GetCurrentUserInfo().UserID); + } + + public static bool CanDeleteSkin(string folderPath, string portalHomeDirMapPath) + { + string skinType; + string skinFolder; + bool canDelete = true; + if (folderPath.ToLower().IndexOf(Globals.HostMapPath.ToLower()) != -1) + { + skinType = "G"; + skinFolder = folderPath.ToLower().Replace(Globals.HostMapPath.ToLower(), "").Replace("\\", "/"); + } + else + { + skinType = "L"; + skinFolder = folderPath.ToLower().Replace(portalHomeDirMapPath.ToLower(), "").Replace("\\", "/"); + } + var portalSettings = PortalController.GetCurrentPortalSettings(); + + string skin = "[" + skinType.ToLowerInvariant() + "]" + skinFolder.ToLowerInvariant(); + if (skinFolder.ToLowerInvariant().Contains("skins")) + { + if (Host.DefaultAdminSkin.ToLowerInvariant().StartsWith(skin) || Host.DefaultPortalSkin.ToLowerInvariant().StartsWith(skin) || + portalSettings.DefaultAdminSkin.ToLowerInvariant().StartsWith(skin) || portalSettings.DefaultPortalSkin.ToLowerInvariant().StartsWith(skin)) + { + canDelete = false; + } + } + else + { + if (Host.DefaultAdminContainer.ToLowerInvariant().StartsWith(skin) || Host.DefaultPortalContainer.ToLowerInvariant().StartsWith(skin) || + portalSettings.DefaultAdminContainer.ToLowerInvariant().StartsWith(skin) || portalSettings.DefaultPortalContainer.ToLowerInvariant().StartsWith(skin)) + { + canDelete = false; + } + } + if (canDelete) + { + //Check if used for Tabs or Modules + canDelete = DataProvider.Instance().CanDeleteSkin(skinType, skinFolder); + } + return canDelete; + } + + public static void DeleteSkin(int skinID) + { + DataProvider.Instance().DeleteSkin(skinID); + } + + public static void DeleteSkinPackage(SkinPackageInfo skinPackage) + { + DataProvider.Instance().DeleteSkinPackage(skinPackage.SkinPackageID); + var eventLogController = new EventLogController(); + eventLogController.AddLog(skinPackage, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINPACKAGE_DELETED); + } + + public static string FormatMessage(string title, string body, int level, bool isError) + { + string message = title; + if (isError) + { + message = "" + title + ""; + } + switch (level) + { + case -1: + message = "

    " + message + ""; + break; + case 0: + message = "

    " + message + ""; + break; + case 1: + message = "
    " + message + ""; + break; + default: + message = "
  • " + message + "
  • "; + break; + } + return message + ": " + body + Environment.NewLine; + } + + public static string FormatSkinPath(string skinSrc) + { + string strSkinSrc = skinSrc; + if (!String.IsNullOrEmpty(strSkinSrc)) + { + strSkinSrc = strSkinSrc.Substring(0, strSkinSrc.LastIndexOf("/") + 1); + } + return strSkinSrc; + } + + public static string FormatSkinSrc(string skinSrc, PortalSettings portalSettings) + { + string strSkinSrc = skinSrc; + if (!String.IsNullOrEmpty(strSkinSrc)) + { + switch (strSkinSrc.ToLowerInvariant().Substring(0, 3)) + { + case "[g]": + strSkinSrc = Regex.Replace(strSkinSrc, "\\[g]", Globals.HostPath, RegexOptions.IgnoreCase); + break; + case "[l]": + strSkinSrc = Regex.Replace(strSkinSrc, "\\[l]", portalSettings.HomeDirectory, RegexOptions.IgnoreCase); + break; + } + } + return strSkinSrc; + } + + public static string GetDefaultAdminContainer() + { + SkinDefaults defaultContainer = SkinDefaults.GetSkinDefaults(SkinDefaultType.ContainerInfo); + return "[G]" + RootContainer + defaultContainer.Folder + defaultContainer.AdminDefaultName; + } + + public static string GetDefaultAdminSkin() + { + SkinDefaults defaultSkin = SkinDefaults.GetSkinDefaults(SkinDefaultType.SkinInfo); + return "[G]" + RootSkin + defaultSkin.Folder + defaultSkin.AdminDefaultName; + } + + public static string GetDefaultPortalContainer() + { + SkinDefaults defaultContainer = SkinDefaults.GetSkinDefaults(SkinDefaultType.ContainerInfo); + return "[G]" + RootContainer + defaultContainer.Folder + defaultContainer.DefaultName; + } + + public static string GetDefaultPortalSkin() + { + SkinDefaults defaultSkin = SkinDefaults.GetSkinDefaults(SkinDefaultType.SkinInfo); + return "[G]" + RootSkin + defaultSkin.Folder + defaultSkin.DefaultName; + } + + public static SkinPackageInfo GetSkinByPackageID(int packageID) + { + return CBO.FillObject(DataProvider.Instance().GetSkinByPackageID(packageID)); + } + + public static SkinPackageInfo GetSkinPackage(int portalId, string skinName, string skinType) + { + return CBO.FillObject(DataProvider.Instance().GetSkinPackage(portalId, skinName, skinType)); + } + + public static List> GetSkins(PortalInfo portalInfo, string skinRoot, SkinScope scope) + { + var skins = new List>(); + switch (scope) + { + case SkinScope.Host: //load host skins + skins = GetHostSkins(skinRoot); + break; + case SkinScope.Site: //load portal skins + skins = GetPortalSkins(portalInfo, skinRoot); + break; + case SkinScope.All: + skins = GetHostSkins(skinRoot); + skins.AddRange(GetPortalSkins(portalInfo, skinRoot)); + break; + } + return skins; + } + + /// ----------------------------------------------------------------------------- + /// + /// format skin name + /// + /// + /// + /// The Folder Name + /// The File Name without extension + /// + /// + /// ----------------------------------------------------------------------------- + private static string FormatSkinName(string skinFolder, string skinFile) + { + if (skinFolder.ToLower() == "_default") + { + // host folder + return skinFile; + + } + + //portal folder + switch (skinFile.ToLower()) + { + case "skin": + case "container": + case "default": + return skinFolder; + default: + return skinFolder + " - " + skinFile; + } + } + + /// + /// Determines if a given skin is defined as a global skin + /// + /// This is the app relative path and filename of the skin to be checked. + /// True if the skin is located in the HostPath child directories. + /// This function performs a quick check to detect the type of skin that is + /// passed as a parameter. Using this method abstracts knowledge of the actual location + /// of skins in the file system. + /// + /// + /// [Joe Brinkman] 10/20/2007 Created + /// + public static bool IsGlobalSkin(string skinSrc) + { + return skinSrc.Contains(Globals.HostPath); + } + + public static void SetSkin(string skinRoot, int portalId, SkinType skinType, string skinSrc) + { + switch (skinRoot) + { + case "Skins": + if (skinType == SkinType.Admin) + { + if (portalId == Null.NullInteger) + { + HostController.Instance.Update("DefaultAdminSkin", skinSrc); + } + else + { + PortalController.UpdatePortalSetting(portalId, "DefaultAdminSkin", skinSrc); + } + } + else + { + if (portalId == Null.NullInteger) + { + HostController.Instance.Update("DefaultPortalSkin", skinSrc); + } + else + { + PortalController.UpdatePortalSetting(portalId, "DefaultPortalSkin", skinSrc); + } + } + break; + case "Containers": + if (skinType == SkinType.Admin) + { + if (portalId == Null.NullInteger) + { + HostController.Instance.Update("DefaultAdminContainer", skinSrc); + } + else + { + PortalController.UpdatePortalSetting(portalId, "DefaultAdminContainer", skinSrc); + } + } + else + { + if (portalId == Null.NullInteger) + { + HostController.Instance.Update("DefaultPortalContainer", skinSrc); + } + else + { + PortalController.UpdatePortalSetting(portalId, "DefaultPortalContainer", skinSrc); + } + } + break; + } + } + + public static void UpdateSkin(int skinID, string skinSrc) + { + DataProvider.Instance().UpdateSkin(skinID, skinSrc); + } + + public static void UpdateSkinPackage(SkinPackageInfo skinPackage) + { + DataProvider.Instance().UpdateSkinPackage(skinPackage.SkinPackageID, + skinPackage.PackageID, + skinPackage.PortalID, + skinPackage.SkinName, + skinPackage.SkinType, + UserController.GetCurrentUserInfo().UserID); + var eventLogController = new EventLogController(); + eventLogController.AddLog(skinPackage, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", EventLogController.EventLogType.SKINPACKAGE_UPDATED); + foreach (KeyValuePair kvp in skinPackage.Skins) + { + UpdateSkin(kvp.Key, kvp.Value); + } + } + + public static string UploadLegacySkin(string rootPath, string skinRoot, string skinName, Stream inputStream) + { + var objZipInputStream = new ZipInputStream(inputStream); + + ZipEntry objZipEntry; + string strExtension; + string strFileName; + FileStream objFileStream; + int intSize = 2048; + var arrData = new byte[2048]; + string strMessage = ""; + var arrSkinFiles = new ArrayList(); + + //Localized Strings + PortalSettings ResourcePortalSettings = Globals.GetPortalSettings(); + string BEGIN_MESSAGE = Localization.GetString("BeginZip", ResourcePortalSettings); + string CREATE_DIR = Localization.GetString("CreateDir", ResourcePortalSettings); + string WRITE_FILE = Localization.GetString("WriteFile", ResourcePortalSettings); + string FILE_ERROR = Localization.GetString("FileError", ResourcePortalSettings); + string END_MESSAGE = Localization.GetString("EndZip", ResourcePortalSettings); + string FILE_RESTICTED = Localization.GetString("FileRestricted", ResourcePortalSettings); + + strMessage += FormatMessage(BEGIN_MESSAGE, skinName, -1, false); + + objZipEntry = objZipInputStream.GetNextEntry(); + while (objZipEntry != null) + { + if (!objZipEntry.IsDirectory) + { + //validate file extension + strExtension = objZipEntry.Name.Substring(objZipEntry.Name.LastIndexOf(".") + 1); + var extraExtensions = new List {".ASCX", ".HTM", ".HTML", ".CSS", ".SWF", ".RESX", ".XAML", ".JS"}; + if(Host.AllowedExtensionWhitelist.IsAllowedExtension(strExtension, extraExtensions)) + { + //process embedded zip files + if (objZipEntry.Name.ToLower() == RootSkin.ToLower() + ".zip") + { + var objMemoryStream = new MemoryStream(); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + while (intSize > 0) + { + objMemoryStream.Write(arrData, 0, intSize); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + } + objMemoryStream.Seek(0, SeekOrigin.Begin); + strMessage += UploadLegacySkin(rootPath, RootSkin, skinName, objMemoryStream); + } + else if (objZipEntry.Name.ToLower() == RootContainer.ToLower() + ".zip") + { + var objMemoryStream = new MemoryStream(); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + while (intSize > 0) + { + objMemoryStream.Write(arrData, 0, intSize); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + } + objMemoryStream.Seek(0, SeekOrigin.Begin); + strMessage += UploadLegacySkin(rootPath, RootContainer, skinName, objMemoryStream); + } + else + { + strFileName = rootPath + skinRoot + "\\" + skinName + "\\" + objZipEntry.Name; + + //create the directory if it does not exist + if (!Directory.Exists(Path.GetDirectoryName(strFileName))) + { + strMessage += FormatMessage(CREATE_DIR, Path.GetDirectoryName(strFileName), 2, false); + Directory.CreateDirectory(Path.GetDirectoryName(strFileName)); + } + + //remove the old file + if (File.Exists(strFileName)) + { + File.SetAttributes(strFileName, FileAttributes.Normal); + File.Delete(strFileName); + } + + //create the new file + objFileStream = File.Create(strFileName); + + //unzip the file + strMessage += FormatMessage(WRITE_FILE, Path.GetFileName(strFileName), 2, false); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + while (intSize > 0) + { + objFileStream.Write(arrData, 0, intSize); + intSize = objZipInputStream.Read(arrData, 0, arrData.Length); + } + objFileStream.Close(); + + //save the skin file + switch (Path.GetExtension(strFileName)) + { + case ".htm": + case ".html": + case ".ascx": + case ".css": + if (strFileName.ToLower().IndexOf(Globals.glbAboutPage.ToLower()) < 0) + { + arrSkinFiles.Add(strFileName); + } + break; + } + break; + } + } + else + { + strMessage += string.Format(FILE_RESTICTED, objZipEntry.Name, Host.AllowedExtensionWhitelist.ToStorageString(), ",", ", *.").Replace("2", "true"); + } + } + objZipEntry = objZipInputStream.GetNextEntry(); + } + strMessage += FormatMessage(END_MESSAGE, skinName + ".zip", 1, false); + objZipInputStream.Close(); + + //process the list of skin files + var NewSkin = new SkinFileProcessor(rootPath, skinRoot, skinName); + strMessage += NewSkin.ProcessList(arrSkinFiles, SkinParser.Portable); + + //log installation event + try + { + var objEventLogInfo = new LogInfo(); + objEventLogInfo.LogTypeKey = EventLogController.EventLogType.HOST_ALERT.ToString(); + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Install Skin:", skinName)); + Array arrMessage = strMessage.Split(new[] {"
    "}, StringSplitOptions.None); + foreach (string strRow in arrMessage) + { + objEventLogInfo.LogProperties.Add(new LogDetailInfo("Info:", HtmlUtils.StripTags(strRow, true))); + } + var objEventLog = new EventLogController(); + objEventLog.AddLog(objEventLogInfo); + } + catch (Exception exc) + { + Logger.Error(exc); + + } + return strMessage; + } + + #endregion + + #region Obsolete + + [Obsolete("In DotNetNuke 5.0, the Skins are uploaded by using the new Installer")] + public static string UploadSkin(string rootPath, string skinRoot, string skinName, string path) + { + var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); + string strMessage = UploadLegacySkin(rootPath, skinRoot, skinName, fileStream); + fileStream.Close(); + return strMessage; + } + + [Obsolete("In DotNetNuke 5.0, the Skins are uploaded by using the new Installer")] + public static string UploadSkin(string rootPath, string skinRoot, string skinName, Stream inputStream) + { + return UploadLegacySkin(rootPath, skinRoot, skinName, inputStream); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinDefaults.cs b/DNN Platform/Library/UI/Skins/SkinDefaults.cs new file mode 100644 index 00000000000..391d6bda971 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinDefaults.cs @@ -0,0 +1,107 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Xml; + +using DotNetNuke.Common.Utilities; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + public enum SkinDefaultType + { + SkinInfo, + ContainerInfo + } + + [Serializable] + public class SkinDefaults + { + private string _adminDefaultName; + private string _defaultName; + private string _folder; + + private SkinDefaults(SkinDefaultType DefaultType) + { + string nodename = Enum.GetName(DefaultType.GetType(), DefaultType).ToLower(); + string filePath = Config.GetPathToFile(Config.ConfigFileType.DotNetNuke); + var dnndoc = new XmlDocument(); + dnndoc.Load(filePath); + XmlNode defaultElement = dnndoc.SelectSingleNode("/configuration/skinningdefaults/" + nodename); + _folder = defaultElement.Attributes["folder"].Value; + _defaultName = defaultElement.Attributes["default"].Value; + _adminDefaultName = defaultElement.Attributes["admindefault"].Value; + } + + public string AdminDefaultName + { + get + { + return _adminDefaultName; + } + set + { + _adminDefaultName = value; + } + } + + public string DefaultName + { + get + { + return _defaultName; + } + set + { + _defaultName = value; + } + } + + public string Folder + { + get + { + return _folder; + } + set + { + _folder = value; + } + } + + private static object GetSkinDefaultsCallback(CacheItemArgs cacheItemArgs) + { + var defaultType = (SkinDefaultType) cacheItemArgs.ParamList[0]; + return new SkinDefaults(defaultType); + } + + public static SkinDefaults GetSkinDefaults(SkinDefaultType DefaultType) + { + return + CBO.GetCachedObject( + new CacheItemArgs(string.Format(DataCache.SkinDefaultsCacheKey, DefaultType), DataCache.SkinDefaultsCacheTimeOut, DataCache.SkinDefaultsCachePriority, DefaultType), + GetSkinDefaultsCallback); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinFileProcessor.cs b/DNN Platform/Library/UI/Skins/SkinFileProcessor.cs new file mode 100644 index 00000000000..ca2c9267921 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinFileProcessor.cs @@ -0,0 +1,1391 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.IO; +using System.Text.RegularExpressions; +using System.Web; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Installer; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + public enum SkinParser + { + Localized, + Portable + } + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinFileProcessor + /// + /// ----------------------------------------------------------------------------- + /// + /// Handles processing of a list of uploaded skin files into a working skin. + /// + /// + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public class SkinFileProcessor + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SkinFileProcessor)); + #region "Private Members" + + private readonly string DUPLICATE_DETAIL = Util.GetLocalizedString("DuplicateSkinObject.Detail"); + private readonly string DUPLICATE_ERROR = Util.GetLocalizedString("DuplicateSkinObject.Error"); + private readonly string FILES_END = Util.GetLocalizedString("EndSkinFiles"); + private readonly string FILE_BEGIN = Util.GetLocalizedString("BeginSkinFile"); + private readonly string FILE_END = Util.GetLocalizedString("EndSkinFile"); + private readonly string INITIALIZE_PROCESSOR = Util.GetLocalizedString("StartProcessor"); + private readonly string LOAD_SKIN_TOKEN = Util.GetLocalizedString("LoadingSkinToken"); + private readonly string PACKAGE_LOAD = Util.GetLocalizedString("PackageLoad"); + private readonly string PACKAGE_LOAD_ERROR = Util.GetLocalizedString("PackageLoad.Error"); + private readonly ControlParser m_ControlFactory; + private readonly Hashtable m_ControlList = new Hashtable(); + private readonly ObjectParser m_ObjectFactory; + private readonly PathParser m_PathFactory = new PathParser(); + private readonly XmlDocument m_SkinAttributes = new XmlDocument(); + private readonly string m_SkinName; + private readonly string m_SkinPath; + private readonly string m_SkinRoot; + private string m_Message = ""; + + #endregion + + #region "Constructors" + + /// ----------------------------------------------------------------------------- + /// + /// SkinFileProcessor class constructor. + /// + /// + /// This constructor parses a memory based skin + /// + /// + /// [cnurse] 3/21/2005 Created + /// + /// ----------------------------------------------------------------------------- + public SkinFileProcessor(string ControlKey, string ControlSrc) + { + m_ControlList.Add(ControlKey, ControlSrc); + + //Instantiate the control parser with the list of skin objects + m_ControlFactory = new ControlParser(m_ControlList); + + //Instantiate the object parser with the list of skin objects + m_ObjectFactory = new ObjectParser(m_ControlList); + } + + /// ----------------------------------------------------------------------------- + /// + /// SkinFileProcessor class constructor. + /// + /// File path to the portals upload directory. + /// Specifies type of skin (Skins or Containers) + /// Name of folder in which skin will reside (Zip file name) + /// + /// The constructor primes the file processor with path information and + /// control data that should only be retrieved once. It checks for the + /// existentce of a skin level attribute file and read it in, if found. + /// It also sorts through the complete list of controls and creates + /// a hashtable which contains only the skin objects and their source paths. + /// These are recognized by their ControlKey's which are formatted like + /// tokens ("[TOKEN]"). The hashtable is required for speed as it will be + /// processed for each token found in the source file by the Control Parser. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public SkinFileProcessor(string SkinPath, string SkinRoot, string SkinName) + { + Message += SkinController.FormatMessage(INITIALIZE_PROCESSOR, SkinRoot + " :: " + SkinName, 0, false); + + //Save path information for future use + m_SkinRoot = SkinRoot; + m_SkinPath = SkinPath; + m_SkinName = SkinName; + + //Check for and read skin package level attribute information file + string FileName = this.SkinPath + this.SkinRoot + "\\" + this.SkinName + "\\" + SkinRoot.Substring(0, SkinRoot.Length - 1) + ".xml"; + if (File.Exists(FileName)) + { + try + { + SkinAttributes.Load(FileName); + Message += SkinController.FormatMessage(PACKAGE_LOAD, Path.GetFileName(FileName), 2, false); + } + catch (Exception ex) + { + //could not load XML file + Logger.Error(ex); + Message += SkinController.FormatMessage(string.Format(PACKAGE_LOAD_ERROR, ex.Message), Path.GetFileName(FileName), 2, true); + } + } + + //Look at every control + string Token; + foreach (SkinControlInfo objSkinControl in SkinControlController.GetSkinControls().Values) + { + Token = objSkinControl.ControlKey.ToUpper(); + + //If the control is already in the hash table + if (m_ControlList.ContainsKey(Token)) + { + Message += SkinController.FormatMessage(string.Format(DUPLICATE_ERROR, objSkinControl.ControlKey.ToUpper()), + string.Format(DUPLICATE_DETAIL, m_ControlList[Token], objSkinControl.ControlSrc), + 2, + true); + } + else + { + //Add it + Message += SkinController.FormatMessage(string.Format(LOAD_SKIN_TOKEN, objSkinControl.ControlKey.ToUpper()), objSkinControl.ControlSrc, 2, false); + m_ControlList.Add(Token, objSkinControl.ControlSrc); + } + } + + //Instantiate the control parser with the list of skin objects + m_ControlFactory = new ControlParser(m_ControlList); + + //Instantiate the object parser with the list of skin objects + m_ObjectFactory = new ObjectParser(m_ControlList); + } + + #endregion + + #region "Private Properties" + + private PathParser PathFactory + { + get + { + return m_PathFactory; + } + } + + private ControlParser ControlFactory + { + get + { + return m_ControlFactory; + } + } + + private ObjectParser ObjectFactory + { + get + { + return m_ObjectFactory; + } + } + + private XmlDocument SkinAttributes + { + get + { + return m_SkinAttributes; + } + } + + private string Message + { + get + { + return m_Message; + } + set + { + m_Message = value; + } + } + + #endregion + + #region "Public Properties" + + public string SkinRoot + { + get + { + return m_SkinRoot; + } + } + + public string SkinPath + { + get + { + return m_SkinPath; + } + } + + public string SkinName + { + get + { + return m_SkinName; + } + } + + #endregion + + #region "Public Methods" + + public string ProcessFile(string FileName, SkinParser ParseOption) + { + string strMessage = SkinController.FormatMessage(FILE_BEGIN, Path.GetFileName(FileName), 0, false); + var objSkinFile = new SkinFile(SkinRoot, FileName, SkinAttributes); + switch (objSkinFile.FileExtension) + { + case ".htm": + case ".html": + string contents = objSkinFile.Contents; + strMessage += ObjectFactory.Parse(ref contents); + strMessage += PathFactory.Parse(ref contents, PathFactory.HTMLList, objSkinFile.SkinRootPath, ParseOption); + strMessage += ControlFactory.Parse(ref contents, objSkinFile.Attributes); + objSkinFile.Contents = contents; + var Registrations = new ArrayList(); + Registrations.AddRange(ControlFactory.Registrations); + Registrations.AddRange(ObjectFactory.Registrations); + strMessage += objSkinFile.PrependASCXDirectives(Registrations); + break; + } + objSkinFile.Write(); + strMessage += objSkinFile.Messages; + strMessage += SkinController.FormatMessage(FILE_END, Path.GetFileName(FileName), 1, false); + return strMessage; + } + + /// ----------------------------------------------------------------------------- + /// + /// Perform processing on list of files to generate skin. + /// + /// ArrayList of files to be processed. + /// HTML formatted string of informational messages. + /// + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string ProcessList(ArrayList FileList) + { + return ProcessList(FileList, SkinParser.Localized); + } + + public string ProcessList(ArrayList FileList, SkinParser ParseOption) + { + foreach (string FileName in FileList) + { + Message += ProcessFile(FileName, ParseOption); + } + Message += SkinController.FormatMessage(FILES_END, SkinRoot + " :: " + SkinName, 0, false); + return Message; + } + + public string ProcessSkin(string SkinSource, XmlDocument SkinAttributes, SkinParser ParseOption) + { + var objSkinFile = new SkinFile(SkinSource, SkinAttributes); + string contents = objSkinFile.Contents; + Message += ControlFactory.Parse(ref contents, objSkinFile.Attributes); + Message += objSkinFile.PrependASCXDirectives(ControlFactory.Registrations); + return contents; + } + + #endregion + + #region Nested type: ControlParser + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinFileProcessor.ControlParser + /// + /// ----------------------------------------------------------------------------- + /// + /// Parsing functionality for token replacement in new skin files. + /// + /// + /// This class encapsulates the data and methods necessary to appropriately + /// handle all the token parsing needs for new skin files (which is appropriate + /// only for HTML files). The parser accomodates some ill formatting of tokens + /// (ignoring whitespace and casing) and allows for naming of token instances + /// if more than one instance of a particular control is desired on a skin. The + /// proper syntax for an instance is: "[TOKEN:INSTANCE]" where the instance can + /// be any alphanumeric string. Generated control ID's all take the + /// form of "TOKENINSTANCE". + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private class ControlParser + { + private readonly Hashtable m_ControlList = new Hashtable(); + private readonly string m_InitMessages = ""; + private XmlDocument m_Attributes = new XmlDocument(); + private string m_ParseMessages = ""; + private ArrayList m_RegisterList = new ArrayList(); + + /// ----------------------------------------------------------------------------- + /// + /// ControlParser class constructor. + /// + /// + /// The constructor processes accepts a hashtable of skin objects to process against. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public ControlParser(Hashtable ControlList) + { + m_ControlList = (Hashtable)ControlList.Clone(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Registration directives generated as a result of the Parse method. + /// + /// ArrayList of formatted registration directives. + /// + /// In addition to the updated file contents, the Parse method also + /// creates this list of formatted registration directives which can + /// be processed later. They are not performed in place during the + /// Parse method in order to preserve the formatting of the input file + /// in case additional parsing might not anticipate the formatting of + /// those directives. Since they are properly formatted, it is better + /// to exclude them from being subject to parsing. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + internal ArrayList Registrations + { + get + { + return m_RegisterList; + } + } + + private MatchEvaluator Handler + { + get + { + return TokenMatchHandler; + } + } + + private ArrayList RegisterList + { + get + { + return m_RegisterList; + } + set + { + m_RegisterList = value; + } + } + + private Hashtable ControlList + { + get + { + return m_ControlList; + } + } + + private XmlDocument Attributes + { + get + { + return m_Attributes; + } + set + { + m_Attributes = value; + } + } + + private string Messages + { + get + { + return m_ParseMessages; + } + set + { + m_ParseMessages = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Perform parsing on the specified source file using the specified attributes. + /// + /// Pointer to Source string to be parsed. + /// XML document containing token attribute information (can be empty). + /// + /// This procedure invokes a handler for each match of a formatted token. + /// The attributes are first set because they will be referenced by the + /// match handler. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string Parse(ref string Source, XmlDocument Attributes) + { + Messages = m_InitMessages; + //set the token attributes + this.Attributes = Attributes; + //clear register list + RegisterList.Clear(); + + //define the regular expression to match tokens + var FindTokenInstance = new Regex("\\[\\s*(?\\w*)\\s*:?\\s*(?\\w*)\\s*]", RegexOptions.IgnoreCase); + + //parse the file + Source = FindTokenInstance.Replace(Source, Handler); + return Messages; + } + + /// ----------------------------------------------------------------------------- + /// + /// Process regular expression matches. + /// + /// Regular expression match for token which requires processing. + /// Properly formatted token. + /// + /// The handler is invoked by the Regex.Replace method once for each match that + /// it encounters. The returned value of the handler is substituted for the + /// original match. So the handler properly formats the replacement for the + /// token and returns it instead. If an unknown token is encountered, the token + /// is unmodified. This can happen if a token is used for a skin object which + /// has not yet been installed. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private string TokenMatchHandler(Match m) + { + string TOKEN_PROC = Util.GetLocalizedString("ProcessToken"); + string TOKEN_SKIN = Util.GetLocalizedString("SkinToken"); + string TOKEN_PANE = Util.GetLocalizedString("PaneToken"); + string TOKEN_FOUND = Util.GetLocalizedString("TokenFound"); + string TOKEN_FORMAT = Util.GetLocalizedString("TokenFormat"); + string TOKEN_NOTFOUND_INFILE = Util.GetLocalizedString("TokenNotFoundInFile"); + string CONTROL_FORMAT = Util.GetLocalizedString("ControlFormat"); + string TOKEN_NOTFOUND = Util.GetLocalizedString("TokenNotFound"); + + string Token = m.Groups["token"].Value.ToUpper(); + string ControlName = Token + m.Groups["instance"].Value; + + //if the token has an instance name, use it to look for the corresponding attributes + string AttributeNode = Token + (String.IsNullOrEmpty(m.Groups["instance"].Value) ? "" : ":" + m.Groups["instance"].Value); + + Messages += SkinController.FormatMessage(TOKEN_PROC, "[" + AttributeNode + "]", 2, false); + + //if the token is a recognized skin control + if (ControlList.ContainsKey(Token) || Token.IndexOf("CONTENTPANE") != -1) + { + string SkinControl = ""; + + if (ControlList.ContainsKey(Token)) + { + Messages += SkinController.FormatMessage(TOKEN_SKIN, (string)ControlList[Token], 2, false); + } + else + { + Messages += SkinController.FormatMessage(TOKEN_PANE, Token, 2, false); + } + + //f there is an attribute file + if (Attributes.DocumentElement != null) + { + //look for the the node of this instance of the token + XmlNode xmlSkinAttributeRoot = Attributes.DocumentElement.SelectSingleNode("descendant::Object[Token='[" + AttributeNode + "]']"); + //if the token is found + if (xmlSkinAttributeRoot != null) + { + Messages += SkinController.FormatMessage(TOKEN_FOUND, "[" + AttributeNode + "]", 2, false); + //process each token attribute + foreach (XmlNode xmlSkinAttribute in xmlSkinAttributeRoot.SelectNodes(".//Settings/Setting")) + { + if (!String.IsNullOrEmpty(xmlSkinAttribute.SelectSingleNode("Value").InnerText)) + { + //append the formatted attribute to the inner contents of the control statement + Messages += SkinController.FormatMessage(TOKEN_FORMAT, + xmlSkinAttribute.SelectSingleNode("Name").InnerText + "=\"" + xmlSkinAttribute.SelectSingleNode("Value").InnerText + "\"", + 2, + false); + SkinControl += " " + xmlSkinAttribute.SelectSingleNode("Name").InnerText + "=\"" + xmlSkinAttribute.SelectSingleNode("Value").InnerText.Replace("\"", """) + + "\""; + } + } + } + else + { + Messages += SkinController.FormatMessage(TOKEN_NOTFOUND_INFILE, "[" + AttributeNode + "]", 2, false); + } + } + if (ControlList.ContainsKey(Token)) + { + //create the skin object user control tag + SkinControl = "dnn:" + Token + " runat=\"server\" id=\"dnn" + ControlName + "\"" + SkinControl; + + //save control registration statement + string ControlRegistration = "<%@ Register TagPrefix=\"dnn\" TagName=\"" + Token + "\" Src=\"~/" + (string)ControlList[Token] + "\" %>" + Environment.NewLine; + if (RegisterList.Contains(ControlRegistration) == false) + { + RegisterList.Add(ControlRegistration); + } + + //return the control statement + Messages += SkinController.FormatMessage(CONTROL_FORMAT, "<" + SkinControl + " />", 2, false); + + SkinControl = "<" + SkinControl + " />"; + } + else + { + if (SkinControl.ToLower().IndexOf("id=") == -1) + { + SkinControl = " id=\"ContentPane\""; + } + SkinControl = "div runat=\"server\"" + SkinControl + ">"; + } + return SkinControl; + } + else + { + //return the unmodified token + //note that this is currently protecting array syntax in embedded javascript + //should be fixed in the regular expressions but is not, currently. + Messages += SkinController.FormatMessage(TOKEN_NOTFOUND, "[" + m.Groups["token"].Value + "]", 2, false); + return "[" + m.Groups["token"].Value + "]"; + } + } + } + + #endregion + + #region Nested type: ObjectParser + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinFileProcessor.ObjectParser + /// + /// ----------------------------------------------------------------------------- + /// + /// Parsing functionality for token replacement in new skin files. + /// + /// + /// This class encapsulates the data and methods necessary to appropriately + /// handle all the object parsing needs for new skin files (which is appropriate + /// only for HTML files). The parser accomodates some ill formatting of objects + /// (ignoring whitespace and casing) and allows for naming of object instances + /// if more than one instance of a particular control is desired on a skin. The + /// proper syntax for an instance is: "[OBJECT:INSTANCE]" where the instance can + /// be any alphanumeric string. Generated control ID's all take the + /// form of "OBJECTINSTANCE". + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private class ObjectParser + { + private readonly Hashtable m_ControlList = new Hashtable(); + private readonly string m_InitMessages = ""; + private string m_ParseMessages = ""; + private ArrayList m_RegisterList = new ArrayList(); + + /// ----------------------------------------------------------------------------- + /// + /// ControlParser class constructor. + /// + /// + /// The constructor processes accepts a hashtable of skin objects to process against. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public ObjectParser(Hashtable ControlList) + { + m_ControlList = (Hashtable)ControlList.Clone(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Registration directives generated as a result of the Parse method. + /// + /// ArrayList of formatted registration directives. + /// + /// In addition to the updated file contents, the Parse method also + /// creates this list of formatted registration directives which can + /// be processed later. They are not performed in place during the + /// Parse method in order to preserve the formatting of the input file + /// in case additional parsing might not anticipate the formatting of + /// those directives. Since they are properly formatted, it is better + /// to exclude them from being subject to parsing. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + internal ArrayList Registrations + { + get + { + return m_RegisterList; + } + } + + private MatchEvaluator Handler + { + get + { + return ObjectMatchHandler; + } + } + + private ArrayList RegisterList + { + get + { + return m_RegisterList; + } + set + { + m_RegisterList = value; + } + } + + private Hashtable ControlList + { + get + { + return m_ControlList; + } + } + + private string Messages + { + get + { + return m_ParseMessages; + } + set + { + m_ParseMessages = value; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Perform parsing on the specified source file. + /// + /// Pointer to Source string to be parsed. + /// + /// This procedure invokes a handler for each match of a formatted object. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string Parse(ref string Source) + { + Messages = m_InitMessages; + + //clear register list + RegisterList.Clear(); + + //define the regular expression to match objects + var FindObjectInstance = new Regex("\\.*?)
    ", RegexOptions.Singleline | RegexOptions.IgnoreCase); + + //parse the file + Source = FindObjectInstance.Replace(Source, Handler); + + return Messages; + } + + /// ----------------------------------------------------------------------------- + /// + /// Process regular expression matches. + /// + /// Regular expression match for object which requires processing. + /// Properly formatted token. + /// + /// The handler is invoked by the Regex.Replace method once for each match that + /// it encounters. The returned value of the handler is substituted for the + /// original match. So the handler properly formats the replacement for the + /// object and returns it instead. If an unknown object is encountered, the object + /// is unmodified. This can happen if an object is a client-side object or + /// has not yet been installed. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private string ObjectMatchHandler(Match m) + { + string OBJECT_PROC = Util.GetLocalizedString("ProcessObject"); + string OBJECT_SKIN = Util.GetLocalizedString("SkinObject"); + string OBJECT_PANE = Util.GetLocalizedString("PaneObject"); + string CONTROL_FORMAT = Util.GetLocalizedString("ControlFormat"); + string OBJECT_NOTFOUND = Util.GetLocalizedString("ObjectNotFound"); + + //"token" string matches will be in the form of (" id=".." codetype=".." codebase=".." etc...>") + //we need to assume properly formatted HTML - attributes will be enclosed in double quotes and there will no spaces between assignments ( ie. attribute="value" ) + + //extract the embedded object attributes (" id=".." codetype=".." codebase=".." etc...") + string EmbeddedObjectAttributes = m.Groups["token"].Value.Substring(0, m.Groups["token"].Value.IndexOf(">")); + + //split into array + string[] Attributes = EmbeddedObjectAttributes.Split(' '); + + //declare skin object elements + string AttributeNode = ""; + string Token = ""; + string ControlName = ""; + + //iterate and process valid attributes + string[] Attribute; + string AttributeName; + string AttributeValue; + foreach (string strAttribute in Attributes) + { + if (strAttribute != string.Empty) + { + Attribute = strAttribute.Split('='); + AttributeName = Attribute[0].Trim(); + AttributeValue = Attribute[1].Trim().Replace("\"", ""); + switch (AttributeName.ToLower()) + { + case "id": + ControlName = AttributeValue; + break; + case "codetype": + AttributeNode = AttributeValue; + break; + case "codebase": + Token = AttributeValue.ToUpper(); + break; + } + } + } + + //process skin object + if (AttributeNode.ToLower() == "dotnetnuke/server") + { + //we have a valid skin object specification + Messages += SkinController.FormatMessage(OBJECT_PROC, Token, 2, false); + + //if the embedded object is a recognized skin object + if (ControlList.ContainsKey(Token) || Token == "CONTENTPANE") + { + string SkinControl = ""; + + if (ControlList.ContainsKey(Token)) + { + Messages += SkinController.FormatMessage(OBJECT_SKIN, (string)ControlList[Token], 2, false); + } + else + { + Messages += SkinController.FormatMessage(OBJECT_PANE, Token, 2, false); + } + + //process embedded object params + string Parameters = m.Groups["token"].Value.Substring(m.Groups["token"].Value.IndexOf(">") + 1); + Parameters = Parameters.Replace("", ""); + + //convert multiple spaces and carriage returns into single spaces + Parameters = Regex.Replace(Parameters, "\\s+", " "); + + if (ControlList.ContainsKey(Token)) + { + //create the skin object user control tag + SkinControl = "dnn:" + Token + " runat=\"server\" "; + if (!String.IsNullOrEmpty(ControlName)) + { + SkinControl += "id=\"" + ControlName + "\" "; + } + SkinControl += Parameters; + + //save control registration statement + string ControlRegistration = "<%@ Register TagPrefix=\"dnn\" TagName=\"" + Token + "\" Src=\"~/" + (string)ControlList[Token] + "\" %>" + Environment.NewLine; + if (RegisterList.Contains(ControlRegistration) == false) + { + RegisterList.Add(ControlRegistration); + } + + //return the control statement + Messages += SkinController.FormatMessage(CONTROL_FORMAT, "<" + SkinControl + " />", 2, false); + SkinControl = "<" + SkinControl + "/>"; + } + else + { + SkinControl = "div runat=\"server\" "; + if (!String.IsNullOrEmpty(ControlName)) + { + SkinControl += "id=\"" + ControlName + "\" "; + } + else + { + SkinControl += "id=\"ContentPane\" "; + } + SkinControl += Parameters + ">"; + } + return SkinControl; + } + else + { + //return the unmodified embedded object + Messages += SkinController.FormatMessage(OBJECT_NOTFOUND, Token, 2, false); + return ""; + } + } + else + { + //return unmodified embedded object + return ""; + } + } + } + + #endregion + + #region Nested type: PathParser + + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinFileProcessor.PathParser + /// + /// ----------------------------------------------------------------------------- + /// + /// Parsing functionality for path replacement in new skin files. + /// + /// + /// This class encapsulates the data and methods necessary to appropriately + /// handle all the path replacement parsing needs for new skin files. Parsing + /// supported for CSS syntax and HTML syntax (which covers ASCX files also). + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private class PathParser + { + private readonly string SUBST = Util.GetLocalizedString("Substituting"); + private readonly string SUBST_DETAIL = Util.GetLocalizedString("Substituting.Detail"); + private readonly ArrayList m_CSSPatterns = new ArrayList(); + private readonly ArrayList m_HTMLPatterns = new ArrayList(); + private string m_Messages = ""; + private string m_SkinPath = ""; + + /// ----------------------------------------------------------------------------- + /// + /// List of regular expressions for processing HTML syntax. + /// + /// ArrayList of Regex objects formatted for the Parser method. + /// + /// Additional patterns can be added to this list (if necessary) if properly + /// formatted to return , and groups. For future + /// consideration, this list could be imported from a configuration file to + /// provide for greater flexibility. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public ArrayList HTMLList + { + get + { + //if the arraylist in uninitialized + if (m_HTMLPatterns.Count == 0) + { + //retrieve the patterns + string[] arrPattern = { + "(?]*?\\sprofile\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?]*?\\s(?:codebase|data|usemap)\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?]*?\\s(?:src|longdesc|usemap)\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?]*?\\s(?:src|usemap)\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?]*?\\s(?:src|longdesc)\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?<(?:td|th|table|body)[^>]*?\\sbackground\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?<(?:script|bgsound|embed|xml|frame)[^>]*?\\ssrc\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?<(?:base|link|a|area)[^>]*?\\shref\\s*=\\s*\")(?!https://|http://|\\\\|[~/]|javascript:|mailto:)(?[^\"]*)(?\"[^>]*>)", + "(?<(?:blockquote|ins|del|q)[^>]*?\\scite\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?<(?:param\\s+name\\s*=\\s*\"(?:movie|src|base)\")[^>]*?\\svalue\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)", + "(?]*?\\s(?:src)\\s*=\\s*\")(?!https://|http://|\\\\|[~/])(?[^\"]*)(?\"[^>]*>)" + }; + + //for each pattern, create a regex object + for (int i = 0; i <= arrPattern.GetLength(0) - 1; i++) + { + var re = new Regex(arrPattern[i], RegexOptions.Multiline | RegexOptions.IgnoreCase); + //add the Regex object to the pattern array list + m_HTMLPatterns.Add(re); + } + + //optimize the arraylist size since it will not change + m_HTMLPatterns.TrimToSize(); + } + return m_HTMLPatterns; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// List of regular expressions for processing CSS syntax. + /// + /// ArrayList of Regex objects formatted for the Parser method. + /// + /// Additional patterns can be added to this list (if necessary) if properly + /// formatted to return , and groups. For future + /// consideration, this list could be imported from a configuration file to + /// provide for greater flexibility. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public ArrayList CSSList + { + get + { + //if the arraylist in uninitialized + if (m_CSSPatterns.Count == 0) + { + //retrieve the patterns + string[] arrPattern = { "(?\\surl\\u0028)(?[^\\u0029]*)(?\\u0029.*;)" }; + + //for each pattern, create a regex object + for (int i = 0; i <= arrPattern.GetLength(0) - 1; i++) + { + var re = new Regex(arrPattern[i], RegexOptions.Multiline | RegexOptions.IgnoreCase); + + //add the Regex object to the pattern array list + m_CSSPatterns.Add(re); + } + + //optimize the arraylist size since it will not change + m_CSSPatterns.TrimToSize(); + } + return m_CSSPatterns; + } + } + + private MatchEvaluator Handler + { + get + { + return MatchHandler; + } + } + + private string SkinPath + { + get + { + return m_SkinPath; + } + set + { + m_SkinPath = value; + } + } + + private SkinParser ParseOption { get; set; } + + /// ----------------------------------------------------------------------------- + /// + /// Perform parsing on the specified source file. + /// + /// Pointer to Source string to be parsed. + /// ArrayList of properly formatted regular expression objects. + /// Path to use in replacement operation. + /// Parse Opition. + /// + /// This procedure iterates through the list of regular expression objects + /// and invokes a handler for each match which uses the specified path. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string Parse(ref string Source, ArrayList RegexList, string SkinPath, SkinParser ParseOption) + { + m_Messages = ""; + + //set path propery which is file specific + this.SkinPath = SkinPath; + //set parse option + this.ParseOption = ParseOption; + + //process each regular expression + for (int i = 0; i <= RegexList.Count - 1; i++) + { + Source = ((Regex)RegexList[i]).Replace(Source, Handler); + } + return m_Messages; + } + + /// ----------------------------------------------------------------------------- + /// + /// Process regular expression matches. + /// + /// Regular expression match for path information which requires processing. + /// Properly formatted path information. + /// + /// The handler is invoked by the Regex.Replace method once for each match that + /// it encounters. The returned value of the handler is substituted for the + /// original match. So the handler properly formats the path information and + /// returns it in favor of the improperly formatted match. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private string MatchHandler(Match m) + { + string strOldTag = m.Groups["tag"].Value + m.Groups["content"].Value + m.Groups["endtag"].Value; + string strNewTag = strOldTag; + + //we do not want to process object tags to DotNetNuke widgets + if (!m.Groups[0].Value.ToLower().Contains("codetype=\"dotnetnuke/client\"")) + { + switch (ParseOption) + { + case SkinParser.Localized: + //if the tag does not contain the localized path + if (strNewTag.IndexOf(SkinPath) == -1) + { + //insert the localized path + strNewTag = m.Groups["tag"].Value + SkinPath + m.Groups["content"].Value + m.Groups["endtag"].Value; + } + break; + case SkinParser.Portable: + //if the tag does not contain a reference to the skinpath + if (strNewTag.ToLower().IndexOf("<%= skinpath %>") == -1) + { + //insert the skinpath + strNewTag = m.Groups["tag"].Value + "<%= SkinPath %>" + m.Groups["content"].Value + m.Groups["endtag"].Value; + } + + //if the tag contains the localized path + if (strNewTag.IndexOf(SkinPath) != -1) + { + //remove the localized path + strNewTag = strNewTag.Replace(SkinPath, ""); + } + break; + } + } + m_Messages += SkinController.FormatMessage(SUBST, string.Format(SUBST_DETAIL, HttpUtility.HtmlEncode(strOldTag), HttpUtility.HtmlEncode(strNewTag)), 2, false); + return strNewTag; + } + } + + #endregion + + #region Nested type: SkinFile + + /// ----------------------------------------------------------------------------- + /// + /// Utility class for processing of skin files. + /// + /// + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + private class SkinFile + { + private readonly string CONTROL_DIR = Util.GetLocalizedString("ControlDirective"); + private readonly string CONTROL_REG = Util.GetLocalizedString("ControlRegister"); + private readonly string FILE_FORMAT_ERROR = Util.GetLocalizedString("FileFormat.Error"); + private readonly string FILE_LOAD = Util.GetLocalizedString("SkinFileLoad"); + private readonly string FILE_LOAD_ERROR = Util.GetLocalizedString("SkinFileLoad.Error"); + private readonly string FILE_WRITE = Util.GetLocalizedString("FileWrite"); + private readonly XmlDocument m_FileAttributes; + private readonly string m_FileExtension; + private readonly string m_FileName; + private readonly string m_SkinRoot; + private readonly string m_SkinRootPath; + private readonly string m_WriteFileName; + private string FILE_FORMAT_DETAIL = Util.GetLocalizedString("FileFormat.Detail"); + private string m_Messages = ""; + + /// ----------------------------------------------------------------------------- + /// + /// SkinFile class constructor. + /// + /// + /// + /// + /// The constructor primes the utility class with basic file information. + /// It also checks for the existentce of a skinfile level attribute file + /// and read it in, if found. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public SkinFile(string SkinContents, XmlDocument SkinAttributes) + { + m_FileAttributes = SkinAttributes; + Contents = SkinContents; + } + + /// ----------------------------------------------------------------------------- + /// + /// SkinFile class constructor. + /// + /// + /// + /// + /// + /// The constructor primes the utility class with basic file information. + /// It also checks for the existentce of a skinfile level attribute file + /// and read it in, if found. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public SkinFile(string SkinRoot, string FileName, XmlDocument SkinAttributes) + { + //capture file information + m_FileName = FileName; + m_FileExtension = Path.GetExtension(FileName); + m_SkinRoot = SkinRoot; + m_FileAttributes = SkinAttributes; + + //determine and store path to portals skin root folder + string strTemp = FileName.Replace(Path.GetFileName(FileName), ""); + strTemp = strTemp.Replace("\\", "/"); + m_SkinRootPath = Globals.ApplicationPath + strTemp.Substring(strTemp.ToUpper().IndexOf("/PORTALS")); + + //read file contents + Contents = Read(FileName); + + //setup some attributes based on file extension + switch (FileExtension) + { + case ".htm": + case ".html": + //set output file name to .ASCX + m_WriteFileName = FileName.Replace(Path.GetExtension(FileName), ".ascx"); + + //capture warning if file does not contain a id="ContentPane" or [CONTENTPANE] + var PaneCheck1 = new Regex("\\s*id\\s*=\\s*\"" + Globals.glbDefaultPane + "\"", RegexOptions.IgnoreCase); + var PaneCheck2 = new Regex("\\s*[" + Globals.glbDefaultPane + "]", RegexOptions.IgnoreCase); + if (PaneCheck1.IsMatch(Contents) == false && PaneCheck2.IsMatch(Contents) == false) + { + m_Messages += SkinController.FormatMessage(FILE_FORMAT_ERROR, string.Format(FILE_FORMAT_ERROR, FileName), 2, true); + } + + //Check for existence of and load skin file level attribute information + if (File.Exists(FileName.Replace(FileExtension, ".xml"))) + { + try + { + m_FileAttributes.Load(FileName.Replace(FileExtension, ".xml")); + m_Messages += SkinController.FormatMessage(FILE_LOAD, FileName, 2, false); + } + catch (Exception exc) //could not load XML file + { + Logger.Error(exc); + m_FileAttributes = SkinAttributes; + m_Messages += SkinController.FormatMessage(FILE_LOAD_ERROR, FileName, 2, true); + } + } + break; + default: + //output file name is same as input file name + m_WriteFileName = FileName; + break; + } + } + + public string SkinRoot + { + get + { + return m_SkinRoot; + } + } + + public XmlDocument Attributes + { + get + { + return m_FileAttributes; + } + } + + public string Messages + { + get + { + return m_Messages; + } + } + + public string FileName + { + get + { + return m_FileName; + } + } + + public string WriteFileName + { + get + { + return m_WriteFileName; + } + } + + public string FileExtension + { + get + { + return m_FileExtension; + } + } + + public string SkinRootPath + { + get + { + return m_SkinRootPath; + } + } + + public string Contents { get; set; } + + private string Read(string FileName) + { + var objStreamReader = new StreamReader(FileName); + string strFileContents = objStreamReader.ReadToEnd(); + objStreamReader.Close(); + return strFileContents; + } + + public void Write() + { + //delete the file before attempting to write + if (File.Exists(WriteFileName)) + { + File.Delete(WriteFileName); + } + m_Messages += SkinController.FormatMessage(FILE_WRITE, Path.GetFileName(WriteFileName), 2, false); + var objStreamWriter = new StreamWriter(WriteFileName); + objStreamWriter.WriteLine(Contents); + objStreamWriter.Flush(); + objStreamWriter.Close(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Prepend ascx control directives to file contents. + /// + /// ArrayList of registration directives. + /// + /// This procedure formats the @Control directive and prepends it and all + /// registration directives to the file contents. + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + public string PrependASCXDirectives(ArrayList Registrations) + { + string Messages = ""; + string Prefix = ""; + + //if the skin source is an HTML document, extract the content within the tags + string strPattern = "<\\s*body[^>]*>(?.*)<\\s*/\\s*body\\s*>"; + + //format and save @Control directive + Match objMatch; + objMatch = Regex.Match(Contents, strPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline); + if (!String.IsNullOrEmpty(objMatch.Groups[1].Value)) + { + Contents = objMatch.Groups[1].Value; + } + if (SkinRoot == SkinController.RootSkin) + { + Prefix += "<%@ Control language=\"vb\" AutoEventWireup=\"false\" Explicit=\"True\" Inherits=\"DotNetNuke.UI.Skins.Skin\" %>" + Environment.NewLine; + } + else if (SkinRoot == SkinController.RootContainer) + { + Prefix += "<%@ Control language=\"vb\" AutoEventWireup=\"false\" Explicit=\"True\" Inherits=\"DotNetNuke.UI.Containers.Container\" %>" + Environment.NewLine; + } + Messages += SkinController.FormatMessage(CONTROL_DIR, HttpUtility.HtmlEncode(Prefix), 2, false); + + //add preformatted Control Registrations + foreach (string Item in Registrations) + { + Messages += SkinController.FormatMessage(CONTROL_REG, HttpUtility.HtmlEncode(Item), 2, false); + Prefix += Item; + } + + //update file contents to include ascx header information + Contents = Prefix + Contents; + return Messages; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinInfo.cs b/DNN Platform/Library/UI/Skins/SkinInfo.cs new file mode 100644 index 00000000000..dd514de2a4e --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinInfo.cs @@ -0,0 +1,130 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinInfo + /// + /// ----------------------------------------------------------------------------- + /// + /// Handles the Business Object for Skins + /// + /// + /// + /// + /// [willhsc] 3/3/2004 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class SkinInfo + { + private int _PortalId; + private int _SkinId; + private string _SkinRoot; + private string _SkinSrc; + private SkinType _SkinType; + + public int SkinId + { + get + { + return _SkinId; + } + set + { + _SkinId = value; + } + } + + public int PortalId + { + get + { + return _PortalId; + } + set + { + _PortalId = value; + } + } + + public string SkinRoot + { + get + { + return _SkinRoot; + } + set + { + _SkinRoot = value; + } + } + + public SkinType SkinType + { + get + { + return _SkinType; + } + set + { + _SkinType = value; + } + } + + public string SkinSrc + { + get + { + return _SkinSrc; + } + set + { + _SkinSrc = value; + } + } + + [Obsolete("Replaced in DNN 5.0 by SkinController.RootSkin")] + public static string RootSkin + { + get + { + return "Skins"; + } + } + + [Obsolete("Replaced in DNN 5.0 by SkinController.RootContainer")] + public static string RootContainer + { + get + { + return "Containers"; + } + } + } +} diff --git a/DNN Platform/Library/UI/Skins/SkinObjectBase.cs b/DNN Platform/Library/UI/Skins/SkinObjectBase.cs new file mode 100644 index 00000000000..6e57da8b2a9 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinObjectBase.cs @@ -0,0 +1,80 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System.ComponentModel; +using System.Web.UI; + +using DotNetNuke.Entities.Portals; +using DotNetNuke.Security.Permissions; +using DotNetNuke.UI.Modules; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// + /// The SkinObject class defines a custom base class inherited by all + /// skin and container objects within the Portal. + /// + /// ----------------------------------------------------------------------------- + public class SkinObjectBase : UserControl, ISkinControl + { + /// ----------------------------------------------------------------------------- + /// + /// Gets the portal Settings for this Skin Control + /// + /// ----------------------------------------------------------------------------- + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PortalSettings PortalSettings + { + get + { + return PortalController.GetCurrentPortalSettings(); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Gets whether we are in Admin Mode + /// + /// ----------------------------------------------------------------------------- + public bool AdminMode + { + get + { + return TabPermissionController.CanAdminPage(); + } + } + + #region ISkinControl Members + + /// ----------------------------------------------------------------------------- + /// + /// Gets and sets the associated ModuleControl for this SkinControl + /// + /// ----------------------------------------------------------------------------- + public IModuleControl ModuleControl { get; set; } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/SkinPackageInfo.cs b/DNN Platform/Library/UI/Skins/SkinPackageInfo.cs new file mode 100644 index 00000000000..4080d15695c --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinPackageInfo.cs @@ -0,0 +1,179 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Data; +using System.Xml.Serialization; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities; +using DotNetNuke.Entities.Modules; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// Project : DotNetNuke + /// Class : SkinPackageInfo + /// + /// ----------------------------------------------------------------------------- + /// + /// Handles the Business Object for Skins + /// + /// + /// + /// + /// [cnurse] 02/04/2008 Created + /// + /// ----------------------------------------------------------------------------- + [Serializable] + public class SkinPackageInfo : BaseEntityInfo, IHydratable + { + #region "Private Members" + + private int _PackageID = Null.NullInteger; + private int _PortalID = Null.NullInteger; + private string _SkinName; + private int _SkinPackageID = Null.NullInteger; + private string _SkinType; + private Dictionary _Skins = new Dictionary(); + + #endregion + + #region "Public Properties" + + public int PackageID + { + get + { + return _PackageID; + } + set + { + _PackageID = value; + } + } + + public int SkinPackageID + { + get + { + return _SkinPackageID; + } + set + { + _SkinPackageID = value; + } + } + + public int PortalID + { + get + { + return _PortalID; + } + set + { + _PortalID = value; + } + } + + public string SkinName + { + get + { + return _SkinName; + } + set + { + _SkinName = value; + } + } + + [XmlIgnore] + public Dictionary Skins + { + get + { + return _Skins; + } + set + { + _Skins = value; + } + } + + public string SkinType + { + get + { + return _SkinType; + } + set + { + _SkinType = value; + } + } + + #endregion + + #region IHydratable Members + + public void Fill(IDataReader dr) + { + SkinPackageID = Null.SetNullInteger(dr["SkinPackageID"]); + PackageID = Null.SetNullInteger(dr["PackageID"]); + SkinName = Null.SetNullString(dr["SkinName"]); + SkinType = Null.SetNullString(dr["SkinType"]); + //Call the base classes fill method to populate base class proeprties + base.FillInternal(dr); + + if (dr.NextResult()) + { + while (dr.Read()) + { + int skinID = Null.SetNullInteger(dr["SkinID"]); + if (skinID > Null.NullInteger) + { + _Skins[skinID] = Null.SetNullString(dr["SkinSrc"]); + } + } + } + } + + public int KeyID + { + get + { + return SkinPackageID; + } + set + { + SkinPackageID = value; + } + } + + #endregion + } +} diff --git a/DNN Platform/Library/UI/Skins/SkinScope.cs b/DNN Platform/Library/UI/Skins/SkinScope.cs new file mode 100644 index 00000000000..29e90f83a26 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinScope.cs @@ -0,0 +1,29 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Skins +{ + public enum SkinScope + { + All = 0, + Host = 1, + Site = 2 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinThumbNailControl.cs b/DNN Platform/Library/UI/Skins/SkinThumbNailControl.cs new file mode 100644 index 00000000000..2921d65b01c --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinThumbNailControl.cs @@ -0,0 +1,470 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Localization; + +using Image = System.Drawing.Image; + +#endregion + +namespace DotNetNuke.UI.Skins +{ + /// ----------------------------------------------------------------------------- + /// + /// SkinThumbNailControl is a user control that provides that displays the skins + /// as a Radio ButtonList with Thumbnail Images where available + /// + /// + /// + /// + /// [cnurse] 10/12/2004 Created + /// + /// ----------------------------------------------------------------------------- + public abstract class SkinThumbNailControl : UserControlBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (SkinThumbNailControl)); + #region "Private Members" + + protected HtmlGenericControl ControlContainer; + protected RadioButtonList OptSkin; + + #endregion + + #region "Properties" + + public string Border + { + get + { + return Convert.ToString(ViewState["SkinControlBorder"]); + } + set + { + ViewState["SkinControlBorder"] = value; + if (!String.IsNullOrEmpty(value)) + { + ControlContainer.Style.Add("border-top", value); + ControlContainer.Style.Add("border-bottom", value); + ControlContainer.Style.Add("border-left", value); + ControlContainer.Style.Add("border-right", value); + } + } + } + + public int Columns + { + get + { + return Convert.ToInt32(ViewState["SkinControlColumns"]); + } + set + { + ViewState["SkinControlColumns"] = value; + if (value > 0) + { + OptSkin.RepeatColumns = value; + } + } + } + + public string Height + { + get + { + return Convert.ToString(ViewState["SkinControlHeight"]); + } + set + { + ViewState["SkinControlHeight"] = value; + if (!String.IsNullOrEmpty(value)) + { + ControlContainer.Style.Add("height", value); + } + } + } + + public string SkinRoot + { + get + { + return Convert.ToString(ViewState["SkinRoot"]); + } + set + { + ViewState["SkinRoot"] = value; + } + } + + public string SkinSrc + { + get + { + return OptSkin.SelectedItem != null ? OptSkin.SelectedItem.Value : ""; + } + set + { + //select current skin + int intIndex; + for (intIndex = 0; intIndex <= OptSkin.Items.Count - 1; intIndex++) + { + if (OptSkin.Items[intIndex].Value == value) + { + OptSkin.Items[intIndex].Selected = true; + break; + } + } + } + } + + public string Width + { + get + { + return Convert.ToString(ViewState["SkinControlWidth"]); + } + set + { + ViewState["SkinControlWidth"] = value; + if (!String.IsNullOrEmpty(value)) + { + ControlContainer.Style.Add("width", value); + } + } + } + + #endregion + + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// AddDefaultSkin adds the not-specified skin to the radio button list + /// + /// + /// + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void AddDefaultSkin() + { + var strDefault = Localization.GetString("Not_Specified") + "
    "; + strDefault += ""; + OptSkin.Items.Insert(0, new ListItem(strDefault, "")); + } + + /// ----------------------------------------------------------------------------- + /// + /// AddSkin adds the skin to the radio button list + /// + /// + /// + /// Root Path. + /// The Skin Folder + /// The Skin File + /// + /// [cnurse] 9/8/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void AddSkin(string root, string strFolder, string strFile) + { + var strImage = ""; + if (File.Exists(strFile.Replace(".ascx", ".jpg"))) + { + strImage += ""; + } + else + { + strImage += ""; + } + OptSkin.Items.Add(new ListItem(FormatSkinName(strFolder, Path.GetFileNameWithoutExtension(strFile)) + "
    " + strImage, root + "/" + strFolder + "/" + Path.GetFileName(strFile))); + } + + /// ----------------------------------------------------------------------------- + /// + /// format skin name + /// + /// + /// + /// The Folder Name + /// The File Name without extension + /// + /// + /// ----------------------------------------------------------------------------- + private static string FormatSkinName(string strSkinFolder, string strSkinFile) + { + if (strSkinFolder.ToLower() == "_default") //host folder + { + return strSkinFile; + } + + //portal folder + switch (strSkinFile.ToLower()) + { + case "skin": + case "container": + case "default": + return strSkinFolder; + default: + return string.Format("{0} - {1}", strSkinFolder, strSkinFile); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// CreateThumbnail creates a thumbnail of the Preview Image + /// + /// + /// + /// The Image File Name + /// + /// [cnurse] 9/8/2004 Created + /// + /// ----------------------------------------------------------------------------- + private static string CreateThumbnail(string strImage) + { + var blnCreate = true; + + var strThumbnail = strImage.Replace(Path.GetFileName(strImage), "thumbnail_" + Path.GetFileName(strImage)); + + //check if image has changed + if (File.Exists(strThumbnail)) + { + //var d1 = File.GetLastWriteTime(strThumbnail); + //var d2 = File.GetLastWriteTime(strImage); + if (File.GetLastWriteTime(strThumbnail) == File.GetLastWriteTime(strImage)) + { + blnCreate = false; + } + } + if (blnCreate) + { + const int intSize = 140; //size of the thumbnail + Image objImage; + try + { + objImage = Image.FromFile(strImage); + + //scale the image to prevent distortion + int intWidth; + int intHeight; + double dblScale; + if (objImage.Height > objImage.Width) + { + //The height was larger, so scale the width + dblScale = (double)intSize / objImage.Height; + intHeight = intSize; + intWidth = Convert.ToInt32(objImage.Width*dblScale); + } + else + { + //The width was larger, so scale the height + dblScale = (double)intSize / objImage.Width; + intWidth = intSize; + intHeight = Convert.ToInt32(objImage.Height*dblScale); + } + + //create the thumbnail image + var objThumbnail = objImage.GetThumbnailImage(intWidth, intHeight, null, IntPtr.Zero); + + //delete the old file ( if it exists ) + if (File.Exists(strThumbnail)) + { + File.Delete(strThumbnail); + } + + //save the thumbnail image + objThumbnail.Save(strThumbnail, objImage.RawFormat); + + //set the file attributes + File.SetAttributes(strThumbnail, FileAttributes.Normal); + File.SetLastWriteTime(strThumbnail, File.GetLastWriteTime(strImage)); + + //tidy up + objImage.Dispose(); + objThumbnail.Dispose(); + } + catch (Exception ex) + { + Logger.Error(ex); + } + } + strThumbnail = Globals.ApplicationPath + "\\" + strThumbnail.Substring(strThumbnail.ToLower().IndexOf("portals\\")); + return strThumbnail; + } + + #endregion + + #region "Public Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Clear clears the radio button list + /// + /// + /// + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void Clear() + { + OptSkin.Items.Clear(); + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadAllSkins loads all the available skins (Host and Site) to the radio button list + /// + /// + /// + /// Optionally include the "Not Specified" option + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void LoadAllSkins(bool includeNotSpecified) + { + //default value + if (includeNotSpecified) + { + AddDefaultSkin(); + } + + //load host skins (includeNotSpecified = false as we have already added it) + LoadHostSkins(false); + + //load portal skins (includeNotSpecified = false as we have already added it) + LoadPortalSkins(false); + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadHostSkins loads all the available Host skins to the radio button list + /// + /// + /// + /// Optionally include the "Not Specified" option + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void LoadHostSkins(bool includeNotSpecified) + { + + //default value + if (includeNotSpecified) + { + AddDefaultSkin(); + } + + //load host skins + var strRoot = Globals.HostMapPath + SkinRoot; + if (Directory.Exists(strRoot)) + { + var arrFolders = Directory.GetDirectories(strRoot); + foreach (var strFolder in arrFolders) + { + if (!strFolder.EndsWith(Globals.glbHostSkinFolder)) + { + LoadSkins(strFolder, "[G]", false); + } + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadHostSkins loads all the available Site/Portal skins to the radio button list + /// + /// + /// + /// Optionally include the "Not Specified" option + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void LoadPortalSkins(bool includeNotSpecified) + { + //default value + if (includeNotSpecified) + { + AddDefaultSkin(); + } + + //load portal skins + var strRoot = PortalSettings.HomeDirectoryMapPath + SkinRoot; + if (Directory.Exists(strRoot)) + { + var arrFolders = Directory.GetDirectories(strRoot); + foreach (var strFolder in arrFolders) + { + LoadSkins(strFolder, "[L]", false); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadSkins loads all the available skins in a specific folder to the radio button list + /// + /// + /// + /// The folder to search for skins + /// A string that identifies whether the skin is Host "[G]" or Site "[L]" + /// Optionally include the "Not Specified" option + /// + /// [cnurse] 12/15/2004 Created + /// + /// ----------------------------------------------------------------------------- + public void LoadSkins(string strFolder, string skinType, bool includeNotSpecified) + { + //default value + if (includeNotSpecified) + { + AddDefaultSkin(); + } + if (Directory.Exists(strFolder)) + { + var arrFiles = Directory.GetFiles(strFolder, "*.ascx"); + strFolder = strFolder.Substring(strFolder.LastIndexOf("\\") + 1); + + foreach (var strFile in arrFiles) + { + AddSkin(skinType + SkinRoot, strFolder, strFile); + } + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/Skins/SkinType.cs b/DNN Platform/Library/UI/Skins/SkinType.cs new file mode 100644 index 00000000000..14fbf1229d7 --- /dev/null +++ b/DNN Platform/Library/UI/Skins/SkinType.cs @@ -0,0 +1,28 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +namespace DotNetNuke.UI.Skins +{ + public enum SkinType + { + Portal = 0, + Admin = 1 + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/UIUtilities.cs b/DNN Platform/Library/UI/UIUtilities.cs new file mode 100644 index 00000000000..a6240565e85 --- /dev/null +++ b/DNN Platform/Library/UI/UIUtilities.cs @@ -0,0 +1,177 @@ +#region Copyright +// +// DotNetNuke® - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +using System; +using System.IO; +using System.Web; +using System.Web.UI; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Modules; +using DotNetNuke.UI.Skins; + +namespace DotNetNuke.UI +{ + public class UIUtilities + { + internal static string GetControlKey() + { + HttpRequest request = HttpContext.Current.Request; + + string key = ""; + if (request.QueryString["ctl"] != null) + { + key = request.QueryString["ctl"]; + } + return key; + } + + internal static int GetModuleId(string key) + { + HttpRequest request = HttpContext.Current.Request; + + int moduleId = -1; + if (request.QueryString["mid"] != null) + { + Int32.TryParse(request.QueryString["mid"], out moduleId); + } + if (request.QueryString["moduleid"] != null && (key.ToLower() == "module" || key.ToLower() == "help")) + { + Int32.TryParse(request.QueryString["moduleid"], out moduleId); + } + + return moduleId; + } + + internal static string GetRenderMode() + { + HttpRequest request = HttpContext.Current.Request; + + var renderMode = ""; + if (request.QueryString["render"] != null) + { + renderMode = request.QueryString["render"]; + } + return renderMode; + } + + internal static ModuleInfo GetSlaveModule(int moduleId, string key, int tabId) + { + HttpRequest request = HttpContext.Current.Request; + + var moduleController = new ModuleController(); + ModuleInfo slaveModule = null; + if (moduleId != -1) + { + ModuleInfo module = moduleController.GetModule(moduleId, tabId, false); + if (module != null) + { + slaveModule = module.Clone(); + } + } + + if (slaveModule == null) + { + slaveModule = (new ModuleInfo {ModuleID = moduleId, ModuleDefID = -1, TabID = tabId, InheritViewPermissions = true}); + } + + if (request.QueryString["moduleid"] != null && (key.ToLower() == "module" || key.ToLower() == "help")) + { + slaveModule.ModuleDefID = -1; + } + + if (request.QueryString["dnnprintmode"] != "true") + { + slaveModule.ModuleTitle = ""; + } + + slaveModule.Header = ""; + slaveModule.Footer = ""; + slaveModule.StartDate = DateTime.MinValue; + slaveModule.EndDate = DateTime.MaxValue; + slaveModule.Visibility = VisibilityState.None; + slaveModule.Color = ""; + slaveModule.Border = ""; + slaveModule.DisplayTitle = true; + slaveModule.DisplayPrint = false; + slaveModule.DisplaySyndicate = false; + + return slaveModule; + } + + public static ModuleInfo GetSlaveModule(int tabId) + { + var key = GetControlKey(); + var moduleId = GetModuleId(key); + + ModuleInfo slaveModule = GetSlaveModule(moduleId, key, tabId); + if (slaveModule != null) + { + var moduleControl = ModuleControlController.GetModuleControlByControlKey(key, slaveModule.ModuleDefID) ?? + ModuleControlController.GetModuleControlByControlKey(key, Null.NullInteger); + if (moduleControl != null) + { + slaveModule.ModuleControlId = moduleControl.ModuleControlID; + } + } + + return slaveModule; + } + + public static bool IsLegacyUI(int moduleId, string key, int portalId) + { + var request = HttpContext.Current.Request; + var isLegacyUi = true; + var settings = PortalController.GetCurrentPortalSettings(); + if (settings != null) + { + isLegacyUi = !(settings.EnablePopUps && !request.Browser.Crawler && request.Browser.EcmaScriptVersion >= new Version(1, 0)); + + if (!isLegacyUi && !String.IsNullOrEmpty(key)) + { + var slaveModule = GetSlaveModule(moduleId, key, settings.ActiveTab.TabID); + if (slaveModule != null) + { + var moduleControl = ModuleControlController.GetModuleControlByControlKey(key, slaveModule.ModuleDefID) ?? + ModuleControlController.GetModuleControlByControlKey(key, Null.NullInteger); + if (moduleControl != null) + { + isLegacyUi = !moduleControl.SupportsPopUps; + } + } + } + } + + return isLegacyUi; + } + + public static bool IsLegacyUI(int portalId) + { + var key = GetControlKey(); + var moduleId = GetModuleId(key); + + return IsLegacyUI(moduleId, key, portalId); + } + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/UserControls/Address.cs b/DNN Platform/Library/UI/UserControls/Address.cs new file mode 100644 index 00000000000..b4170b49126 --- /dev/null +++ b/DNN Platform/Library/UI/UserControls/Address.cs @@ -0,0 +1,912 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Linq; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; +using DotNetNuke.Common.Lists; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Framework; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.WebControls; + +#endregion + +namespace DotNetNuke.UI.UserControls +{ + + /// + /// The Address UserControl is used to manage User Addresses + /// + /// + /// + /// + /// [cnurse] 10/08/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + public abstract class Address : UserControlBase + { + + #region Private Members + + private const string MyFileName = "Address.ascx"; + private string _cell; + private string _city; + private string _controlColumnWidth = ""; + private string _country; + private string _countryData = "Text"; + private string _fax; + private string _labelColumnWidth = ""; + private int _moduleId; + private string _postal; + private string _region; + private string _regionData = "Text"; + private bool _showCell = true; + private bool _showCity = true; + private bool _showCountry = true; + private bool _showFax = true; + private bool _showPostal = true; + private bool _showRegion = true; + private bool _showStreet = true; + private bool _showTelephone = true; + private bool _showUnit = true; + private string _street; + private string _telephone; + private string _unit; + protected CountryListBox cboCountry; + protected DropDownList cboRegion; + protected CheckBox chkCell; + protected CheckBox chkCity; + protected CheckBox chkCountry; + protected CheckBox chkFax; + protected CheckBox chkPostal; + protected CheckBox chkRegion; + protected CheckBox chkStreet; + protected CheckBox chkTelephone; + protected LabelControl plCell; + protected LabelControl plCity; + protected LabelControl plCountry; + protected LabelControl plFax; + protected LabelControl plPostal; + protected LabelControl plRegion; + protected LabelControl plStreet; + protected LabelControl plTelephone; + protected LabelControl plUnit; + protected HtmlGenericControl divCell; + protected HtmlGenericControl divCity; + protected HtmlGenericControl divCountry; + protected HtmlGenericControl divFax; + protected HtmlGenericControl divPostal; + protected HtmlGenericControl divRegion; + protected HtmlGenericControl divStreet; + protected HtmlGenericControl divTelephone; + protected HtmlGenericControl divUnit; + protected TextBox txtCell; + protected TextBox txtCity; + protected TextBox txtFax; + protected TextBox txtPostal; + protected TextBox txtRegion; + protected TextBox txtStreet; + protected TextBox txtTelephone; + protected TextBox txtUnit; + protected RequiredFieldValidator valCell; + protected RequiredFieldValidator valCity; + protected RequiredFieldValidator valCountry; + protected RequiredFieldValidator valFax; + protected RequiredFieldValidator valPostal; + protected RequiredFieldValidator valRegion1; + protected RequiredFieldValidator valRegion2; + protected RequiredFieldValidator valStreet; + protected RequiredFieldValidator valTelephone; + + #endregion + + #region Constructors + + protected Address() + { + StartTabIndex = 1; + } + + #endregion + + #region Properties + + public int ModuleId + { + get + { + return Convert.ToInt32(ViewState["ModuleId"]); + } + set + { + _moduleId = value; + } + } + + public string LabelColumnWidth + { + get + { + return Convert.ToString(ViewState["LabelColumnWidth"]); + } + set + { + _labelColumnWidth = value; + } + } + + public string ControlColumnWidth + { + get + { + return Convert.ToString(ViewState["ControlColumnWidth"]); + } + set + { + _controlColumnWidth = value; + } + } + + public int StartTabIndex { private get; set; } + + public string Street + { + get + { + return txtStreet.Text; + } + set + { + _street = value; + } + } + + public string Unit + { + get + { + return txtUnit.Text; + } + set + { + _unit = value; + } + } + + public string City + { + get + { + return txtCity.Text; + } + set + { + _city = value; + } + } + + public string Country + { + get + { + var retValue = ""; + if (cboCountry.SelectedItem != null) + { + switch (_countryData.ToLower()) + { + case "text": + retValue = cboCountry.SelectedIndex == 0 ? "" : cboCountry.SelectedItem.Text; + break; + case "value": + retValue = cboCountry.SelectedItem.Value; + break; + } + } + return retValue; + } + set + { + _country = value; + } + } + + public string Region + { + get + { + var retValue = ""; + if (cboRegion.Visible) + { + if (cboRegion.SelectedItem != null) + { + switch (_regionData.ToLower()) + { + case "text": + if (cboRegion.SelectedIndex > 0) + { + retValue = cboRegion.SelectedItem.Text; + } + break; + case "value": + retValue = cboRegion.SelectedItem.Value; + break; + } + } + } + else + { + retValue = txtRegion.Text; + } + return retValue; + } + set + { + _region = value; + } + } + + public string Postal + { + get + { + return txtPostal.Text; + } + set + { + _postal = value; + } + } + + public string Telephone + { + get + { + return txtTelephone.Text; + } + set + { + _telephone = value; + } + } + + public string Cell + { + get + { + return txtCell.Text; + } + set + { + _cell = value; + } + } + + public string Fax + { + get + { + return txtFax.Text; + } + set + { + _fax = value; + } + } + + public bool ShowStreet + { + set + { + _showStreet = value; + } + } + + public bool ShowUnit + { + set + { + _showUnit = value; + } + } + + public bool ShowCity + { + set + { + _showCity = value; + } + } + + public bool ShowCountry + { + set + { + _showCountry = value; + } + } + + public bool ShowRegion + { + set + { + _showRegion = value; + } + } + + public bool ShowPostal + { + set + { + _showPostal = value; + } + } + + public bool ShowTelephone + { + set + { + _showTelephone = value; + } + } + + public bool ShowCell + { + set + { + _showCell = value; + } + } + + public bool ShowFax + { + set + { + _showFax = value; + } + } + + public string CountryData + { + set + { + _countryData = value; + } + } + + public string RegionData + { + set + { + _regionData = value; + } + } + + public string LocalResourceFile + { + get + { + return Localization.GetResourceFile(this, MyFileName); + } + } + + #endregion + + #region Private Methods + + /// + /// Localize correctly sets up the control for US/Canada/Other Countries + /// + /// + /// + /// + /// [cnurse] 10/08/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + private void Localize() + { + var countryCode = cboCountry.SelectedItem.Value; + var ctlEntry = new ListController(); + //listKey in format "Country.US:Region" + var listKey = "Country." + countryCode; + var entryCollection = ctlEntry.GetListEntryInfoItems("Region", listKey); + + if (entryCollection.Any()) + { + cboRegion.Visible = true; + txtRegion.Visible = false; + { + cboRegion.Items.Clear(); + cboRegion.DataSource = entryCollection; + cboRegion.DataBind(); + cboRegion.Items.Insert(0, new ListItem("<" + Localization.GetString("Not_Specified", Localization.SharedResourceFile) + ">", "")); + } + if (countryCode.ToLower() == "us") + { + valRegion1.Enabled = true; + valRegion2.Enabled = false; + valRegion1.ErrorMessage = Localization.GetString("StateRequired", Localization.GetResourceFile(this, MyFileName)); + plRegion.Text = Localization.GetString("plState", Localization.GetResourceFile(this, MyFileName)); + plRegion.HelpText = Localization.GetString("plState.Help", Localization.GetResourceFile(this, MyFileName)); + plPostal.Text = Localization.GetString("plZip", Localization.GetResourceFile(this, MyFileName)); + plPostal.HelpText = Localization.GetString("plZip.Help", Localization.GetResourceFile(this, MyFileName)); + } + else + { + valRegion1.ErrorMessage = Localization.GetString("ProvinceRequired", Localization.GetResourceFile(this, MyFileName)); + plRegion.Text = Localization.GetString("plProvince", Localization.GetResourceFile(this, MyFileName)); + plRegion.HelpText = Localization.GetString("plProvince.Help", Localization.GetResourceFile(this, MyFileName)); + plPostal.Text = Localization.GetString("plPostal", Localization.GetResourceFile(this, MyFileName)); + plPostal.HelpText = Localization.GetString("plPostal.Help", Localization.GetResourceFile(this, MyFileName)); + } + valRegion1.Enabled = true; + valRegion2.Enabled = false; + } + else + { + cboRegion.ClearSelection(); + cboRegion.Visible = false; + txtRegion.Visible = true; + valRegion1.Enabled = false; + valRegion2.Enabled = true; + valRegion2.ErrorMessage = Localization.GetString("RegionRequired", Localization.GetResourceFile(this, MyFileName)); + plRegion.Text = Localization.GetString("plRegion", Localization.GetResourceFile(this, MyFileName)); + plRegion.HelpText = Localization.GetString("plRegion.Help", Localization.GetResourceFile(this, MyFileName)); + plPostal.Text = Localization.GetString("plPostal", Localization.GetResourceFile(this, MyFileName)); + plPostal.HelpText = Localization.GetString("plPostal.Help", Localization.GetResourceFile(this, MyFileName)); + } + + var reqRegion = PortalController.GetPortalSettingAsBoolean("addressregion", PortalSettings.PortalId, true); + if (reqRegion) + { + valRegion1.Enabled = false; + valRegion2.Enabled = false; + } + } + + /// + /// ShowRequiredFields sets up displaying which fields are required + /// + /// + /// + /// + /// [cnurse] 10/08/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + private void ShowRequiredFields() + { + var reqStreet = PortalController.GetPortalSettingAsBoolean("addressstreet", PortalSettings.PortalId, true); + var reqCity = PortalController.GetPortalSettingAsBoolean("addresscity", PortalSettings.PortalId, true); + var reqCountry = PortalController.GetPortalSettingAsBoolean("addresscountry", PortalSettings.PortalId, true); + var reqRegion = PortalController.GetPortalSettingAsBoolean("addressregion", PortalSettings.PortalId, true); + var reqPostal = PortalController.GetPortalSettingAsBoolean("addresspostal", PortalSettings.PortalId, true); + var reqTelephone = PortalController.GetPortalSettingAsBoolean("addresstelephone", PortalSettings.PortalId, true); + var reqCell = PortalController.GetPortalSettingAsBoolean("addresscell", PortalSettings.PortalId, true); + var reqFax = PortalController.GetPortalSettingAsBoolean("addressfax", PortalSettings.PortalId, true); + + if (TabPermissionController.CanAdminPage()) + { + if (reqCountry) + { + chkCountry.Checked = true; + valCountry.Enabled = true; + cboCountry.CssClass = "dnnFormRequired"; + } + else + { + valCountry.Enabled = false; + cboCountry.CssClass = ""; + } + if (reqRegion) + { + chkRegion.Checked = true; + txtRegion.CssClass = "dnnFormRequired"; + cboRegion.CssClass = "dnnFormRequired"; + + if (cboRegion.Visible) + { + valRegion1.Enabled = true; + valRegion2.Enabled = false; + } + else + { + valRegion1.Enabled = false; + valRegion2.Enabled = true; + } + } + else + { + valRegion1.Enabled = false; + valRegion2.Enabled = false; + txtRegion.CssClass = ""; + cboRegion.CssClass = ""; + } + if (reqCity) + { + chkCity.Checked = true; + valCity.Enabled = true; + txtCity.CssClass = "dnnFormRequired"; + } + else + { + valCity.Enabled = false; + txtCity.CssClass = ""; + } + if (reqStreet) + { + chkStreet.Checked = true; + valStreet.Enabled = true; + txtStreet.CssClass = "dnnFormRequired"; + } + else + { + valStreet.Enabled = false; + txtStreet.CssClass = ""; + } + if (reqPostal) + { + chkPostal.Checked = true; + valPostal.Enabled = true; + txtPostal.CssClass = "dnnFormRequired"; + } + else + { + valPostal.Enabled = false; + txtPostal.CssClass = ""; + } + if (reqTelephone) + { + chkTelephone.Checked = true; + valTelephone.Enabled = true; + txtTelephone.CssClass = "dnnFormRequired"; + } + else + { + valTelephone.Enabled = false; + txtTelephone.CssClass = ""; + } + if (reqCell) + { + chkCell.Checked = true; + valCell.Enabled = true; + txtCell.CssClass = "dnnFormRequired"; + } + else + { + valCell.Enabled = false; + txtCell.CssClass = ""; + } + if (reqFax) + { + chkFax.Checked = true; + valFax.Enabled = true; + txtFax.CssClass = "dnnFormRequired"; + } + else + { + valFax.Enabled = false; + txtFax.CssClass = ""; + } + } + } + + /// + /// UpdateRequiredFields updates which fields are required + /// + /// + /// + /// + /// [cnurse] 10/08/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + private void UpdateRequiredFields() + { + if (chkCountry.Checked == false) + { + chkRegion.Checked = false; + } + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addressstreet", chkStreet.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addresscity", chkCity.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addresscountry", chkCountry.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addressregion", chkRegion.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addresspostal", chkPostal.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addresstelephone", chkTelephone.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addresscell", chkCell.Checked ? "" : "N"); + PortalController.UpdatePortalSetting(PortalSettings.PortalId, "addressfax", chkFax.Checked ? "" : "N"); + + ShowRequiredFields(); + } + + #endregion + + #region Event Handlers + + /// + /// Page_Load runs when the control is loaded + /// + /// + /// + /// + /// [cnurse] 10/08/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + cboCountry.SelectedIndexChanged += OnCountryIndexChanged; + chkCell.CheckedChanged += OnCellCheckChanged; + chkCity.CheckedChanged += OnCityCheckChanged; + chkCountry.CheckedChanged += OnCountryCheckChanged; + chkFax.CheckedChanged += OnFaxCheckChanged; + chkPostal.CheckedChanged += OnPostalCheckChanged; + chkRegion.CheckedChanged += OnRegionCheckChanged; + chkStreet.CheckedChanged += OnStreetCheckChanged; + chkTelephone.CheckedChanged += OnTelephoneCheckChanged; + + try + { + valStreet.ErrorMessage = Localization.GetString("StreetRequired", Localization.GetResourceFile(this, MyFileName)); + valCity.ErrorMessage = Localization.GetString("CityRequired", Localization.GetResourceFile(this, MyFileName)); + valCountry.ErrorMessage = Localization.GetString("CountryRequired", Localization.GetResourceFile(this, MyFileName)); + valPostal.ErrorMessage = Localization.GetString("PostalRequired", Localization.GetResourceFile(this, MyFileName)); + valTelephone.ErrorMessage = Localization.GetString("TelephoneRequired", Localization.GetResourceFile(this, MyFileName)); + valCell.ErrorMessage = Localization.GetString("CellRequired", Localization.GetResourceFile(this, MyFileName)); + valFax.ErrorMessage = Localization.GetString("FaxRequired", Localization.GetResourceFile(this, MyFileName)); + + if (!Page.IsPostBack) + { + txtStreet.TabIndex = Convert.ToInt16(StartTabIndex); + txtUnit.TabIndex = Convert.ToInt16(StartTabIndex + 1); + txtCity.TabIndex = Convert.ToInt16(StartTabIndex + 2); + cboCountry.TabIndex = Convert.ToInt16(StartTabIndex + 3); + cboRegion.TabIndex = Convert.ToInt16(StartTabIndex + 4); + txtRegion.TabIndex = Convert.ToInt16(StartTabIndex + 5); + txtPostal.TabIndex = Convert.ToInt16(StartTabIndex + 6); + txtTelephone.TabIndex = Convert.ToInt16(StartTabIndex + 7); + txtCell.TabIndex = Convert.ToInt16(StartTabIndex + 8); + txtFax.TabIndex = Convert.ToInt16(StartTabIndex + 9); + + //", "")); + + switch (_countryData.ToLower()) + { + case "text": + if (String.IsNullOrEmpty(_country)) + { + cboCountry.SelectedIndex = 0; + } + else + { + if (cboCountry.Items.FindByText(_country) != null) + { + cboCountry.ClearSelection(); + cboCountry.Items.FindByText(_country).Selected = true; + } + } + break; + case "value": + if (cboCountry.Items.FindByValue(_country) != null) + { + cboCountry.ClearSelection(); + cboCountry.Items.FindByValue(_country).Selected = true; + } + break; + } + Localize(); + + if (cboRegion.Visible) + { + switch (_regionData.ToLower()) + { + case "text": + if (String.IsNullOrEmpty(_region)) + { + cboRegion.SelectedIndex = 0; + } + else + { + if (cboRegion.Items.FindByText(_region) != null) + { + cboRegion.Items.FindByText(_region).Selected = true; + } + } + break; + case "value": + if (cboRegion.Items.FindByValue(_region) != null) + { + cboRegion.Items.FindByValue(_region).Selected = true; + } + break; + } + } + else + { + txtRegion.Text = _region; + } + txtStreet.Text = _street; + txtUnit.Text = _unit; + txtCity.Text = _city; + txtPostal.Text = _postal; + txtTelephone.Text = _telephone; + txtCell.Text = _cell; + txtFax.Text = _fax; + + divStreet.Visible = _showStreet; + divUnit.Visible = _showUnit; + divCity.Visible = _showCity; + divCountry.Visible = _showCountry; + divRegion.Visible = _showRegion; + divPostal.Visible = _showPostal; + divTelephone.Visible = _showTelephone; + divCell.Visible = _showCell; + divFax.Visible = _showFax; + + if (TabPermissionController.CanAdminPage()) + { + chkStreet.Visible = true; + chkCity.Visible = true; + chkCountry.Visible = true; + chkRegion.Visible = true; + chkPostal.Visible = true; + chkTelephone.Visible = true; + chkCell.Visible = true; + chkFax.Visible = true; + } + ViewState["ModuleId"] = Convert.ToString(_moduleId); + ViewState["LabelColumnWidth"] = _labelColumnWidth; + ViewState["ControlColumnWidth"] = _controlColumnWidth; + + ShowRequiredFields(); + } + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnCountryIndexChanged(object sender, EventArgs e) + { + try + { + Localize(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnCityCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnCountryCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnPostalCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnRegionCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnStreetCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnTelephoneCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnCellCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnFaxCheckChanged(object sender, EventArgs e) + { + try + { + UpdateRequiredFields(); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + #endregion + + } +} diff --git a/DNN Platform/Library/UI/UserControls/DualListControl.cs b/DNN Platform/Library/UI/UserControls/DualListControl.cs new file mode 100644 index 00000000000..7a21c6b8497 --- /dev/null +++ b/DNN Platform/Library/UI/UserControls/DualListControl.cs @@ -0,0 +1,308 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Web.UI.WebControls; + +using DotNetNuke.Framework; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.UserControls +{ + public abstract class DualListControl : UserControlBase + { + #region "Private Members" + protected Label Label1; + protected Label Label2; + private string MyFileName = "DualListControl.ascx"; + private ArrayList _Assigned; + private ArrayList _Available; + private string _DataTextField = ""; + private string _DataValueField = ""; + private bool _Enabled = true; + private string _ListBoxHeight = ""; + private string _ListBoxWidth = ""; + protected LinkButton cmdAdd; + protected LinkButton cmdAddAll; + protected LinkButton cmdRemove; + protected LinkButton cmdRemoveAll; + protected ListBox lstAssigned; + protected ListBox lstAvailable; + + #endregion + + #region "Public Properties" + + public string ListBoxWidth + { + get + { + return Convert.ToString(ViewState[ClientID + "_ListBoxWidth"]); + } + set + { + _ListBoxWidth = value; + } + } + + public string ListBoxHeight + { + get + { + return Convert.ToString(ViewState[ClientID + "_ListBoxHeight"]); + } + set + { + _ListBoxHeight = value; + } + } + + public ArrayList Available + { + get + { + var objList = new ArrayList(); + foreach (ListItem objListItem in lstAvailable.Items) + { + objList.Add(objListItem); + } + return objList; + } + set + { + _Available = value; + } + } + + public ArrayList Assigned + { + get + { + var objList = new ArrayList(); + foreach (ListItem objListItem in lstAssigned.Items) + { + objList.Add(objListItem); + } + return objList; + } + set + { + _Assigned = value; + } + } + + public string DataTextField + { + set + { + _DataTextField = value; + } + } + + public string DataValueField + { + set + { + _DataValueField = value; + } + } + + public bool Enabled + { + set + { + _Enabled = value; + } + } + + #endregion + + #region "Protected Event Handlers" + + /// The Page_Load server event handler on this page is used to populate the role information for the page + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + cmdAdd.Click += cmdAdd_Click; + cmdAddAll.Click += cmdAddAll_Click; + cmdRemove.Click += cmdRemove_Click; + cmdRemoveAll.Click += cmdRemoveAll_Click; + + try + { + //Localization + Label1.Text = Localization.GetString("Available", Localization.GetResourceFile(this, MyFileName)); + Label2.Text = Localization.GetString("Assigned", Localization.GetResourceFile(this, MyFileName)); + cmdAdd.ToolTip = Localization.GetString("Add", Localization.GetResourceFile(this, MyFileName)); + cmdAddAll.ToolTip = Localization.GetString("AddAll", Localization.GetResourceFile(this, MyFileName)); + cmdRemove.ToolTip = Localization.GetString("Remove", Localization.GetResourceFile(this, MyFileName)); + cmdRemoveAll.ToolTip = Localization.GetString("RemoveAll", Localization.GetResourceFile(this, MyFileName)); + + if (!Page.IsPostBack) + { + //set dimensions of control + if (!String.IsNullOrEmpty(_ListBoxWidth)) + { + lstAvailable.Width = Unit.Parse(_ListBoxWidth); + lstAssigned.Width = Unit.Parse(_ListBoxWidth); + } + if (!String.IsNullOrEmpty(_ListBoxHeight)) + { + lstAvailable.Height = Unit.Parse(_ListBoxHeight); + lstAssigned.Height = Unit.Parse(_ListBoxHeight); + } + + //load available + lstAvailable.DataTextField = _DataTextField; + lstAvailable.DataValueField = _DataValueField; + lstAvailable.DataSource = _Available; + lstAvailable.DataBind(); + Sort(lstAvailable); + + //load selected + lstAssigned.DataTextField = _DataTextField; + lstAssigned.DataValueField = _DataValueField; + lstAssigned.DataSource = _Assigned; + lstAssigned.DataBind(); + Sort(lstAssigned); + + //set enabled + lstAvailable.Enabled = _Enabled; + lstAssigned.Enabled = _Enabled; + + //save persistent values + ViewState[ClientID + "_ListBoxWidth"] = _ListBoxWidth; + ViewState[ClientID + "_ListBoxHeight"] = _ListBoxHeight; + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void cmdAdd_Click(object sender, EventArgs e) + { + var objList = new ArrayList(); + foreach (ListItem objListItem in lstAvailable.Items) + { + objList.Add(objListItem); + } + foreach (ListItem objListItem in objList) + { + if (objListItem.Selected) + { + lstAvailable.Items.Remove(objListItem); + lstAssigned.Items.Add(objListItem); + } + } + lstAvailable.ClearSelection(); + lstAssigned.ClearSelection(); + Sort(lstAssigned); + } + + private void cmdRemove_Click(object sender, EventArgs e) + { + var objList = new ArrayList(); + foreach (ListItem objListItem in lstAssigned.Items) + { + objList.Add(objListItem); + } + foreach (ListItem objListItem in objList) + { + if (objListItem.Selected) + { + lstAssigned.Items.Remove(objListItem); + lstAvailable.Items.Add(objListItem); + } + } + lstAvailable.ClearSelection(); + lstAssigned.ClearSelection(); + Sort(lstAvailable); + } + + private void cmdAddAll_Click(object sender, EventArgs e) + { + foreach (ListItem objListItem in lstAvailable.Items) + { + lstAssigned.Items.Add(objListItem); + } + lstAvailable.Items.Clear(); + lstAvailable.ClearSelection(); + lstAssigned.ClearSelection(); + Sort(lstAssigned); + } + + private void cmdRemoveAll_Click(object sender, EventArgs e) + { + foreach (ListItem objListItem in lstAssigned.Items) + { + lstAvailable.Items.Add(objListItem); + } + lstAssigned.Items.Clear(); + lstAvailable.ClearSelection(); + lstAssigned.ClearSelection(); + Sort(lstAvailable); + } + + #endregion + + #region "Private Methods" + + private void Sort(ListBox ctlListBox) + { + var arrListItems = new ArrayList(); + foreach (ListItem objListItem in ctlListBox.Items) + { + arrListItems.Add(objListItem); + } + arrListItems.Sort(new ListItemComparer()); + ctlListBox.Items.Clear(); + foreach (ListItem objListItem in arrListItems) + { + ctlListBox.Items.Add(objListItem); + } + } + + #endregion + } + + public class ListItemComparer : IComparer + { + #region IComparer Members + + public int Compare(object x, object y) + { + var a = (ListItem) x; + var b = (ListItem) y; + var c = new CaseInsensitiveComparer(); + return c.Compare(a.Text, b.Text); + } + + #endregion + } +} \ No newline at end of file diff --git a/DNN Platform/Library/UI/UserControls/Help.cs b/DNN Platform/Library/UI/UserControls/Help.cs new file mode 100644 index 00000000000..e1a355d3bfb --- /dev/null +++ b/DNN Platform/Library/UI/UserControls/Help.cs @@ -0,0 +1,158 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.IO; +using System.Web.UI.WebControls; + +using DotNetNuke.Application; +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Modules.Definitions; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Installer.Packages; +using DotNetNuke.Services.Localization; + +#endregion + +namespace DotNetNuke.UI.UserControls +{ + public abstract class Help : PortalModuleBase + { + private string MyFileName = "Help.ascx"; + private string _key; + protected LinkButton cmdCancel; + protected Literal helpFrame; + protected Label lblHelp; + protected Label lblInfo; + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the control is loaded. + /// + /// + /// + /// + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + cmdCancel.Click += cmdCancel_Click; + int moduleControlId = Null.NullInteger; + + if (Request.QueryString["ctlid"] != null) + { + moduleControlId = Int32.Parse(Request.QueryString["ctlid"]); + } + else if (Host.EnableModuleOnLineHelp) + { + helpFrame.Text = string.Format(" + + + + + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/MobilePreview/Preview.ascx.cs b/Website/DesktopModules/Admin/MobilePreview/Preview.ascx.cs new file mode 100644 index 00000000000..2ba3e74388c --- /dev/null +++ b/Website/DesktopModules/Admin/MobilePreview/Preview.ascx.cs @@ -0,0 +1,245 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Security; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Framework; +using DotNetNuke.Services.Mobile; +using DotNetNuke.Web.Client.ClientResourceManagement; +using DotNetNuke.Web.UI.WebControls; + +#endregion + +namespace DotNetNuke.Modules.Admin.MobilePreview +{ + public partial class Preview : PortalModuleBase + { + #region "Public Properties" + + protected string PreviewUrl + { + get + { + var tabId = PortalSettings.HomeTabId; + + if (Request.QueryString["previewTab"] != null) + { + int.TryParse(Request.QueryString["previewTab"], out tabId); + } + + return Globals.NavigateURL(tabId, string.Empty, string.Empty); + } + } + + #endregion + + #region "Event Handlers" + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if (!string.IsNullOrEmpty(Request.QueryString["UserAgent"])) + { + var userAgent = UrlUtils.DecryptParameter(Request.QueryString["UserAgent"]); + if (Request.QueryString["SendAgent"] != "true") + { + userAgent = Request.UserAgent; + } + + CreateViewProxy(userAgent); + } + + this.Page.Title = LocalizeString("PageTitle"); + + ClientResourceManager.RegisterScript(this.Page, string.Format("{0}Scripts/PreviewEmulator.js", this.ControlPath)); + + if (!IsPostBack) + { + BindProfiles(); + } + } + + #endregion + + #region "Private Methods" + + private void BindProfiles() + { + var profiles = new PreviewProfileController().GetProfilesByPortal(ModuleContext.PortalId); + ddlProfileList.Items.Clear(); + + var selectedProfile = -1; + if (Request.QueryString["profile"] != null) + { + selectedProfile = Convert.ToInt32(Request.QueryString["profile"]); + } + + foreach (var previewProfile in profiles) + { + var value = string.Format("width : \"{0}\", height : \"{1}\", userAgent: \"{2}\"", previewProfile.Width, previewProfile.Height, UrlUtils.EncryptParameter(previewProfile.UserAgent)); + + var listItem = new ListItem(previewProfile.Name, value); + if (selectedProfile == previewProfile.Id) + { + listItem.Selected = true; + } + + ddlProfileList.AddItem(listItem.Text, listItem.Value); + } + } + + private void CreateViewProxy(string userAgent) + { + Response.Clear(); + + //Depending on number of redirects, GetHttpContent can be a self-recursive call. + Response.Write(GetHttpContent(PreviewUrl, userAgent)); + + Response.End(); + } + + private string GetHttpContent(string url, string userAgent) + { + try + { + //add dnnprintmode in url so that all DNN page will display in normal. + var requestUrl = url; + if (requestUrl.IndexOf("dnnprintmode") == -1) + { + requestUrl = string.Format("{0}{1}dnnprintmode=true", url, url.IndexOf("?") == -1 ? "?" : "&"); + } + + var wreq = Globals.GetExternalRequest(requestUrl); + wreq.UserAgent = userAgent; + wreq.Referer = Request.Url.ToString(); + wreq.Method = "GET"; + wreq.Timeout = Host.WebRequestTimeout; + wreq.AllowAutoRedirect = false; + wreq.ContentType = "application/x-www-form-urlencoded"; + SetCookies(wreq); + + if (requestUrl.StartsWith("https://")) + { + ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; + } + + var httpResponse = wreq.GetResponse() as HttpWebResponse; + + //if the request has been redirect, add PrintMode in url and re-request + if (httpResponse.StatusCode == HttpStatusCode.Found || httpResponse.StatusCode == HttpStatusCode.MovedPermanently) + { + var redirectUrl = httpResponse.Headers["Location"]; + + //calling same method recursive. + return GetHttpContent(redirectUrl, userAgent); + } + + //get content from http response + var responseStream = httpResponse.GetResponseStream(); + + using (var reader = new StreamReader(responseStream, true)) + { + var content = reader.ReadToEnd(); + + var requestUri = wreq.Address; + + content = MakeAbsoluteUrl(content, requestUri); + + //append current url to a js variable, so that can be used in client side. + content += string.Format("", url); + return content; + } + } + catch (SecurityException) + { + return string.Format("{0}", "You must change your website's trust level to full trust if you want to preview an SSL path."); + } + catch (Exception ex) + { + return string.Format("{0}", "ERROR:" + ex.Message); + } + } + + //append current cookies to the http request + private void SetCookies(HttpWebRequest proxyRequest) + { + proxyRequest.CookieContainer = new CookieContainer(); + var sessionCookie = GetSessionCookieName(); + foreach (var key in Request.Cookies.AllKeys) + { + if (key == sessionCookie) + { + continue; + } + + var cookie = new Cookie(key, Request.Cookies[key].Value, "/", proxyRequest.RequestUri.Host); + proxyRequest.CookieContainer.Add(cookie); + } + } + + private string MakeAbsoluteUrl(string content, Uri requestUri) + { + var domain = requestUri.AbsoluteUri.Replace(requestUri.PathAndQuery, string.Empty); + var currDirectory = domain; + for (var i = 0; i < requestUri.Segments.Length - 1; i++) + { + currDirectory += requestUri.Segments[i]; + + } + + Regex pathReg = new Regex("(src|href)=['\"]?([^>'\"\\s]+)['\"]?"); + MatchCollection matches = pathReg.Matches(content); + foreach (Match match in matches) + { + var path = match.Groups[2].Value; + if (!string.IsNullOrEmpty(path) && path.IndexOf(":") == -1 && !path.StartsWith("#")) + { + var prefix = path.StartsWith("/") ? domain : currDirectory; + content = content.Replace(match.Value, string.Format("{0}=\"{1}{2}\"", match.Groups[1].Value, prefix, path)); + } + } + + return content; + } + + private string GetSessionCookieName() + { + return "ASP.NET_SessionId"; + } + + #endregion + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/MobilePreview/Scripts/PreviewEmulator.js b/Website/DesktopModules/Admin/MobilePreview/Scripts/PreviewEmulator.js new file mode 100644 index 00000000000..7709d889589 --- /dev/null +++ b/Website/DesktopModules/Admin/MobilePreview/Scripts/PreviewEmulator.js @@ -0,0 +1,240 @@ +(function ($) { + $.fn.previewEmulator = function (options) { + var handler = this; + + if (handler.data("previewEmulator")) { + return handler.data("previewEmulator"); + } + + var hDimension = this.find(".dimension_h"); + var vDimension = this.find(".dimension_v"); + var viewContainer = this.find(".emulator_c"); + var viewAddr = this.find(".emulator_addr"); + var viewer = this.find("iframe"); + var sendAgent = true; + + var bindElement = function () { + viewContainer = handler.find(".emulator_c"); + viewer = handler.find("iframe"); + + viewContainer.scroll(); + + viewContainer.bind("resize", function (e) { + var width = $(this).width(); + var height = $(this).height(); + + hDimension.width(width); + vDimension.height(height); + viewAddr.width(width); + + var hContentWidth = width - hDimension.find(".left").width() - hDimension.find(".right").width(); + hDimension.find(".center").width(hContentWidth).html(width + "px"); + + var vContentHeight = height - vDimension.find(".top").height() - vDimension.find(".bottom").height(); + vDimension.find(".middle").height(vContentHeight).css("line-height", vContentHeight + "px").html(height + "px"); + + if (viewer.width() < viewContainer.width()) { + viewer.width(viewContainer.width()); + } + + if (viewer.height() < viewContainer.height()) { + viewer.height(viewContainer.height()); + } + + $(this).scroll(); + + }); + + viewer.bind("load", function () { + var frameWin = this.contentWindow; + var frameDoc = frameWin.document; + + var body = frameDoc.documentElement != undefined ? frameDoc.documentElement : frameDoc.body; + var width = body.scrollWidth; + var height = body.scrollHeight; + + $(this).width(width).height(height); + + viewAddr.html(frameWin.dnnPreviewUrl); + + viewContainer.trigger("resize"); + }); + }; + + bindElement(); + + var updateViewer = function (userAgent) { + var url = location.href + (location.href.indexOf("?") > -1 ? "&" : "?") + "UserAgent=" + userAgent + "&SendAgent=" + sendAgent; + viewer.attr("src", url); + }; + + this.setPreview = function (width, height, userAgent) { + updateViewer(userAgent); + viewContainer.width(width).height(height); + viewContainer.trigger("resize"); + }; + + this.showDimension = function (show) { + var visible = show ? "visible" : "hidden"; + hDimension.css("visibility", visible); + vDimension.css("visibility", visible); + }; + + this.previewWithAgent = function(send) { + sendAgent = send; + }; + + hDimension.html(""); + vDimension.html(""); + + handler.data("previewEmulator", this); + + return this; + }; + + $.fn.scroll = function (options) { + var handler = this; + var scrollTemplate = "
    "; + var mask = $("
    "); + } + + hScrollBar.unbind("mousedown").mousedown(function (e) { + startDragOnX($(this), e); + }); + }; + + var startDragOnY = function (bar, event) { + initDrag(bar); + bar.data("position", event.pageY); + $(document).mousemove(function (e) { + if (bar.data("position") !== undefined && bar.data("position") !== null) { + var offset = e.pageY - bar.data("position"); + scrollOnY(offset); + + bar.data("position", e.pageY); + } + }).mouseup(function (e) { + endDrag(bar); + }); + }; + + var startDragOnX = function (bar, event) { + initDrag(bar); + bar.data("position", event.pageX); + $(document).mousemove(function (e) { + if (bar.data("position") !== undefined && bar.data("position") !== null) { + var offset = e.pageX - bar.data("position"); + scrollOnX(offset); + + bar.data("position", e.pageX); + } + }).mouseup(function (e) { + endDrag(bar); + }); + }; + + var initDrag = function (bar) { + mask.appendTo(handler).width(handler.data("viewWidth")).height(handler.data("viewHeight")).css({ opacity: 0 }); + }; + + var endDrag = function (bar) { + bar.data("position", null); + $(document).unbind(); + + mask.remove(); + }; + + var scrollOnY = function (offset) { + var margin = parseInt(vScrollBar.css("top")) + offset; + if (margin >= 0 && margin <= vScroll.height() - vScrollBar.height()) { + vScrollBar.css({ top: margin + "px" }); + + var percent = margin / (vScroll.height() - vScrollBar.height()); + var contentTop = (contentArea.height() - handler.data("viewHeight")) * percent * -1; + + contentArea.css({ top: contentTop + "px" }); + } + }; + + var scrollOnX = function (offset) { + var margin = parseInt(hScrollBar.css("left")) + offset; + if (margin >= 0 && margin <= hScroll.width() - hScrollBar.width()) { + hScrollBar.css({ left: margin + "px" }); + + var percent = margin / (hScroll.width() - hScrollBar.width()); + var contentLeft = (contentArea.width() - handler.data("viewWidth")) * percent * -1; + + contentArea.css({ left: contentLeft + "px" }); + } + }; + + var scrollTo = function (x, y) { + var offsetX = x - parseInt(hScrollBar.css("margin-left")); + scrollOnX(offsetX); + + var offsetY = y - parseInt(vScrollBar.css("margin-top")); + scrollOnY(offsetY); + }; + + init(); + + this.data("scroll", "initialed"); + return this; + }; +})(jQuery); \ No newline at end of file diff --git a/Website/DesktopModules/Admin/MobilePreview/module.css b/Website/DesktopModules/Admin/MobilePreview/module.css new file mode 100644 index 00000000000..286b8c7625c --- /dev/null +++ b/Website/DesktopModules/Admin/MobilePreview/module.css @@ -0,0 +1,30 @@ +#emulator {position: relative;display: inline-block;margin-left: 60px; } + +#emulator .dimension_h {display: inline-block;position: absolute;height: 10px;left: 10px;} +#emulator .dimension_h span { display: block;text-align: center;vertical-align: middle;color: #939393;float: left;} +#emulator .dimension_h span.left{ background: url(images/arrow.png) no-repeat 0 -3px;width: 3px;height: 5px;} +#emulator .dimension_h span.center{ border-bottom: 1px solid #e0e0e0;height: 23px;margin-top: -21px;} +#emulator .dimension_h span.right{ background: url(images/arrow.png) no-repeat -8px -3px;width: 3px;height: 5px;} + +#emulator .dimension_v {display: inline-block;position: absolute;width: 10px;top: 70px;} +#emulator .dimension_v span { display: block;text-align: center;vertical-align: middle;color: #939393;} +#emulator .dimension_v span.top{ background: url(images/arrow.png) no-repeat -3px 0;width: 5px;height: 3px;} +#emulator .dimension_v span.middle{ border-right: 1px solid #e0e0e0;width: 60px;margin-left: -58px;} +#emulator .dimension_v span.bottom{ background: url(images/arrow.png) no-repeat -3px -8px;width: 5px;height: 3px;} + + + +#emulator .emulator_c{top: 10px;left:10px;border: 1px solid #e0e0e0; overflow: hidden;position: relative;-webkit-user-select: none;} +#emulator .emulator_c iframe{ border: none;position: relative;} +#emulator .emulator_c .scroll{ background-color: #e0e0e0;position: absolute;overflow: hidden;} +#emulator .emulator_c .scroll .bar{ position: absolute;background-color: #939393;cursor:pointer;-webkit-user-select: none;} +#emulator .emulator_c .vertical{top: 0; right: 0;width: 10px;height: 100%;-moz-user-select:none;} +#emulator .emulator_c .vertical .bar{ width: 100%;top: 0px;} +#emulator .emulator_c .horizontal{bottom: 0; left: 0;height: 10px;width: 100%;-moz-user-select:none;} +#emulator .emulator_c .horizontal .bar{ height: 100%;left: 0px;} +#emulator .emulator_c .status{ bottom: 0;right: 0;width: 10px;height: 10px;background-color: #fff;position: absolute;} +#emulator .emulator_c .mask{ position: absolute;left: 0;top: 0;background-color: #f00;} + +#emulator .emulator_addr{ top: 0px;left: 10px;background-color: #ccc; position: relative;height: 30px;line-height: 30px;font-size: 14px;overflow: hidden;margin-bottom: 30px;} + +div.dnnFormItem label, div.dnnFormItem .dnnFormLabel, div.dnnFormItem .dnnTooltip{ width: 20%;} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Newsletters/App_LocalResources/Newsletter.ascx.resx b/Website/DesktopModules/Admin/Newsletters/App_LocalResources/Newsletter.ascx.resx new file mode 100644 index 00000000000..b155a74de4f --- /dev/null +++ b/Website/DesktopModules/Admin/Newsletters/App_LocalResources/Newsletter.ascx.resx @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Basic Settings + + + Addressees + + + User Role(s) + + + Select the User Roles that are to receive this message, e.g. 'Administrators', or 'Registered Users'. + + + Language Filter + + + Specify a filter for users according to the languages in their profiles. + + + Additional Emails + + + You can add Email addresses, separated by a ";". + + + From + + + Enter the 'From' email address of the email message. + + + Reply To + + + Enter the 'ReplyTo' email address for the email message. + + + The email address is in an invalid format! + + + Subject + + + Enter the subject of this message. + + + Message + + + Advanced Settings + + + Attachment + + + Select an Attachment for this message. + + + Priority + + + Select the priority for this message. + + + Normal + + + High + + + Low + + + Replace Tokens + + + Does the text contain any tokens, that shall be replaced with current environment values?<br> Note: User tokens are not replaced, if send method is "BCC" + + + No duplicate addresses + + + Activate this option to remove duplicate email addresses from the addressees list. + + + TO: One Message Per Email Address ( Personalized ) + + + BCC: One Email To Blind Distribution List ( Not Personalized ) + + + Relay: One Message Per Email Address ( Personalized ) to a specified relay server + + + Relay Address + + + Select the method for this email to be sent. + + + Send Method + + + Send Action + + + Select, how emails should be sent - Synchronous - emails are sent immediately - you will not be able to return to the application until this has completed or Asynchronous - emails are sent as a background task - you will be able to continue to do other tasks while this is being completed.. + + + Synchronous + + + Asynchronous + + + Send Email + + + Newsletters + + + Bulk mail sent (asynchronous mode). Please check confirmation email for result. + + + <h1>About Newsletters</h1> +<p>Administrators can send bulk email to all users belonging to&nbsp;one or multiple&nbsp;selected <strong>roles</strong> and can also specify <strong>additional email addresses</strong> manually. In Multilingual websites, there is a <strong>language filter</strong> displayed, in order to send language specific content.</p> +<p>The author can specify a <strong>sender's email address</strong> (default&nbsp;is taken from his own profile)&nbsp;and optionally a <strong>&quot;ReplyTo&quot; address</strong>. The <strong>format</strong> (plain text or HTML) of the email is determined by the editor used.</p> +<p>Text in the <strong>subject</strong> and <strong>body</strong> can contain tokens for properties for environment objects like Portal, User and Date/Time, that will get replaced by the current values, if <strong>Replace Tokens</strong> is enabled. An <strong>Attachment</strong> file can be specified as well as <strong>priority</strong> and whether to <strong>suppress multiple emails</strong> sent to same address.</p> +<p>There are 3 <strong>send methods</strong>:</p> +<ul> + <li><strong>TO</strong> sends the address individually to each adressee, replacing all available tokens</li> + <li><strong>BCC</strong> sends a single email to the sender, including all adressees as hidden recipients.<br /> + All user individual&nbsp;tokens will not get replaced</li> + <li><strong>RELAY</strong> is used like TO, but all individual emails get send to the specified RELAY address. You need to use tokens for users' mobile&nbsp;phone or fax number to&nbsp;get the message delivered.</li> +</ul> +<p>If you send&nbsp;<strong>synchronously</strong>, you need to wait until all mails are sent, before you can continue. In Asynchronous mode, you can continue immediately. The success of the send out will be delivered as a report to the&nbsp;&quot;FROM&quot; email address.</p> + + + Dear  + + + You must include a Subject and Message + + + {0} Messages were sent out successfully + + + No Messages were sent. A confirmation email has been sent to {0} with a description of the errors that happened during the sending process. + + + Preview Email + + + An error occurred while sending the email: {0} + + + No Messages were sent because there are no recipients for this email. + + + Cancel Preview + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx b/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx new file mode 100644 index 00000000000..990c2a06779 --- /dev/null +++ b/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx @@ -0,0 +1,141 @@ +<%@ Control Inherits="DotNetNuke.Modules.Admin.Newsletters.Newsletter" Language="C#" AutoEventWireup="false" CodeFile="Newsletter.ascx.cs" %> +<%@ Register TagPrefix="dnn" TagName="TextEditor" Src="~/controls/TextEditor.ascx" %> +<%@ Register TagPrefix="dnn" TagName="SectionHead" Src="~/controls/SectionHeadControl.ascx" %> +<%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %> +<%@ Register TagPrefix="dnn" TagName="URLControl" Src="~/controls/URLControl.ascx" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.UI.WebControls" Assembly="DotNetNuke" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.UI.WebControls" Assembly="DotNetNuke.Web" %> +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + +
    +
    + + + +
    +
    + + +
    +
    + + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    + + +
    +
    + + <%-- + + + + --%> + + + + + + + +
    +
    + + <%-- + + + + --%> + + + + + + + +
    +
    + + + +
    +
    + + + + + +
    +
    +
    +
      +
    • +
    • +
    +
    + + + + + + + + + + + + + + +
    Preview
    +
      +
    • +
    +
    + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx.cs b/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx.cs new file mode 100644 index 00000000000..f511718a3f0 --- /dev/null +++ b/Website/DesktopModules/Admin/Newsletters/Newsletter.ascx.cs @@ -0,0 +1,444 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections.Generic; +using System.Net.Mime; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; + +using DotNetNuke.Common; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Mail; +using DotNetNuke.Services.Tokens; +using DotNetNuke.UI.Skins.Controls; + +#endregion + +namespace DotNetNuke.Modules.Admin.Newsletters +{ + + /// ----------------------------------------------------------------------------- + /// + /// The Newsletter PortalModuleBase is used to manage a Newsletters + /// + /// + /// + /// + /// [cnurse] 2004-09-13 Updated to reflect design changes for Help, 508 support and localisation + /// [lpointer] 2006-02-03 Added 'From' email address support. + /// + /// ----------------------------------------------------------------------------- + public partial class Newsletter : PortalModuleBase + { + + #region Private Methods + + /// + /// helper function for ManageDirectoryBase + /// + /// [vmasanas] 2007-09-07 added + /// [sleupold] 2008-02-10 support for local links added + /// + /// + private static string FormatUrls(Match m) + { + var match = m.Value; + var url = m.Groups["url"].Value; + var result = match; + if (url.StartsWith("/")) //server absolute path + { + return result.Replace(url, Globals.AddHTTP(HttpContext.Current.Request.Url.Host) + url); + } + return url.Contains("://") || url.Contains("mailto:") ? result : result.Replace(url, Globals.AddHTTP(HttpContext.Current.Request.Url.Host) + Globals.ApplicationPath + "/" + url); + } + + #endregion + + #region Event Handlers + + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the control is loaded + /// + /// + /// [cnurse] 2004-09-10 Updated to reflect design changes for Help, 508 support and localisation + /// [sleupold] 2007-10-07 Relay address and Language adoption added + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + cmdPreview.Click += OnPreviewClick; + cmdSend.Click += OnSendClick; + + jQuery.RequestDnnPluginsRegistration(); + + try + { + if (!Page.IsPostBack) + { + txtFrom.Text = UserInfo.Email; + } + plLanguages.Visible = (LocaleController.Instance.GetLocales(PortalId).Count > 1); + pnlRelayAddress.Visible = (cboSendMethod.SelectedValue == "RELAY"); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdSend_Click runs when the cmdSend Button is clicked + /// + /// + /// + /// + /// [cnurse] 2004-09-10 Updated to reflect design changes for Help, 508 support and localisation + /// [sleupold] 2007-08-15 added support for tokens and SendTokenizedBulkEmail + /// [sleupold] 2007-09-09 moved Roles to SendTokenizedBulkEmail + /// + /// ----------------------------------------------------------------------------- + protected void OnSendClick(Object sender, EventArgs e) + { + var message = ""; + var messageType = ModuleMessage.ModuleMessageType.GreenSuccess; + + try + { + List roleNames; + List users; + GetRecipients(out roleNames, out users); + + if(IsReadyToSend(roleNames, users, ref message, ref messageType)) + { + SendEmail(roleNames, users, ref message, ref messageType); + } + + UI.Skins.Skin.AddModuleMessage(this, message, messageType); + ((CDefault) Page).ScrollToControl(Page.Form); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void SendEmail(List roleNames, List users, ref string message, ref ModuleMessage.ModuleMessageType messageType) + { + //it is awkward to ensure that email is disposed correctly because when sent asynch it should be disposed by the asynch thread + var email = new SendTokenizedBulkEmail(roleNames, users, /*removeDuplicates*/ true, txtSubject.Text, ConvertToAbsoluteUrls(teMessage.Text)); + + bool isValid; + try + { + isValid = PrepareEmail(email, ref message, ref messageType); + } + catch(Exception) + { + email.Dispose(); + throw; + } + + if (isValid) + { + + if (optSendAction.SelectedItem.Value == "S") + { + try + { + SendMailSynchronously(email, out message, out messageType); + } + finally + { + email.Dispose(); + } + } + else + { + SendMailAsyncronously(email, out message, out messageType); + //dispose will be handled by async thread + } + } + } + + private void SendMailAsyncronously(SendTokenizedBulkEmail email, out string message, out ModuleMessage.ModuleMessageType messageType) + { + //First send off a test message + var strStartSubj = Localization.GetString("EMAIL_BulkMailStart_Subject.Text", Localization.GlobalResourceFile); + if (!string.IsNullOrEmpty(strStartSubj)) strStartSubj = string.Format(strStartSubj, txtSubject.Text); + + var strStartBody = Localization.GetString("EMAIL_BulkMailStart_Body.Text", Localization.GlobalResourceFile); + if (!string.IsNullOrEmpty(strStartBody)) strStartBody = string.Format(strStartBody, txtSubject.Text, UserInfo.DisplayName, email.Recipients().Count); + + var sendMailResult = Mail.SendMail(txtFrom.Text, + txtFrom.Text, + "", + "", + MailPriority.Normal, + strStartSubj, + MailFormat.Text, + Encoding.UTF8, + strStartBody, + "", + Host.SMTPServer, + Host.SMTPAuthentication, + Host.SMTPUsername, + Host.SMTPPassword, + Host.EnableSMTPSSL); + + if (string.IsNullOrEmpty(sendMailResult)) + { + var objThread = new Thread(() => SendAndDispose(email)); + objThread.Start(); + message = Localization.GetString("MessageSent", LocalResourceFile); + messageType = ModuleMessage.ModuleMessageType.GreenSuccess; + } + else + { + message = string.Format(Localization.GetString("NoMessagesSentPlusError", LocalResourceFile), sendMailResult); + messageType = ModuleMessage.ModuleMessageType.YellowWarning; + } + } + + private void SendAndDispose(SendTokenizedBulkEmail email) + { + using(email) + { + email.Send(); + } + } + + private void SendMailSynchronously(SendTokenizedBulkEmail email, out string strResult, out ModuleMessage.ModuleMessageType msgResult) + { + int mailsSent = email.SendMails(); + + if (mailsSent > 0) + { + strResult = string.Format(Localization.GetString("MessagesSentCount", LocalResourceFile), mailsSent); + msgResult = ModuleMessage.ModuleMessageType.GreenSuccess; + } + else + { + strResult = string.Format(Localization.GetString("NoMessagesSent", LocalResourceFile), email.SendingUser.Email); + msgResult = ModuleMessage.ModuleMessageType.YellowWarning; + } + } + + private bool PrepareEmail(SendTokenizedBulkEmail email, ref string message, ref ModuleMessage.ModuleMessageType messageType) + { + bool isValid = true; + + switch (teMessage.Mode) + { + case "RICH": + email.BodyFormat = MailFormat.Html; + break; + default: + email.BodyFormat = MailFormat.Text; + break; + } + + switch (cboPriority.SelectedItem.Value) + { + case "1": + email.Priority = MailPriority.High; + break; + case "2": + email.Priority = MailPriority.Normal; + break; + case "3": + email.Priority = MailPriority.Low; + break; + default: + isValid = false; + break; + } + + if (txtFrom.Text != string.Empty && email.SendingUser.Email != txtFrom.Text) + { + var myUser = email.SendingUser ?? new UserInfo(); + myUser.Email = txtFrom.Text; + email.SendingUser = myUser; + } + + if (txtReplyTo.Text != string.Empty && email.ReplyTo.Email != txtReplyTo.Text) + { + var myUser = new UserInfo {Email = txtReplyTo.Text}; + email.ReplyTo = myUser; + } + + if (selLanguage.Visible && selLanguage.SelectedLanguages != null) + { + email.LanguageFilter = selLanguage.SelectedLanguages; + } + + if (ctlAttachment.Url.StartsWith("FileID=")) + { + int fileId = int.Parse(ctlAttachment.Url.Substring(7)); + var objFileInfo = FileManager.Instance.GetFile(fileId); + //TODO: support secure storage locations for attachments! [sleupold 06/15/2007] + email.AddAttachment(FileManager.Instance.GetFileContent(objFileInfo), + new ContentType { MediaType = objFileInfo.ContentType, Name = objFileInfo.FileName }); + } + + switch (cboSendMethod.SelectedItem.Value) + { + case "TO": + email.AddressMethod = SendTokenizedBulkEmail.AddressMethods.Send_TO; + break; + case "BCC": + email.AddressMethod = SendTokenizedBulkEmail.AddressMethods.Send_BCC; + break; + case "RELAY": + email.AddressMethod = SendTokenizedBulkEmail.AddressMethods.Send_Relay; + if (string.IsNullOrEmpty(txtRelayAddress.Text)) + { + message = string.Format(Localization.GetString("MessagesSentCount", LocalResourceFile), -1); + messageType = ModuleMessage.ModuleMessageType.YellowWarning; + isValid = false; + } + else + { + email.RelayEmailAddress = txtRelayAddress.Text; + } + break; + } + + email.SuppressTokenReplace = !chkReplaceTokens.Checked; + + return isValid; + } + + private bool IsReadyToSend(List roleNames, List users, ref string message, ref ModuleMessage.ModuleMessageType messageType) + { + if (String.IsNullOrEmpty(txtSubject.Text) || String.IsNullOrEmpty(teMessage.Text)) + { + message = Localization.GetString("MessageValidation", LocalResourceFile); + messageType = ModuleMessage.ModuleMessageType.RedError; + return false; + } + + if (users.Count == 0 && roleNames.Count == 0) + { + message = string.Format(Localization.GetString("NoRecipients", LocalResourceFile), -1); + messageType = ModuleMessage.ModuleMessageType.YellowWarning; + return false; + } + + return true; + } + + private void GetRecipients(out List objRoleNames, out List objUsers) + { + objRoleNames = new List(); + foreach (string strRoleName in dgSelectedRoles.SelectedRoleNames) + { + objRoleNames.Add(strRoleName); + } + + objUsers = new List(); + if (!String.IsNullOrEmpty(txtEmail.Text)) + { + Array arrEmail = txtEmail.Text.Split(';'); + foreach (string strEmail in arrEmail) + { + var objUser = new UserInfo {UserID = Null.NullInteger, Email = strEmail, DisplayName = strEmail}; + objUsers.Add(objUser); + } + } + } + + /// + /// Display a preview of the message to be sent out + /// + /// ignored + /// ignores + /// + /// [vmasanas] 2007-09-07 added + /// + protected void OnPreviewClick(object sender, EventArgs e) + { + try + { + if (String.IsNullOrEmpty(txtSubject.Text) || String.IsNullOrEmpty(teMessage.Text)) + { + //no subject or message + var strResult = Localization.GetString("MessageValidation", LocalResourceFile); + const ModuleMessage.ModuleMessageType msgResult = ModuleMessage.ModuleMessageType.YellowWarning; + UI.Skins.Skin.AddModuleMessage(this, strResult, msgResult); + ((CDefault) Page).ScrollToControl(Page.Form); + return; + } + + //convert links to absolute + var strBody = ConvertToAbsoluteUrls(teMessage.Text); + + if (chkReplaceTokens.Checked) + { + var objTr = new TokenReplace(); + if (cboSendMethod.SelectedItem.Value == "TO") + { + objTr.User = UserInfo; + objTr.AccessingUser = UserInfo; + objTr.DebugMessages = true; + } + lblPreviewSubject.Text = objTr.ReplaceEnvironmentTokens(txtSubject.Text); + lblPreviewBody.Text = objTr.ReplaceEnvironmentTokens(strBody); + } + else + { + lblPreviewSubject.Text = txtSubject.Text; + lblPreviewBody.Text = strBody; + } + pnlPreview.Visible = true; + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private static string ConvertToAbsoluteUrls(string content) + { + //convert links to absolute + const string pattern = "<(a|link|img|script|object).[^>]*(href|src|action)=(\\\"|'|)(?(.[^\\\"']*))(\\\"|'|)[^>]*>"; + return Regex.Replace(content, pattern, FormatUrls); + } + + #endregion + + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Newsletters/module.css b/Website/DesktopModules/Admin/Newsletters/module.css new file mode 100644 index 00000000000..8e53fc0d537 --- /dev/null +++ b/Website/DesktopModules/Admin/Newsletters/module.css @@ -0,0 +1,91 @@ +.dnnNewsletters .dnnFormItem input[type="text"], .dnnNewsletters .dnnFormItem .dnnFormInput, .dnnNewsletters .dnnFormItem textarea { + width: 50%; +} +.dnnNewsletters .dnnFormItem input[type="checkbox"] { + width: auto; + float: none; +} +.dnnNewsletters .dnnFormItem input[type="radio"] { + width: auto; +} +.dnnTextEditor label, .dnnTextEditor .dnnFormLabel, .dnnTextEditor .dnnTooltip label { + width: auto; + margin-top: 0; + font-weight: normal; + padding: 0 15px 0 5px; + text-align: right; +} +.dnnTextEditor td { + padding: 10px 0; +} +.dnnTextEditor .dnnFormItem .dnnTooltip { + width: 34%; +} +span.dnnNewsletterRadios { + display: block; + float: left; + overflow: hidden; + width: 50%; +} +span.dnnNewsletterRadios label { + width: auto; + text-align: left; + font-weight: normal; + margin-top: 0; + padding: 0 15px 0 5px; +} +.dnnFormItem.dnnNewsletterAttachment .urlControl { + float: left; +} +.dnnFormItem.dnnNewsletterAttachment .dnnFormItem { + padding: 0; + margin: 0; +} +.dnnFormItem.dnnNewsletterAttachment .dnnFormLabel { + text-align: left; + font-weight: normal; +} + +.dnnFormItem.dnnNewsletterAttachment .dnnFormMessage { + margin: 0; +} +.dnnFormItem.dnnNewsletterAttachment .dnnUrlControl .dnnFormLabel { + font-weight: normal; + width: auto; + margin-top: 0; +} +.dnnFormItem.dnnNewsletterAttachment .dnnUrlControl br { + display: none; +} + +.dnnNewsletters .dnnLangSelector { + width: 50%; + float: left; +} +.dnnLangSelector ul li { + float: left; + display: block; + width: 50%; +} +.dnnLangSelector ul li label { + width: auto; +} +.dnnRolesGrid { + width: 50%; + float: left; + margin-bottom: 18px; +} +.dnnRolesGrid > table{ + width: 100%; + border: 1px solid #ccc; +} +.dnnRolesGrid > table td{ + padding: 6px 0 6px 12px; + vertical-align: middle; +} + +.dnnRolesGrid > table tr.dnnGridHeader td{ + text-align: center; +} + +.dnnNewsletters .newMessage .dnnFormItem textarea.noResize{ resize: none;} diff --git a/Website/DesktopModules/Admin/Portals/App_LocalResources/Portals.ascx.resx b/Website/DesktopModules/Admin/Portals/App_LocalResources/Portals.ascx.resx new file mode 100644 index 00000000000..6fcaaff9949 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/App_LocalResources/Portals.ascx.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Title + + + Site Aliases + + + Users + + + Disk Space + + + Hosting Fee + + + Expires + + + Add New Site + + + Edit this Site + + + Site Management + + + <h1>About Site Management</h1><p>The Super User can manage the various parent and child Sites within the installation. This module allows you to add a new site, modify an existing site, and delete a site.</p> + + + Export Site Template + + + A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z + + + Pages + + + Site deleted successfully + + + Expired + + + Delete Expired Sites + + + Site Id + + + Delete Site + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/App_LocalResources/Signup.ascx.resx b/Website/DesktopModules/Admin/Portals/App_LocalResources/Signup.ascx.resx new file mode 100644 index 00000000000..d0922996eea --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/App_LocalResources/Signup.ascx.resx @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + There are two types of websites which can be created using this application:<br><br><li><b>Parent Websites</b> are sites which have a unique URL ( ie. www.domain.com ) associated to them. This generally involves purchasing a Domain Name from an Internet Registrar, setting the Primary/Secondary DNS entries to point to the Hosting Provider's DNS Server, and having your Hosting Provider map the Domain Name to the IP Address of your account. An example of a valid Parent Portal Name is <b>www.mydomain.com</b>. You can also use the IP Address of your site without a Domain Name ( ie. <b>65.174.86.217</b> ). If you need to have multiple Domain Names pointing to the same portal then you can seperate them with commas ( ie. <b>www.domain1.com,www.domain2.com</b> ). Do not create a Parent Portal until all of the DNS mappings are in place or else you will not be able to access your portal.<br><br><li><b>Child Portals</b> are subhosts of your Hosting Provider account. Essentially this means a directory is created on the web server which allows the site to be accessed through a URL address which includes a Parent domain name as well as the directory name ( ie. www.domain.com/directory ). A Child Portal can be converted into a Parent Portal at any time by simply modifying the Portal Alias entry.<br><br>*Please Note: Portals will be created using the default properties defined in the Host Settings module ( HostFee, HostSpace, DemoPeriod ) or in the selected template file. Once the portal is created, these properties can be modified in the Admin tab Site Settings module.<br><br> + + + Site Type: + + + There are two types of sites which can be created using this application (see the Module Help available on the Action Menu for more details). + + + Demo Site Signup allows you to create your very own Website and experiment with its advanced features {0}. At any time during or after the trial period, you can convert your Demo Site into a Registered Site by logging in as the Administrator and selecting the Renew/Extend Your Site Subscription link in the Admin tab. Registered Sites have the added benefit of using their own domain name ( ie. www.yourdomain.com ) as their Web address.<br><br><b>*Note:</b> Your Site Name must be a simple name for your site and cannot contain spaces or punctuation characters. The URL for your site will take the form of <b> {1}/sitename</b><br><br> + + + Your admin.template File Is Missing And Must be Uploaded To The Site.<br> + + + Your site template File Is Missing And Must be Uploaded To The Site.<br> + + + Site Name: + + + Enter a name for the Site + + + Site Title Is Required. + + + Title: + + + Give your site a title. + + + Description: + + + Enter a description for your site. + + + Keywords: + + + Enter some keywords separated by a comma. These are added to the Html page as MetaData and help Search Engines index your site. + + + Template: + + + Choose a template for the new Site. + + + First Name: + + + Enter your first name. + + + Last Name: + + + Enter your last name. + + + First Name Is Required. + + + Last Name Is Required. + + + Administrator User Name: + + + Enter a username for the Administrator Account for this site. + + + Password: + + + Enter a password for the Administrator Account for this site. + + + Confirm: + + + Repeat your password to confirm it was typed correctly. + + + Username Is Required. + + + Password Is Required. + + + Password Confirmation Is Required. + + + Email: + + + Enter an email address for the Administrator Account for this site. + + + Email Is Required. + + + Create Site + + + <strong>*Note:</strong> Once your Site is created, you will need to login using the Administrator information specified below. + + + {0} is not a valid Site Template File. + + + The Site Alias Must Not Contain Spaces Or Punctuation. + + + The Password Values Entered Do Not Match. + + + The Child Site Name You Specified Already Exists. Please Choose A Different Child Site Name. + + + An Error Was Encountered During The Creation Of Your Site. This May Have Been Caused By Specifying An Incorrect Password For An Existing User Account. Please Verify Your Details Before You Try Again. + + + Site Setup + + + Security Settings + + + Site Alias: + + + Enter the Alias for this Site + + + Home Directory: + + + Enter the Home Directory for this Site + + + Customize + + + Please select a template file + + + Parent + + + Child + + + Auto Generate + + + Add Site + + + There was an error sending confirmation emails - {0}. However, the website was created. <a href='{1}' {2}>Click Here To Access the new site</a> + + + Add New Site + + + The Home Folder you specified is not valid. + + + The Site Alias Name You Specified Already Exists. Please Choose A Different Site Alias. + + + There was an error sending confirmation emails. However, the website was created. <a href='{0}' {1}>Click Here To Access the new site</a> + + + Validation Results + + + Enter the answer to the above question. + + + Password Answer: + + + Enter a question to use when requesting a password. + + + Password Question: + + + Email address is invalid + + + Check this box if you want to use the current SuperUser as the Administrator for the site. If this box is unchecked you will be able to enter user credentials for the Administrator. + + + Use Current User as Administrator: + + + Site Alias is required. + + + There has a page which's name is same with your site alias, please change a site alias. + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/App_LocalResources/SiteSettings.ascx.resx b/Website/DesktopModules/Admin/Portals/App_LocalResources/SiteSettings.ascx.resx new file mode 100644 index 00000000000..84c3740e247 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/App_LocalResources/SiteSettings.ascx.resx @@ -0,0 +1,1151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Basic Settings + + + In this section, you can set up the basic settings for your site. + + + Site Details + + + Title: + + + This is the Title for your website. The text you enter will show up in the Title Bar. + + + Description: + + + Enter a description about your site here. + + + Keywords: + + + Enter some keywords for your site (separated by commas). These keywords are used by some internet search engines like Google to help index your site. + + + GUID: + + + The globally unique identifier which can be used to identify this website. + + + Site Submission + + + Search Engine: + + + Submit your site to the selected search engine for indexing. + + + Submit + + + Site Map URL: + + + Submit your Site Map to Google for better search optimization. Click Submit to get a Google Webmaster Tools account and verify your site ownership ( using the Verification option below ). Once verified, you can select the Add General Web Sitemap option on the Google Sitemaps tab, and paste the Site Map URL displayed. + + + Submit + + + Verification: + + + When signing up with Google Webmaster Tools you will need to Verify your site ownership. Choose the "Upload an HTML file" method from the Google Verification screen. Enter the filename displayed ( ie. google53c0cef435b2b81e.html ) in the Verification textbox and click Create. Return to Google and select the Verify button. + + + Create + + + Banners: + + + Indicate the type of Banner Advertising you wish to display on your site. + + + Appearance + + + Logo: + + + Depending on the skin chosen, this image will appear in the top left corner of the page. + + + Site Skin: + + + The selected skin will be applied to all pages on the site, unless overridden at the Page level. + + + Site Container: + + + The selected container will be applied to all modules on the site, unless overridden at the Page or Module level. + + + Edit Skin: + + + The selected skin will be applied to all edit mode (ctl=) pages on the site. + + + Edit Container: + + + The selected container will be applied to all edit mode (ctl=) modules on the site. + + + Body Background: + + + Depending on the skin, if selected, an image will display in the background of all pages. + + + Favicon.ico: + + + The selected favicon will be applied to all pages in the site. + + + Advanced Settings + + + In this section, you can set up more advanced settings for your site. + + + Security Settings + + + User Registration: + + + The type of user registration allowed for this site + + + None + + + Private + + + Public + + + Verified + + + Page Management + + + Splash Page: + + + The Splash Page for your site. + + + Home Page: + + + The Home Page for your site. + + + Login Page: + + + The Login Page for your site, pages with no Account Login module are not eligible. + + + User Profile Page: + + + The User Profile Page for your site. + + + Payment Settings + + + Currency: + + + The Currency used on the site. + + + Payment Processor: + + + The Payment Processor used to handle payments on the site. + + + Go To Payment Processor WebSite + + + Processor UserId: + + + The UserId for the Payment Processor. + + + Processor Password: + + + User Password for the Payment Processor. + + + Usability Settings + + + Inline Editor Enabled? + + + Select this option if you wish for inline editing to be enabled on your site. + + + Control Panel Mode: + + + Select the default Control Panel Mode for authorized users of your site. + + + View + + + Edit + + + Control Panel Visibility: + + + Select the default Control Panel Visibility for authorized users of your site. + + + Minimized + + + Maximized + + + Control Panel Security: + + + Select whether the Control Panel will be displayed for Page Editors or Module Editors. + + + Page Editors + + + Module Editors + + + Other Settings + + + Copyright: + + + If supported by the skin this Copyright text is displayed on your site. + + + Site + + + Host + + + Administrator: + + + The Administrator User for the site. + + + Default Language: + + + The Default Language for the site. + + + Site TimeZone: + + + The TimeZone for the location of the site. + + + Host Settings + + + Site Alias: + + + The Site Alias is the URL used to reach the site. + + + Expiry Date: + + + The Expiry Date is the date that the Hosting Contract for the website expires. + + + Hosting Fee: + + + The Hosting Fee is the monthly charge for hosting this site. + + + Disk Space: + + + The amount of Disk Space in MB allowed for this site (enter 0 for unlimited space). + + + Site Log History (Days): + + + The number of days of site activity that is kept for this site. + + + Available modules: + + + Here you can select which of the installed modules can be used in this site. + + + Stylesheet Editor + + + Save Style Sheet + + + Restore Default Style Sheet + + + Login Instructions + + + Registration Instructions + + + New User Signup Message + + + Are You Sure You Wish To Delete This Website? + + + Submit Site To Google + + + Home Directory: + + + The Home Directory for this site + + + Site Settings + + + Edit Site Settings + + + Upload Skin/Container + + + Upload Container + + + <h1>About Site Settings</h1><p>The Site Settings module represents the local options for your website. Local settings allow you to customize your website to meet your business requirements.</p> + + + Are You Sure You Want To Restore The Default Stylesheet (All Changes To The Current Stylesheet Will Be Lost) ? + + + Invalid fee, needs to be a currency value! + + + You can specify a maximum number of pages per website. + + + Page Quota: + + + You can specify a maximum number of users per website. + + + User Quota: + + + SSL Settings + + + SSL Enabled? + + + Specify whether an SSL Certificate has been installed for this site + + + SSL Enforced? + + + When this option is set, Pages which are not marked as Secure will not be accessible with SSL ( HTTPS ) + + + SSL URL: + + + Optionally specify a URL which will be used for secure connections for this site. This is only necessary if you do not have an SSL Certificate installed for your standard site URL. An example would be a shared hosting account where the hoster provides you with a Shared SSL URL. + + + Standard URL: + + + If an SSL URL is specified above, you will also need to specify a Standard URL for unsecure connections. + + + <br>Banner option was set by the hostingprovider, and cannot be changed + + + Add All Modules + + + Add Module + + + Available Modules + + + Selected Modules + + + Remove All Modules + + + Remove Module + + + Check this box to enable Skin Widgets for this site. + + + Enable Skin Widgets: + + + Site Aliases + + + You must provide a title for your site + + + By default a subscriber is redirected to the website home page on payment canceled. If you use the subscription feature, you can create a page with information to display to the user if the payment has been canceled. Enter the fully qualified URL of this page. + + + PayPal Cancel URL: + + + By default a subscriber is redirected to the website home page when a payment is validated. If you use the subscription feature, you can redirect the subscriber to a specific page. Enter the fully qualified URL of this page. + + + PayPal Return URL: + + + Check to use the PayPal Sandbox instead the real payment gateway. + + + Use Sandbox: + + + Check to prevent adding hidden folders or folders that start with underscore when performing folder synchronization. + + + Hide System Folders + + + The User Registration page for your site. + + + Registration Page: + + + English Name + + + Native Name + + + Select the language you wish to update settings for. You can select whether the language in the drop-down list is displayed in English or in the Native tongue. + + + Select Language: + + + The search results page for your site + + + Search Results Page: + + + This setting determines how the site responds to URLs which are defined as alias, but are not the default-alias. None - no additional action is taken, Canonical - the alias URL is handled as a Canaonical URL, Redirect - redirected to default alias. + + + SiteAlias Mapping Mode: + + + Canonical + + + Redirect + + + This setting determines how the site responds to URLs which are mapped to the site but are not currently in the list of aliases. Setting is effective in single-siteconfiguration only. Select this option to automatically map new URL. + + + Auto Add Site Alias: + + + The default alias is used in conjunction with the Mapping Mode. If the mode is set to Canonical then the default alias is used as the canonical alias for search engines. If the mode is redirect then the default alias is used as the permanent redirect. + + + Default Alias: + + + Check this box to enable the new Modal Pop-Up User Interface. + + + Enable Pop-Ups? + + + Site Marketing + + + Preview Edit Skin and Container + + + Preview Site Skin and Container + + + Expand All + + + Please select a skin and/or container to preview. + + + Invalid expiry date + + + Client Resource Management + + + Composite files are combinations of resources (JavaScript and CSS) created to reduce the number of file requests by the browser. This will significantly increase the page loading speed. + + + Enable Composite Files + + + This is the version number of the client resources on your site. As this version number changes, each user will be forced to download the new version of the files. It is recommended the version be incremented only when necessary. + + + Site Version + + + Messaging Settings + + + Throttling Interval in Minutes: + + + Number of minutes after which a User can send the next message. Zero indicates no restrictions. Not applies to Site Administrators or Host + + + Recipient Limit: + + + Maximum number of Recipients allowed in To field. Message to a Role is considered as a single Recipient . + + + Enable Profanity Filters: + + + Enabling of this setting automatically converts Profane (inappropriate) words into something equivalent. The list is managed at Host->List->ProfanityFilters or at Admin->List->ProfanityFilters. + + + Yes + + + No + + + Allow Attachments: + + + Select if attachments are allowed or not. + + + Yes + + + No + + + Send Emails: + + + Select if Emails are to be sent to Recipients for every Message and Notification. + + + The host dictates default Client Resource Management behavior, but if you choose to do so, you may configure your site to behave differently. +The host-level settings are currently set as follows: +<ul> + <li>Version: {0}</li> + <li>Enable Composite Files: {1}</li> + <li>Minify Css: {2}</li> + <li>Minify Js: {3}</li> +</ul> + {0} = Version Value (number) +{1} = Enable Composite Files Value (true or false) +{2} = Minify CSS Value (true or false) +{3} = Minify JS Value (true or false) + + + When this option is enabled, this site will use its own settings for client resources instead of the host level settings. Check this box to show the settings that are available to configure for your site. + + + Override Host Settings + + + Increment Site Version + + + <p>This action will force all site visitors to download new versions of CSS and JavaScript files. You should only do this if you are certain that the files have changed and you want those changes to be reflected on the client's browser.</p><p>Are you sure you want to increment the version number for your site?</p> + + + There was an error incrementing the Client Resource version. + + + CSS minification will reduce the size of the CSS code by using regular expressions to remove comments, whitespace and "dead css". It is only available when composite files are enabled. + + + Minify CSS + + + JS minification will reduce the size of the JavaScript code using JSMin. It is only available when composite files are enabled. + + + Minify JS + + + Debug mode is currently enabled at the application level (this is specified in the web.config file). This means that files will not be combined, even if file combining is enabled here or at the host level. + + + Important note regarding application debug mode + + + If minification settings are changed when composite files are enabled, you must first save the minification settings by clicking Update and then increment the version number. This will issue new composite files using the new minification settings. + + + Important note regarding minification settings + + + Login Settings + + + Profile Settings + + + Registration Settings + + + User Account Settings + + + Select the type of Registration Form that you want to use. + + + Registration Form Type: + + + You can define a comma-delimited list of terms that a user cannot use in their Username or Display Name. + + + Excluded Terms: + + + You can specify the list of fields you wish to include as a comma-delimited list. If this setting is used, this will take precedence over the other settings. The possible fields include Username, Email, Password, ConfirmPassword, DisplayName and all the Profile Properties. + + + Registration Fields: + + + You can optionally require your users to use a unique display name. If a user chooses a name that exists already this will suggest a modified name. + + + Require Unique Display Name: + + + Select this option to use Authentication providers during registration. Note - that not all providers support this option. + + + Use Authentication Providers: + + + Check this option to use the Email Address as a UserName. If this is true the username entry field is not shown in the regsitration form. + + + Use Email Address as Username: + + + Selecting this option will enforce the profanity filter for the UserName and DisplayName during Registration. + + + Use Profanity Filter: + + + If this is checked then each user will be required to provide a unique Email address. This means that a user cannot register multiple times with the same email address. + + + Requires Unique Email: + + + You can optionally specify a format for the users display name. The format can include tokens for dynamic substitution such as [FIRSTNAME] [LASTNAME]. If a display name format is specified, the display name will no longer be editable through the user interface. + + + Display Name Format: + + + You can modify the provided Email Validation Expression, which is used to check the validity of email addresses provided. + + + Email Address Validation: + + + Add your own Validation Expression, which is used to check the validity of the user name provided. If you change this from the default you should update the message that a user would see when they enter an invalid username using the localization editor. (SharedResources.resx - Username.RegExError) + + + User Name Validation + + + Custom + + + Standard + + + The maximum number of failed login attempts within a specified time window. + + + Maximum No of Invalid Attempts: + + + The minimum number of non-alphanumeric characters required in a password. + + + Minimum No of Non AlphaNumeric Characters: + + + The minimum number of characters required in a password + + + Minimum Password Length: + + + The time window (in minutes) for the maximim number of login attempts. + + + Invalid Attempt Window (in mins): + + + The number of days before a User must change their password (value of 0 means the password never expires) + + + Password Expiry (in days): + + + The number of days warning the user will recieve that their password is about to expire. + + + Password Expiry Reminder (in days): + + + The password format + + + Password Format: + + + Can the Administrator reset the user's password. + + + Password Reset Enabled: + + + Can the User's password be retrieved. + + + Password Retrieval Enabled: + + + A regular expression to use to validate a password. + + + Password Regular Expression: + + + Check this box to generate random passwords during registration, rather than displaying a password entry field. + + + Use Random Password: + + + Chcek this to require the registration form to display a password confirmation box. + + + Require Password Confirmation: + + + Is a User supplied Question and Answer required to modify or retrieve a password + + + Requires Question and Answer: + + + You can select a page to redirect the user to, on successful registration. + + + Redirect After Registration: + + + Indicate whether this site should use CAPTCHA for Registration. + + + Use CAPTCHA For Registration: + + + You can optionally require that a new user enters a valid profile during registration. + + + Require a valid Profile for Registration: + + + Select the default Profile Visibility Mode for the Users Profile + + + Default Profile Visibility Mode: + + + Check to display the Profile Visibility control in the Users profile + + + Display Profile Visibility: + + + You can select a page to redirect to after successful login + + + Redirect After Login: + + + You can select a page to redirect the user to, on logout. + + + Redirect After Logout: + + + Indicate whether this site should use CAPTCHA for associating Logins e.g. openid, liveid, cardspace + + + Use CAPTCHA For Associating Logins: + + + Select to add a CAPTCHA control to Password Retrieval + + + Use CAPTCHA to Retrieve Password + + + You can optionally require a user to update their Profile before be logged in, if their Profile is no longer Valid. + + + Require a valid Profile for Login: + + + The Regular Expression - {1} - entered for {0} is invalid + + + The field(s) - {0} - are not valid in the list of Registration Fields. This is either because the field is an image type or you have spelt the field name incorrectly. + + + You must, at a minimum, include the "Email" field. + + + You have selected the Require Unique Display Name option but you have not included the Display Name in the list of fields. + + + Specifies the number of times the wrong password can be entered before account is locked. Can only be changed in web.config file. + + + Max Invalid Password Attempts + + + Specifies the minimum number of special characters in the password. Can only be changed in web.config file. + + + Min Non Alphanumeric Characters + + + Specifies the minimum number of characters in the password. Can only be changed in web.config file. + + + Min Password Length + + + Specifies the length of time an account is locked after failed login attempts. Can only be changed in web.config file. + + + Password Attempt Window + + + Password will be Clear, Hashed or Encrypted. Can only be changed in web.config file. + + + Password Format + + + Specifies whether or not a user can request their password to be reset. Can only be changed in web.config file. + + + Password Reset Enabled + + + Specifies whether or not a user can request their password to be sent to their email. Can only be changed in web.config file. + + + Password Retrieval Enabled + + + The regular expression used to evaluate password complexity from the provider specified in the Provider property, Can only be changed in web.config file, by adding/altering the passwordStrengthRegularExpression node of AspNetSqlMembershipProvider. Note: this server validation is different from the password strength meter introduced in 7.1.0 which only advises on password strength, whereas this expression is a requirement for new passwords (if it is defined). + + + Password Strength Regular Expression + + + Specifies whether a question and answer system is used as part of the registration process. Can only be changed in web.config file. + + + Requires Question And Answer + + + No + + + Yes + + + Check this box to hide the login link in page. + + + Hide Login Control? + + + Membership Management + + + Enable password banned list + + + Sets whether passwords are checked against a list of banned items + + + Enable IP address checking + + + Sets whether IP address is checked during login + + + Select the character to use to concatenate URLs. + + + Character: + + + Enter the extension, including the period prefix. The default extension is .aspx. + + + Extension to use (default is .aspx): + + + Enable + + + In this section you can manage the site's aliases. + + + Manage Alias(es): + + + Check this box to force old style profile URLs to be redirected to custom URLs. + + + Redirect Old Profile URLs: + + + Check this box to verify the profile URLs entered by users. + + + Verify User Profile URLs: + + + Whether enable website administrator to receive email notification during new user registration. + + + Receive user registration notification: + + + File Version Settings + + + Set whether or not file versioning is enabled or disabled for the site + + + File Versioning enabled? + + + Set the number of file versions to keep + + + Maximum number of file versions kept + + + The number of versions kept must be in the range 5 to 25. + + + Enter a string to use to prefix vanity URLs + + + Vanity URL Prefix: + + + myVanityUrl + + + Enter a prefix for Vanity Urls + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/App_LocalResources/template.ascx.resx b/Website/DesktopModules/Admin/Portals/App_LocalResources/template.ascx.resx new file mode 100644 index 00000000000..30bd4be1e37 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/App_LocalResources/template.ascx.resx @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Export Template + + + Template File Name Is Required + + + Template File Name: + + + Site: + + + The new site template has been saved in folder: <b>{0}</b> + + + Select The SiteTo Export + + + Provide a name for the Template File to be created + + + Include Content? + + + Check this option if you want to export all module content when creating the new template + + + Template Description: + + + Enter a description for the template file + + + Template Description Is Required + + + Export Template + + + <h1>About Templates</h1><p>Allows you to export a site template to be used to build new sites.</p> + + + Return + + + Site Setup + + + You must select at least one page to be exported. + + + Check this option if you want to export all site files and folders when creating the new template. + + + Include Files? + + + If the site being exported has content localization enabled you can decide whether to create a template for a multilanguage site or just create a single language template. + + + Export As Multilingual Site? + + + Select the pages that must be exported to the template. <br /><b>NB: </b>If you intend to use the exported template to create a new site, please be sure to select all, or selected Admin pages. If no Admin pages are available in the template, the new site will not have an Admin menu. + + + Pages to export: + + + Check this option if you want to export profile property definitions when creating the new template. + + + Include Profile Properties? + + + Check this option if you want to export roles when creating the new template. + + + Include Roles? + + + Advanced Configuration + + + This option allows you to select which languages will be included in the template when exporting pages. + + + Export pages in selected languages: + + + You must select all ancestors from root level in order to include a child page. + + + Check this option to include module deploy permissions into the exported template. Please be aware that if you check this option, it may also be necessary to export Roles as well. + + + Include Module Deployment Permissions? + + + Note: the default language ({0}) will always be exported + + + Basic configuration + + + Visible to administrators only + + + Page is disabled + + + Page is visible to everyone + + + Page is hidden in menu + + + Homepage of the website + + + Visible to registered users + + + Visible to dedicated roles only + + + {0} is the default language of the selected site + + + Note: the default language is <b>{0}</b> + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/Portals.ascx.cs b/Website/DesktopModules/Admin/Portals/Portals.ascx.cs new file mode 100644 index 00000000000..bcea5004da5 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/Portals.ascx.cs @@ -0,0 +1,346 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.UI.WebControls; + +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Modules.Actions; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Security; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.UI.Skins.Controls; +using DotNetNuke.UI.Utilities; +using DotNetNuke.Web.UI.WebControls; +using Telerik.Web.UI; +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DotNetNuke.Modules.Admin.Portals +{ + + /// + /// The Portals PortalModuleBase is used to manage the portlas. + /// + public partial class Portals : PortalModuleBase + { + #region Private Members + + public Portals() + { + Filter = ""; + } + + #endregion + + #region Protected Members + + protected string Filter { get; set; } + + #endregion + + #region Private Methods + + /// + /// BindData fetches the data from the database and updates the controls + /// + private void BindData() + { + CreateLetterSearch(); + + int totalRecords = 0; + ArrayList portals; + if (Filter == Localization.GetString("Expired", LocalResourceFile)) + { + portals = PortalController.GetExpiredPortals(); + totalRecords = portals.Count; + } + else + { + portals = PortalController.GetPortalsByName(Filter + "%", grdPortals.CurrentPageIndex, grdPortals.PageSize, ref totalRecords); + } + grdPortals.VirtualItemCount = totalRecords; + grdPortals.DataSource = portals; + } + + private void CheckSecurity() + { + if (!UserInfo.IsSuperUser) + { + Response.Redirect(Globals.NavigateURL("Access Denied"), true); + } + } + + /// + /// Builds the letter filter + /// + private void CreateLetterSearch() + { + var filters = Localization.GetString("Filter.Text", LocalResourceFile); + + filters += "," + Localization.GetString("All"); + filters += "," + Localization.GetString("Expired", LocalResourceFile); + + var strAlphabet = filters.Split(','); + rptLetterSearch.DataSource = strAlphabet; + rptLetterSearch.DataBind(); + } + + /// + /// Deletes all expired portals + /// + private void DeleteExpiredPortals() + { + try + { + CheckSecurity(); + PortalController.DeleteExpiredPortals(Globals.GetAbsoluteServerPath(Request)); + + BindData(); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + #endregion + + #region Protected Methods + + /// + /// FilterURL correctly formats the Url for filter by first letter and paging + /// + protected string FilterURL(string filter, string currentPage) + { + string url; + if (!String.IsNullOrEmpty(filter)) + { + url = !String.IsNullOrEmpty(currentPage) ? Globals.NavigateURL(TabId, "", "filter=" + filter, "currentpage=" + grdPortals.CurrentPageIndex) : Globals.NavigateURL(TabId, "", "filter=" + filter); + } + else + { + url = !String.IsNullOrEmpty(currentPage) ? Globals.NavigateURL(TabId, "", "currentpage=" + grdPortals.CurrentPageIndex) : Globals.NavigateURL(TabId, ""); + } + return url; + } + + #endregion + + #region Public Methods + + /// + /// FormatExpiryDate formats the expiry date and filter out null-dates + /// + public string FormatExpiryDate(DateTime dateTime) + { + var strDate = string.Empty; + try + { + if (!Null.IsNull(dateTime)) + { + strDate = dateTime.ToShortDateString(); + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + return strDate; + } + + /// + /// FormatExpiryDate formats the format name as an a tag + /// + public string FormatPortalAliases(int portalID) + { + var str = new StringBuilder(); + try + { + var arr = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portalID).ToList(); + foreach ( PortalAliasInfo portalAliasInfo in arr) + { + var httpAlias = Globals.AddHTTP(portalAliasInfo.HTTPAlias); + var originalUrl = HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString().ToLowerInvariant(); + + httpAlias = Globals.AddPort(httpAlias, originalUrl); + + str.Append("" + portalAliasInfo.HTTPAlias + "" + "
    "); + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + return str.ToString(); + } + + #endregion + + #region Event Handlers + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + cmdDeleteExpired.Visible = PortalController.GetExpiredPortals().Count > 0; + cmdDeleteExpired.Click += cmdDeleteExpired_Click; + + foreach (GridColumn column in grdPortals.Columns) + { + if (ReferenceEquals(column.GetType(), typeof (DnnGridImageCommandColumn))) + { + //Manage Delete Confirm JS + var imageColumn = (DnnGridImageCommandColumn)column; + if (imageColumn.CommandName == "Delete") + { + imageColumn.OnClickJs = Localization.GetString("DeleteItem"); + } + + //Manage Edit Column NavigateURLFormatString + if (imageColumn.CommandName == "Edit") + { + //so first create the format string with a dummy value and then + //replace the dummy value with the FormatString place holder + var formatString = EditUrl("pid", "KEYFIELD", "Edit"); + formatString = formatString.Replace("KEYFIELD", "{0}"); + imageColumn.NavigateURLFormatString = formatString; + } + + //Localize Image Column Text + if (!String.IsNullOrEmpty(imageColumn.CommandName)) + { + imageColumn.Text = Localization.GetString(imageColumn.CommandName, LocalResourceFile); + } + } + } + } + + void cmdDeleteExpired_Click(object sender, EventArgs e) + { + DeleteExpiredPortals(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + grdPortals.DeleteCommand += OnGridDeleteCommand; + grdPortals.ItemDataBound += OnGridItemDataBound; + + try + { + + if (!UserInfo.IsSuperUser) + { + Response.Redirect(Globals.NavigateURL("Access Denied"), true); + } + if (Request.QueryString["CurrentPage"] != null) + { + grdPortals.CurrentPageIndex = Convert.ToInt32(Request.QueryString["CurrentPage"]); + } + if (Request.QueryString["filter"] != null) + { + Filter = Request.QueryString["filter"]; + } + if (Filter == Localization.GetString("All")) + { + Filter = ""; + } + if (!Page.IsPostBack) + { + BindData(); + } + } + catch (Exception exc) + { + //Module failed to load + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnGridDeleteCommand(object source, GridCommandEventArgs e) + { + try + { + var objPortalController = new PortalController(); + var portal = objPortalController.GetPortal(Int32.Parse(e.CommandArgument.ToString())); + if (portal != null) + { + var strMessage = PortalController.DeletePortal(portal, Globals.GetAbsoluteServerPath(Request)); + if (string.IsNullOrEmpty(strMessage)) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalName", portal.PortalName, PortalSettings, UserId, EventLogController.EventLogType.PORTAL_DELETED); + UI.Skins.Skin.AddModuleMessage(this, Localization.GetString("PortalDeleted", LocalResourceFile), ModuleMessage.ModuleMessageType.GreenSuccess); + } + else + { + UI.Skins.Skin.AddModuleMessage(this, strMessage, ModuleMessage.ModuleMessageType.RedError); + } + } + BindData(); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + protected void OnGridItemDataBound(object sender, GridItemEventArgs e) + { + var item = e.Item; + switch (item.ItemType) + { + case GridItemType.SelectedItem: + case GridItemType.AlternatingItem: + case GridItemType.Item: + { + var imgColumnControl = ((GridDataItem)item)["DeleteColumn"].Controls[0]; + if (imgColumnControl is ImageButton) + { + var delImage = (ImageButton) imgColumnControl; + var portal = (PortalInfo) item.DataItem; + delImage.Visible = (portal.PortalID != PortalSettings.PortalId && !PortalController.IsMemberOfPortalGroup(portal.PortalID)); + } + } + break; + } + } + + #endregion + + protected void GridNeedsDataSource(object sender, GridNeedDataSourceEventArgs e) + { + BindData(); + } + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/Signup.ascx.cs b/Website/DesktopModules/Admin/Portals/Signup.ascx.cs new file mode 100644 index 00000000000..7092a9fb36e --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/Signup.ascx.cs @@ -0,0 +1,644 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Web.UI.WebControls; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Internal; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Users; +using DotNetNuke.Framework; +using DotNetNuke.Instrumentation; +using DotNetNuke.Security.Membership; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.Services.Mail; +using DotNetNuke.UI.Skins.Controls; + +#endregion + +namespace DotNetNuke.Modules.Admin.Portals +{ + public partial class Signup : PortalModuleBase + { + private static readonly ILog Logger = LoggerSource.Instance.GetLogger(typeof (Signup)); + #region Private Properties + + private CultureDropDownTypes DisplayType { get; set; } + + #endregion + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + cmdCancel.Click += cmdCancel_Click; + cmdUpdate.Click += cmdUpdate_Click; + optType.SelectedIndexChanged += optType_SelectedIndexChanged; + btnCustomizeHomeDir.Click += btnCustomizeHomeDir_Click; + cboTemplate.SelectedIndexChanged += cboTemplate_SelectedIndexChanged; + useCurrent.CheckedChanged += useCurrent_CheckedChanged; + + //Customise the Control Title + if (IsHostMenu) + { + ModuleConfiguration.ModuleTitle = Localization.GetString("AddPortal", LocalResourceFile); + } + + jQuery.RequestDnnPluginsRegistration(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the control is loaded. + /// + /// + /// + /// + /// [cnurse] 5/10/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + try + { + //ensure portal signup is allowed + if ((!IsHostMenu || UserInfo.IsSuperUser == false) && !Host.DemoSignup) + { + Response.Redirect(Globals.NavigateURL("Access Denied"), true); + } + valEmail2.ValidationExpression = Globals.glbEmailRegEx; + + //set the async timeout same with script time out + AJAX.GetScriptManager(Page).AsyncPostBackTimeout = 900; + + if (!Page.IsPostBack) + { + BindTemplates(); + // load template description + cboTemplate_SelectedIndexChanged(null, null); + + if (UserInfo.IsSuperUser) + { + rowType.Visible = true; + useCurrentPanel.Visible = true; + useCurrent.Checked = true; + adminUserPanel.Visible = false; + + optType.SelectedValue = "P"; + } + else + { + useCurrentPanel.Visible = false; + useCurrent.Checked = false; + adminUserPanel.Visible = true; + + optType.SelectedValue = "C"; + + txtPortalAlias.Text = Globals.GetDomainName(Request) + @"/"; + rowType.Visible = false; + string strMessage = string.Format(Localization.GetString("DemoMessage", LocalResourceFile), + Host.DemoPeriod != Null.NullInteger ? " for " + Host.DemoPeriod + " days" : "", + Globals.GetDomainName(Request)); + lblInstructions.Text = strMessage; + lblInstructions.Visible = true; + btnCustomizeHomeDir.Visible = false; + } + + txtHomeDirectory.Text = @"Portals/[PortalID]"; + txtHomeDirectory.Enabled = false; + if (MembershipProviderConfig.RequiresQuestionAndAnswer) + { + questionRow.Visible = true; + answerRow.Visible = true; + } + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + class TemplateDisplayComparer : IComparer + { + public int Compare(PortalController.PortalTemplateInfo x, PortalController.PortalTemplateInfo y) + { + var cultureCompare = String.Compare(x.CultureCode, y.CultureCode, StringComparison.CurrentCulture); + if (cultureCompare == 0) + { + return String.Compare(x.Name, y.Name, StringComparison.CurrentCulture); + } + + //put blank cultures last + if(string.IsNullOrEmpty(x.CultureCode) || string.IsNullOrEmpty(y.CultureCode)) + { + cultureCompare *= -1; + } + return cultureCompare; + } + } + + void BindTemplates() + { + var templates = TestablePortalController.Instance.GetAvailablePortalTemplates(); + templates = templates.OrderBy(x => x, new TemplateDisplayComparer()).ToList(); + + foreach (var template in templates) + { + var item = CreateListItem(template); + cboTemplate.AddItem(item.Text, item.Value); + } + + SelectADefaultTemplate(templates); + + if (cboTemplate.Items.Count == 0) + { + UI.Skins.Skin.AddModuleMessage(this, "", Localization.GetString("PortalMissing", LocalResourceFile), + ModuleMessage.ModuleMessageType.RedError); + cmdUpdate.Enabled = false; + } + //cboTemplate.InsertItem(0, Localization.GetString("None_Specified"), ""); + //cboTemplate.SelectedIndex = 0; + + } + + void SelectADefaultTemplate(IList templates) + { + string currentCulture = Thread.CurrentThread.CurrentUICulture.Name; + + var defaultTemplates = + templates.Where(x => Path.GetFileNameWithoutExtension(x.TemplateFilePath) == "Default Website").ToList(); + + var match = defaultTemplates.FirstOrDefault(x => x.CultureCode == currentCulture); + if(match == null) + { + match = defaultTemplates.FirstOrDefault(x => x.CultureCode.StartsWith(currentCulture.Substring(0, 2))); + } + if(match == null) + { + match = defaultTemplates.FirstOrDefault(x => String.IsNullOrEmpty(x.CultureCode)); + } + + if(match != null) + { + cboTemplate.SelectedIndex = templates.IndexOf(match); + } + } + + ListItem CreateListItem(PortalController.PortalTemplateInfo template) + { + string text, value; + if (string.IsNullOrEmpty(template.CultureCode)) + { + text = template.Name; + value = Path.GetFileName(template.TemplateFilePath); + } + else + { + if (DisplayType == 0) + { + string _ViewType = Convert.ToString(Services.Personalization.Personalization.GetProfile("LanguageDisplayMode", "ViewType" + PortalId)); + switch (_ViewType) + { + case "NATIVE": + DisplayType = CultureDropDownTypes.NativeName; + break; + case "ENGLISH": + DisplayType = CultureDropDownTypes.EnglishName; + break; + default: + DisplayType = CultureDropDownTypes.DisplayName; + break; + } + } + + text = string.Format("{0} - {1}", template.Name, Localization.GetLocaleName(template.CultureCode, DisplayType)); + value = string.Format("{0}|{1}", Path.GetFileName(template.TemplateFilePath), template.CultureCode); + } + + return new ListItem(text, value); + } + + + /// ----------------------------------------------------------------------------- + /// + /// cmdCancel_Click runs when the Cancel button is clicked + /// + /// + /// + /// + /// [cnurse] 5/10/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + private void cmdCancel_Click(object sender, EventArgs e) + { + try + { + Response.Redirect(IsHostMenu ? Globals.NavigateURL() : Globals.GetPortalDomainName(PortalAlias.HTTPAlias, Request, true), true); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdUpdate_Click runs when the Update button is clicked + /// + /// + /// + /// + /// [cnurse] 5/10/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + private void cmdUpdate_Click(Object sender, EventArgs e) + { + if (Page.IsValid) + { + PortalController.PortalTemplateInfo template = LoadPortalTemplateInfoForSelectedItem(); + + try + { + bool blnChild; + string strPortalAlias; + string strChildPath = string.Empty; + var closePopUpStr = string.Empty; + + var objPortalController = new PortalController(); + + //check template validity + var messages = new ArrayList(); + string schemaFilename = Server.MapPath(string.Concat(AppRelativeTemplateSourceDirectory, "portal.template.xsd")); + string xmlFilename = template.TemplateFilePath; + var xval = new PortalTemplateValidator(); + if (!xval.Validate(xmlFilename, schemaFilename)) + { + UI.Skins.Skin.AddModuleMessage(this, "", String.Format(Localization.GetString("InvalidTemplate", LocalResourceFile), Path.GetFileName(template.TemplateFilePath)), ModuleMessage.ModuleMessageType.RedError); + messages.AddRange(xval.Errors); + lstResults.Visible = true; + lstResults.DataSource = messages; + lstResults.DataBind(); + validationPanel.Visible = true; + return; + } + + //Set Portal Name + txtPortalAlias.Text = txtPortalAlias.Text.ToLowerInvariant(); + txtPortalAlias.Text = txtPortalAlias.Text.Replace("http://", ""); + + //Validate Portal Name + if (!Globals.IsHostTab(PortalSettings.ActiveTab.TabID)) + { + blnChild = true; + strPortalAlias = txtPortalAlias.Text; + } + else + { + blnChild = (optType.SelectedValue == "C"); + + strPortalAlias = blnChild ? PortalController.GetPortalFolder(txtPortalAlias.Text) : txtPortalAlias.Text; + } + + string message = String.Empty; + ModuleMessage.ModuleMessageType messageType = ModuleMessage.ModuleMessageType.RedError; + if (!PortalAliasController.ValidateAlias(strPortalAlias, blnChild)) + { + message = Localization.GetString("InvalidName", LocalResourceFile); + } + + //check whether have conflict between tab path and portal alias. + var checkTabPath = string.Format("//{0}", strPortalAlias); + if (TabController.GetTabByTabPath(PortalSettings.PortalId, checkTabPath, string.Empty) != Null.NullInteger) + { + message = Localization.GetString("DuplicateWithTab", LocalResourceFile); + } + + //Validate Password + if (txtPassword.Text != txtConfirm.Text) + { + if (!String.IsNullOrEmpty(message)) message += "
    "; + message += Localization.GetString("InvalidPassword", LocalResourceFile); + } + string strServerPath = Globals.GetAbsoluteServerPath(Request); + + //Set Portal Alias for Child Portals + if (String.IsNullOrEmpty(message)) + { + if (blnChild) + { + strChildPath = strServerPath + strPortalAlias; + + if (Directory.Exists(strChildPath)) + { + message = Localization.GetString("ChildExists", LocalResourceFile); + } + else + { + if (!Globals.IsHostTab(PortalSettings.ActiveTab.TabID)) + { + strPortalAlias = Globals.GetDomainName(Request, true) + "/" + strPortalAlias; + } + else + { + strPortalAlias = txtPortalAlias.Text; + } + } + } + } + + //Get Home Directory + string homeDir = txtHomeDirectory.Text != @"Portals/[PortalID]" ? txtHomeDirectory.Text : ""; + + //Validate Home Folder + if (!string.IsNullOrEmpty(homeDir)) + { + if (string.IsNullOrEmpty(String.Format("{0}\\{1}\\", Globals.ApplicationMapPath, homeDir).Replace("/", "\\"))) + { + message = Localization.GetString("InvalidHomeFolder", LocalResourceFile); + } + if (homeDir.Contains("admin") || homeDir.Contains("DesktopModules") || homeDir.ToLowerInvariant() == "portals/") + { + message = Localization.GetString("InvalidHomeFolder", LocalResourceFile); + } + } + + //Validate Portal Alias + if (!string.IsNullOrEmpty(strPortalAlias)) + { + PortalAliasInfo portalAlias = PortalAliasController.GetPortalAliasLookup(strPortalAlias.ToLower()); + if (portalAlias != null) + { + message = Localization.GetString("DuplicatePortalAlias", LocalResourceFile); + } + } + + //Create Portal + if (String.IsNullOrEmpty(message)) + { + //Attempt to create the portal + UserInfo adminUser = new UserInfo(); + int intPortalId; + try + { + if (useCurrent.Checked) + { + adminUser = UserInfo; + intPortalId = objPortalController.CreatePortal(txtPortalName.Text, + adminUser.UserID, + txtDescription.Text, + txtKeyWords.Text, + template, + homeDir, + strPortalAlias, + strServerPath, + strChildPath, + blnChild); + } + else + { + adminUser = new UserInfo + { + FirstName = txtFirstName.Text, + LastName = txtLastName.Text, + Username = txtUsername.Text, + DisplayName = txtFirstName.Text + " " + txtLastName.Text, + Email = txtEmail.Text, + IsSuperUser = false, + Membership = + { + Approved = true, + Password = txtPassword.Text, + PasswordQuestion = txtQuestion.Text, + PasswordAnswer = txtAnswer.Text + }, + Profile = + { + FirstName = txtFirstName.Text, + LastName = txtLastName.Text + } + }; + + intPortalId = objPortalController.CreatePortal(txtPortalName.Text, + adminUser, + txtDescription.Text, + txtKeyWords.Text, + template, + homeDir, + strPortalAlias, + strServerPath, + strChildPath, + blnChild); + } + + } + catch (Exception ex) + { + intPortalId = Null.NullInteger; + message = ex.Message; + } + if (intPortalId != -1) + { + //Create a Portal Settings object for the new Portal + PortalInfo objPortal = objPortalController.GetPortal(intPortalId); + var newSettings = new PortalSettings { PortalAlias = new PortalAliasInfo { HTTPAlias = strPortalAlias }, PortalId = intPortalId, DefaultLanguage = objPortal.DefaultLanguage }; + string webUrl = Globals.AddHTTP(strPortalAlias); + try + { + if (!Globals.IsHostTab(PortalSettings.ActiveTab.TabID)) + { + message = Mail.SendMail(PortalSettings.Email, + txtEmail.Text, + PortalSettings.Email + ";" + Host.HostEmail, + Localization.GetSystemMessage(newSettings, "EMAIL_PORTAL_SIGNUP_SUBJECT", adminUser), + Localization.GetSystemMessage(newSettings, "EMAIL_PORTAL_SIGNUP_BODY", adminUser), + "", + "", + "", + "", + "", + ""); + } + else + { + message = Mail.SendMail(Host.HostEmail, + txtEmail.Text, + Host.HostEmail, + Localization.GetSystemMessage(newSettings, "EMAIL_PORTAL_SIGNUP_SUBJECT", adminUser), + Localization.GetSystemMessage(newSettings, "EMAIL_PORTAL_SIGNUP_BODY", adminUser), + "", + "", + "", + "", + "", + ""); + } + } + catch (Exception exc) + { + Logger.Error(exc); + + closePopUpStr = (PortalSettings.EnablePopUps) ? "onclick=\"return " + UrlUtils.ClosePopUp(true,webUrl,true) + "\"" : ""; + message = string.Format(Localization.GetString("UnknownSendMail.Error", LocalResourceFile), webUrl, closePopUpStr); + } + var objEventLog = new EventLogController(); + objEventLog.AddLog(objPortalController.GetPortal(intPortalId), PortalSettings, UserId, "", EventLogController.EventLogType.PORTAL_CREATED); + + // mark default language as published if content localization is enabled + bool ContentLocalizationEnabled = PortalController.GetPortalSettingAsBoolean("ContentLocalizationEnabled", PortalId, false); + if (ContentLocalizationEnabled) + { + LocaleController lc = new LocaleController(); + lc.PublishLanguage(intPortalId, objPortal.DefaultLanguage, true); + } + + //Redirect to this new site + if (message == Null.NullString) + { + webUrl = (PortalSettings.EnablePopUps) ? UrlUtils.ClosePopUp(true, webUrl, false) : webUrl; + Response.Redirect(webUrl,true); + } + else + { + closePopUpStr = (PortalSettings.EnablePopUps) ? "onclick=\"return " + UrlUtils.ClosePopUp(true, webUrl, true) + "\"" : ""; + message = string.Format(Localization.GetString("SendMail.Error", LocalResourceFile), message, webUrl, closePopUpStr); + messageType = ModuleMessage.ModuleMessageType.YellowWarning; + } + } + } + UI.Skins.Skin.AddModuleMessage(this, "", message, messageType); + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + } + + /// ----------------------------------------------------------------------------- + /// + /// optType_SelectedIndexChanged runs when the Portal Type is changed + /// + /// + /// + /// + /// [cnurse] 5/10/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + private void optType_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + txtPortalAlias.Text = optType.SelectedValue == "C" ? Globals.GetDomainName(Request) + @"/" : ""; + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void btnCustomizeHomeDir_Click(Object sender, EventArgs e) + { + try + { + if (txtHomeDirectory.Enabled) + { + btnCustomizeHomeDir.Text = Localization.GetString("Customize", LocalResourceFile); + txtHomeDirectory.Text = @"Portals/[PortalID]"; + txtHomeDirectory.Enabled = false; + } + else + { + btnCustomizeHomeDir.Text = Localization.GetString("AutoGenerate", LocalResourceFile); + txtHomeDirectory.Text = ""; + txtHomeDirectory.Enabled = true; + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void cboTemplate_SelectedIndexChanged(Object sender, EventArgs e) + { + try + { + if (cboTemplate.SelectedIndex > 0) + { + var template = LoadPortalTemplateInfoForSelectedItem(); + + if (!String.IsNullOrEmpty(template.Description)) + { + rowTemplateDescription.Visible = true; + lblTemplateDescription.Text = Server.HtmlDecode(template.Description); + } + else + { + rowTemplateDescription.Visible = false; + } + } + else + { + rowTemplateDescription.Visible = false; + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + PortalController.PortalTemplateInfo LoadPortalTemplateInfoForSelectedItem() + { + var values = cboTemplate.SelectedItem.Value.Split('|'); + + return TestablePortalController.Instance.GetPortalTemplate(Path.Combine(TestableGlobals.Instance.HostMapPath, values[0]), values.Length > 1 ? values[1] : null); + } + + private void useCurrent_CheckedChanged(object sender, EventArgs e) + { + adminUserPanel.Visible = !useCurrent.Checked; + } + + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/SiteSettings.ascx.cs b/Website/DesktopModules/Admin/Portals/SiteSettings.ascx.cs new file mode 100644 index 00000000000..fe4862ec57e --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/SiteSettings.ascx.cs @@ -0,0 +1,1361 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Web.UI; +using System.Web.UI.WebControls; + +using DotNetNuke.Common; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Data; +using DotNetNuke.Entities.Controllers; +using DotNetNuke.Entities.Host; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Portals.Internal; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Entities.Urls; +using DotNetNuke.Entities.Users; +using DotNetNuke.ExtensionPoints; +using DotNetNuke.Framework; +using DotNetNuke.Security.Membership; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.Installer; +using DotNetNuke.Services.Localization; +using DotNetNuke.Services.Log.EventLog; +using DotNetNuke.UI.Internals; +using DotNetNuke.UI.Skins; +using DotNetNuke.UI.Skins.Controls; +using DotNetNuke.UI.WebControls; +using DotNetNuke.Web.Common; +using DotNetNuke.Web.UI.WebControls; +using DotNetNuke.Web.UI.WebControls.Extensions; + +using System.Globalization; +using System.Web; + +using DotNetNuke.Web.Client; + +using DataCache = DotNetNuke.Common.Utilities.DataCache; +using Globals = DotNetNuke.Common.Globals; + +#endregion + +namespace DesktopModules.Admin.Portals +{ + /// ----------------------------------------------------------------------------- + /// + /// The SiteSettings PortalModuleBase is used to edit the main settings for a + /// portal. + /// + /// + /// + /// + /// [cnurse] 9/8/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + public partial class SiteSettings : PortalModuleBase + { + + #region Private Members + private IEnumerable advancedSettingsExtensions; + + private int _portalId = -1; + + private string SelectedCultureCode + { + get + { + return LocaleController.Instance.GetCurrentLocale(PortalId).Code; + } + } + + #endregion + + #region Public Properties + + protected string CustomRegistrationFields { get; set; } + + #endregion + + #region Private Methods + + private void BindAliases(PortalInfo portal) + { + var portalSettings = new PortalSettings(portal); + + var portalAliasMapping = portalSettings.PortalAliasMappingMode.ToString().ToUpper(); + if (String.IsNullOrEmpty(portalAliasMapping)) + { + portalAliasMapping = "CANONICALURL"; + } + portalAliasModeButtonList.Select(portalAliasMapping, false); + + //Auto Add Portal Alias + //if (Config.GetFriendlyUrlProvider() == "advanced") + //{ + // autoAddAlias.Visible = false; + //} + //else + //{ + autoAddAlias.Visible = true; + if (new PortalController().GetPortals().Count > 1) + { + chkAutoAddPortalAlias.Enabled = false; + chkAutoAddPortalAlias.Checked = false; + } + else + { + chkAutoAddPortalAlias.Checked = HostController.Instance.GetBoolean("AutoAddPortalAlias"); + } + //} + + } + + private void BindDesktopModules() + { + var dicModules = DesktopModuleController.GetDesktopModules(Null.NullInteger); + var dicPortalDesktopModules = DesktopModuleController.GetPortalDesktopModulesByPortalID(_portalId); + + ctlDesktopModules.Items.Clear(); + + foreach (var objDicModule in dicModules.Values) + { + DnnComboBoxItem comboBoxItem = new DnnComboBoxItem(objDicModule.ModuleName, objDicModule.DesktopModuleID.ToString()); + foreach (var objPortalDesktopModule in dicPortalDesktopModules.Values) + { + if (objPortalDesktopModule.DesktopModuleID == objDicModule.DesktopModuleID) + { + comboBoxItem.Checked = true; + break; + } + } + + ctlDesktopModules.Items.Add(comboBoxItem); + } + } + + private void BindDetails(PortalInfo portal) + { + if (portal != null) + { + txtPortalName.Text = portal.PortalName; + txtDescription.Text = portal.Description; + txtKeyWords.Text = portal.KeyWords; + lblGUID.Text = portal.GUID.ToString().ToUpper(); + txtFooterText.Text = portal.FooterText; + } + } + + private void BindHostSettings(PortalInfo portal) + { + if (!Null.IsNull(portal.ExpiryDate)) + { + datepickerExpiryDate.SelectedDate = portal.ExpiryDate; + } + txtHostFee.Text = portal.HostFee.ToString(); + txtHostSpace.Text = portal.HostSpace.ToString(); + txtPageQuota.Text = portal.PageQuota.ToString(); + txtUserQuota.Text = portal.UserQuota.ToString(); + if (portal.SiteLogHistory != Null.NullInteger) + { + txtSiteLogHistory.Text = portal.SiteLogHistory.ToString(); + } + } + + private void BindMarketing(PortalInfo portal) + { + //Load DocTypes + var searchEngines = new Dictionary + { + { "Google", "http://www.google.com/addurl?q=" + Globals.HTTPPOSTEncode(Globals.AddHTTP(Globals.GetDomainName(Request))) }, + { "Yahoo", "http://siteexplorer.search.yahoo.com/submit" }, + { "Microsoft", "http://search.msn.com.sg/docs/submit.aspx" } + }; + + cboSearchEngine.DataSource = searchEngines; + cboSearchEngine.DataBind(); + + var aliases = TestablePortalAliasController.Instance.GetPortalAliasesByPortalId(portal.PortalID).ToList(); + if (PortalController.IsChildPortal(portal, Globals.GetAbsoluteServerPath(Request))) + { + txtSiteMap.Text = Globals.AddHTTP(Globals.GetDomainName(Request)) + @"/SiteMap.aspx?portalid=" + portal.PortalID; + } + else + { + if (aliases.Count > 0) + { + //Get the first Alias + var objPortalAliasInfo = (PortalAliasInfo)aliases[0]; + txtSiteMap.Text = Globals.AddHTTP(objPortalAliasInfo.HTTPAlias) + @"/SiteMap.aspx"; + } + else + { + txtSiteMap.Text = Globals.AddHTTP(Globals.GetDomainName(Request)) + @"/SiteMap.aspx"; + } + } + optBanners.SelectedIndex = portal.BannerAdvertising; + if (UserInfo.IsSuperUser) + { + lblBanners.Visible = false; + } + else + { + optBanners.Enabled = portal.BannerAdvertising != 2; + lblBanners.Visible = portal.BannerAdvertising == 2; + } + + } + + private void BindMessaging(PortalInfo portal) + { + var throttlingIntervals = new Dictionary + { + { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 }, { 10, 10 } + }; + + cboMsgThrottlingInterval.DataSource = throttlingIntervals; + cboMsgThrottlingInterval.DataBind(PortalController.GetPortalSettingAsInteger("MessagingThrottlingInterval", portal.PortalID, 0).ToString()); + + var recipientLimits = new Dictionary + { + { 1, 1 }, { 5, 5 }, { 10, 10 }, { 15, 15 }, { 25, 25 }, { 50, 50 }, { 75, 75 }, { 100, 100 } + }; + + cboMsgRecipientLimit.DataSource = recipientLimits; + cboMsgRecipientLimit.DataBind(PortalController.GetPortalSettingAsInteger("MessagingRecipientLimit", portal.PortalID, 5).ToString()); + + optMsgAllowAttachments.Select(PortalController.GetPortalSetting("MessagingAllowAttachments", portal.PortalID, "NO"), false); + optMsgProfanityFilters.Select(PortalController.GetPortalSetting("MessagingProfanityFilters", portal.PortalID, "NO"), false); + optMsgSendEmail.Select(PortalController.GetPortalSetting("MessagingSendEmail", portal.PortalID, "YES"), false); + } + + private void BindPages(PortalInfo portal, string activeLanguage) + { + //Set up special page lists + List listTabs = TabController.GetPortalTabs(TabController.GetTabsBySortOrder(portal.PortalID, activeLanguage, true), + Null.NullInteger, + true, + "<" + Localization.GetString("None_Specified") + ">", + true, + false, + false, + false, + false); + + var tabs = listTabs.Where(t => t.DisableLink == false).ToList(); + + if (portal.SplashTabId > 0) + { + cboSplashTabId.SelectedPage = tabs.SingleOrDefault(t => t.TabID == portal.SplashTabId); + } + + cboSplashTabId.PortalId = portal.PortalID; + + if (portal.HomeTabId > 0) + { + cboHomeTabId.SelectedPage = tabs.SingleOrDefault(t => t.TabID == portal.HomeTabId); + } + + cboHomeTabId.PortalId = portal.PortalID; + + cboLoginTabId.DataSource = tabs.Where(t => (t.TabID > 0 && Globals.ValidateLoginTabID(t.TabID)) || t.TabID == Null.NullInteger).ToList(); + cboLoginTabId.DataBind(portal.LoginTabId.ToString(CultureInfo.InvariantCulture)); + + if (portal.RegisterTabId > 0) + { + cboRegisterTabId.SelectedPage = tabs.SingleOrDefault(t => t.TabID == portal.RegisterTabId); + } + + cboRegisterTabId.PortalId = portal.PortalID; + + cboSearchTabId.DataSource = tabs.Where(t => (t.TabID > 0 && Globals.ValidateModuleInTab(t.TabID, "Search Results")) || t.TabID == Null.NullInteger).ToList(); + cboSearchTabId.DataBind(portal.SearchTabId.ToString(CultureInfo.InvariantCulture)); + + pagesExtensionPoint.BindAction(portal.PortalID, -1, -1); + + if (portal.UserTabId > 0) + { + listTabs = TabController.GetPortalTabs(portal.PortalID, Null.NullInteger, false, true); + cboUserTabId.SelectedPage = listTabs.SingleOrDefault(t => t.TabID == portal.UserTabId); + } + + cboUserTabId.PortalId = portal.PortalID; + } + + private void BindPaymentProcessor(PortalInfo portal) + { + var listController = new ListController(); + currencyCombo.DataSource = listController.GetListEntryInfoItems("Currency", ""); + var currency = portal.Currency; + if (String.IsNullOrEmpty(currency)) + { + currency = "USD"; + } + currencyCombo.DataBind(currency); + + processorCombo.DataSource = listController.GetListEntryInfoItems("Processor", ""); + processorCombo.DataBind(); + processorCombo.InsertItem(0, "<" + Localization.GetString("None_Specified") + ">", ""); + processorCombo.Select(Host.PaymentProcessor, true); + + // use sandbox? + var usePayPalSandbox = Boolean.Parse(PortalController.GetPortalSetting("paypalsandbox", portal.PortalID, "false")); + chkPayPalSandboxEnabled.Checked = usePayPalSandbox; + processorLink.NavigateUrl = usePayPalSandbox ? "https://developer.paypal.com" : Globals.AddHTTP(processorCombo.SelectedItem.Value); + + txtUserId.Text = portal.ProcessorUserId; + + // return url after payment or on cancel + var strPayPalReturnUrl = PortalController.GetPortalSetting("paypalsubscriptionreturn", portal.PortalID, Null.NullString); + txtPayPalReturnURL.Text = strPayPalReturnUrl; + var strPayPalCancelUrl = PortalController.GetPortalSetting("paypalsubscriptioncancelreturn", portal.PortalID, Null.NullString); + txtPayPalCancelURL.Text = strPayPalCancelUrl; + } + + private void BindPortal(int portalId, string activeLanguage) + { + //Ensure localization + DataProvider.Instance().EnsureLocalizationExists(portalId, activeLanguage); + + var portalController = new PortalController(); + var portal = portalController.GetPortal(portalId, activeLanguage); + + BindDetails(portal); + + BindMarketing(portal); + + ctlLogo.FilePath = portal.LogoFile; + ctlLogo.FileFilter = Globals.glbImageFileTypes; + ctlBackground.FilePath = portal.BackgroundFile; + ctlBackground.FileFilter = Globals.glbImageFileTypes; + ctlFavIcon.FilePath = new FavIcon(portal.PortalID).GetSettingPath(); + chkSkinWidgestEnabled.Checked = PortalController.GetPortalSettingAsBoolean("EnableSkinWidgets", portalId, true); + + BindSkins(portal); + + BindPages(portal, activeLanguage); + + lblHomeDirectory.Text = portal.HomeDirectory; + + optUserRegistration.SelectedIndex = portal.UserRegistration; + chkEnableRegisterNotification.Checked = PortalController.GetPortalSettingAsBoolean("EnableRegisterNotification", portalId, true); + + BindPaymentProcessor(portal); + + BindUsability(portal); + + BindMessaging(portal); + + var roleController = new RoleController(); + cboAdministratorId.DataSource = roleController.GetUserRoles(portalId, null, portal.AdministratorRoleName); + cboAdministratorId.DataBind(portal.AdministratorId.ToString()); + + //PortalSettings for portal being edited + var portalSettings = new PortalSettings(portal); + + chkHideLoginControl.Checked = portalSettings.HideLoginControl; + + cboTimeZone.DataBind(portalSettings.TimeZone.Id); + + + if (UserInfo.IsSuperUser) + { + BindAliases(portal); + + BindSSLSettings(portal); + + BindHostSettings(portal); + + } + + BindUrlSettings(portal); + + SiteSettingAdvancedSettingExtensionControl.BindAction(portalId, TabId, ModuleId); + SiteSettingsTabExtensionControl.BindAction(portalId, TabId, ModuleId); + + LoadStyleSheet(portal); + + ctlAudit.Entity = portal; + + var overrideDefaultSettings = Boolean.Parse(PortalController.GetPortalSetting(ClientResourceSettings.OverrideDefaultSettingsKey, portalId, "false")); + chkOverrideDefaultSettings.Checked = overrideDefaultSettings; + BindClientResourceManagementUi(portal.PortalID, overrideDefaultSettings); + ManageMinificationUi(); + } + + private void BindClientResourceManagementUi(int portalId, bool overrideDefaultSettings) + { + EnableCompositeFilesRow.Visible = overrideDefaultSettings; + CrmVersionRow.Visible = overrideDefaultSettings; + MinifyCssRow.Visible = overrideDefaultSettings; + MinifyJsRow.Visible = overrideDefaultSettings; + DebugEnabledRow.Visible = HttpContext.Current.IsDebuggingEnabled; + + // set up host settings information + var hostVersion = HostController.Instance.GetInteger(ClientResourceSettings.VersionKey, 1).ToString(CultureInfo.InvariantCulture); + var hostEnableCompositeFiles = HostController.Instance.GetBoolean(ClientResourceSettings.EnableCompositeFilesKey, false); + var hostEnableMinifyCss = HostController.Instance.GetBoolean(ClientResourceSettings.MinifyCssKey, false); + var hostEnableMinifyJs = HostController.Instance.GetBoolean(ClientResourceSettings.MinifyJsKey, false); + + string yes = Localization.GetString("Yes.Text", Localization.SharedResourceFile); + string no = Localization.GetString("No.Text", Localization.SharedResourceFile); + + CrmHostSettingsSummary.Text = string.Format(LocalizeString("CrmHostSettingsSummary"), + hostVersion, // {0} = version + hostEnableCompositeFiles ? yes : no, // {1} = enable composite files + hostEnableMinifyCss ? yes : no, // {2} = minify css + hostEnableMinifyJs ? yes : no); // {3} = minify js + + // set up UI for portal-specific options + if (overrideDefaultSettings) + { + chkEnableCompositeFiles.Checked = Boolean.Parse(PortalController.GetPortalSetting(ClientResourceSettings.EnableCompositeFilesKey, portalId, "false")); + chkMinifyCss.Checked = Boolean.Parse(PortalController.GetPortalSetting(ClientResourceSettings.MinifyCssKey, portalId, "false")); + chkMinifyJs.Checked = Boolean.Parse(PortalController.GetPortalSetting(ClientResourceSettings.MinifyJsKey, portalId, "false")); + + var settingValue = PortalController.GetPortalSetting(ClientResourceSettings.VersionKey, portalId, "0"); + int version; + if (int.TryParse(settingValue, out version)) + { + if (version == 0) + { + version = 1; + PortalController.UpdatePortalSetting(portalId, ClientResourceSettings.VersionKey, "1", true); + } + CrmVersionLabel.Text = version.ToString(CultureInfo.InvariantCulture); + } + } + } + + private void BindSkins(PortalInfo portal) + { + var skins = SkinController.GetSkins(portal, SkinController.RootSkin, SkinScope.All) + .ToDictionary(skin => skin.Key, skin => skin.Value); + var containers = SkinController.GetSkins(portal, SkinController.RootContainer, SkinScope.All) + .ToDictionary(skin => skin.Key, skin => skin.Value); + portalSkinCombo.DataSource = skins; + portalSkinCombo.DataBind(PortalController.GetPortalSetting("DefaultPortalSkin", portal.PortalID, Host.DefaultPortalSkin)); + + portalContainerCombo.DataSource = containers; + portalContainerCombo.DataBind(PortalController.GetPortalSetting("DefaultPortalContainer", portal.PortalID, Host.DefaultPortalContainer)); + + editSkinCombo.DataSource = skins; + editSkinCombo.DataBind(PortalController.GetPortalSetting("DefaultAdminSkin", portal.PortalID, Host.DefaultAdminSkin)); + + editContainerCombo.DataSource = containers; + editContainerCombo.DataBind(PortalController.GetPortalSetting("DefaultAdminContainer", portal.PortalID, Host.DefaultAdminContainer)); + + if (ModuleContext.PortalSettings.UserInfo.IsSuperUser) + { + uploadSkinLink.NavigateUrl = Util.InstallURL(ModuleContext.TabId, ""); + + if (PortalSettings.EnablePopUps) + { + uploadSkinLink.Attributes.Add("onclick", "return " + UrlUtils.PopUpUrl(uploadSkinLink.NavigateUrl, this, PortalSettings, true, false)); + } + } + else + { + uploadSkinLink.Visible = false; + } + } + + private void BindSSLSettings(PortalInfo portal) + { + chkSSLEnabled.Checked = PortalController.GetPortalSettingAsBoolean("SSLEnabled", portal.PortalID, false); + chkSSLEnforced.Checked = PortalController.GetPortalSettingAsBoolean("SSLEnforced", portal.PortalID, false); + txtSSLURL.Text = PortalController.GetPortalSetting("SSLURL", portal.PortalID, Null.NullString); + txtSTDURL.Text = PortalController.GetPortalSetting("STDURL", portal.PortalID, Null.NullString); + } + + private void BindUrlSettings(PortalInfo portal) + { + if (Config.GetFriendlyUrlProvider() == "advanced") + { + var urlSettings = new DotNetNuke.Entities.Urls.FriendlyUrlSettings(portal.PortalID); + redirectOldProfileUrls.Checked = urlSettings.RedirectOldProfileUrl; + } + } + + private void BindUsability(PortalInfo portal) + { + //PortalSettings for portal being edited + var portalSettings = new PortalSettings(portal); + chkInlineEditor.Checked = portalSettings.InlineEditorEnabled; + enablePopUpsCheckBox.Checked = portalSettings.EnablePopUps; + chkHideSystemFolders.Checked = portalSettings.HideFoldersEnabled; + + var mode = (portalSettings.DefaultControlPanelMode == PortalSettings.Mode.Edit) ? "EDIT" : "VIEW"; + optControlPanelMode.Select(mode, false); + + optControlPanelVisibility.Select(PortalController.GetPortalSetting("ControlPanelVisibility", portal.PortalID, "MAX"), false); + + optControlPanelSecurity.Select(PortalController.GetPortalSetting("ControlPanelSecurity", portal.PortalID, "MODULE"), false); + } + + private void BindUserAccountSettings(int portalId) + { + if (!Page.IsPostBack) + { + var settings = UserController.GetUserSettings(portalId); + + basicRegistrationSettings.DataSource = settings; + basicRegistrationSettings.DataBind(); + + var setting = PortalController.GetPortalSettingAsInteger("Registration_RegistrationFormType", portalId, 0); + registrationFormType.Select(setting.ToString(CultureInfo.InvariantCulture)); + + standardRegistrationSettings.DataSource = settings; + standardRegistrationSettings.DataBind(); + + validationRegistrationSettings.DataSource = settings; + validationRegistrationSettings.DataBind(); + + var customRegistrationFields = PortalController.GetPortalSetting("Registration_RegistrationFields", portalId, String.Empty); + + CustomRegistrationFields = BuildCustomRegistrationFields(customRegistrationFields); + + passwordRegistrationSettings.DataSource = settings; + passwordRegistrationSettings.DataBind(); + + otherRegistrationSettings.DataSource = settings; + otherRegistrationSettings.DataBind(); + + RequiresUniqueEmailLabel.Text = MembershipProviderConfig.RequiresUniqueEmail.ToString(CultureInfo.InvariantCulture); + PasswordFormatLabel.Text = MembershipProviderConfig.PasswordFormat.ToString(); + PasswordRetrievalEnabledLabel.Text = MembershipProviderConfig.PasswordRetrievalEnabled.ToString(CultureInfo.InvariantCulture); + PasswordResetEnabledLabel.Text = MembershipProviderConfig.PasswordResetEnabled.ToString(CultureInfo.InvariantCulture); + MinPasswordLengthLabel.Text = MembershipProviderConfig.MinPasswordLength.ToString(CultureInfo.InvariantCulture); + MinNonAlphanumericCharactersLabel.Text = MembershipProviderConfig.MinNonAlphanumericCharacters.ToString(CultureInfo.InvariantCulture); + RequiresQuestionAndAnswerLabel.Text = MembershipProviderConfig.RequiresQuestionAndAnswer.ToString(CultureInfo.InvariantCulture); + PasswordStrengthRegularExpressionLabel.Text = MembershipProviderConfig.PasswordStrengthRegularExpression; + MaxInvalidPasswordAttemptsLabel.Text = MembershipProviderConfig.MaxInvalidPasswordAttempts.ToString(CultureInfo.InvariantCulture); + PasswordAttemptWindowLabel.Text = MembershipProviderConfig.PasswordAttemptWindow.ToString(CultureInfo.InvariantCulture); + + loginSettings.DataSource = settings; + loginSettings.DataBind(); + + var urlSettings = new FriendlyUrlSettings(portalId); + VanityUrlAlias.Text = String.Format("{0}/", PortalSettings.PortalAlias.HTTPAlias); + vanilyUrlPrefixTextBox.Text = urlSettings.VanityUrlPrefix; + VanityUrlExample.Text = String.Format("/{0}", LocalizeString("VanityUrlExample")); + + userVisiblity.EnumType = "DotNetNuke.Entities.Users.UserVisibilityMode, DotNetNuke"; + profileSettings.DataSource = settings; + profileSettings.DataBind(); + } + else + { + CustomRegistrationFields = BuildCustomRegistrationFields(registrationFields.Text); + } + passwordSettings.EditMode = UserInfo.IsSuperUser ? PropertyEditorMode.Edit : PropertyEditorMode.View; + passwordSettings.LocalResourceFile = LocalResourceFile; + passwordSettings.DataSource = new PasswordConfig(); + passwordSettings.DataBind(); + + } + + private string BuildCustomRegistrationFields(string customRegistrationFields) + { + if (!String.IsNullOrEmpty(customRegistrationFields)) + { + var sb = new StringBuilder(); + sb.Append("[ "); + int i = 0; + foreach (var field in customRegistrationFields.Split(',')) + { + if (i != 0) sb.Append(","); + sb.Append("{ id: \"" + field + "\", name: \"" + field + "\"}"); + i++; + } + sb.Append(" ]"); + return sb.ToString(); + } + + return "null"; + } + + /// ----------------------------------------------------------------------------- + /// + /// LoadStyleSheet loads the stylesheet + /// + /// + /// + /// + /// [cnurse] 9/8/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void LoadStyleSheet(PortalInfo portalInfo) + { + string uploadDirectory = ""; + if (portalInfo != null) + { + uploadDirectory = portalInfo.HomeDirectoryMapPath; + } + + //read CSS file + if (File.Exists(uploadDirectory + "portal.css")) + { + using (var text = File.OpenText(uploadDirectory + "portal.css")) + { + txtStyleSheet.Text = text.ReadToEnd(); + } + } + } + + #endregion + + #region Protected Methods + + /// ----------------------------------------------------------------------------- + /// + /// FormatCurrency formats the currency. + /// control. + /// + /// A formatted string + /// + /// + /// + /// [cnurse] 9/8/2004 Modified + /// + /// ----------------------------------------------------------------------------- + protected string FormatCurrency() + { + var retValue = ""; + try + { + retValue = Host.HostCurrency + " / " + Localization.GetString("Month"); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// FormatFee formats the fee. + /// control. + /// + /// A formatted string + /// + /// + /// + /// [cnurse] 9/8/2004 Modified + /// + /// ----------------------------------------------------------------------------- + protected string FormatFee(object objHostFee) + { + var retValue = ""; + try + { + retValue = objHostFee != DBNull.Value ? ((float)objHostFee).ToString("#,##0.00") : "0"; + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + return retValue; + } + + /// ----------------------------------------------------------------------------- + /// + /// IsSubscribed determines whether the portal has subscribed to the premium + /// control. + /// + /// True if Subscribed, False if not + /// + /// + /// + /// [cnurse] 9/8/2004 Modified + /// + /// ----------------------------------------------------------------------------- + protected bool IsSubscribed(int portalModuleDefinitionId) + { + try + { + return Null.IsNull(portalModuleDefinitionId) == false; + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + return false; + } + } + + /// ----------------------------------------------------------------------------- + /// + /// IsSuperUser determines whether the cuurent user is a SuperUser + /// control. + /// + /// True if SuperUser, False if not + /// + /// + /// + /// [cnurse] 10/4/2004 Added + /// + /// ----------------------------------------------------------------------------- + protected bool IsSuperUser() + { + return UserInfo.IsSuperUser; + } + + protected string AddPortalAlias(string portalAlias, int portalID) + { + if (!String.IsNullOrEmpty(portalAlias)) + { + if (portalAlias.IndexOf("://", StringComparison.Ordinal) != -1) + { + portalAlias = portalAlias.Remove(0, portalAlias.IndexOf("://", StringComparison.Ordinal) + 3); + } + var objPortalAliasController = new PortalAliasController(); + var objPortalAlias = objPortalAliasController.GetPortalAlias(portalAlias, portalID); + if (objPortalAlias == null) + { + objPortalAlias = new PortalAliasInfo { PortalID = portalID, HTTPAlias = portalAlias }; + TestablePortalAliasController.Instance.AddPortalAlias(objPortalAlias); + } + } + return portalAlias; + } + + #endregion + + #region Event Handlers + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + jQuery.RequestDnnPluginsRegistration(); + ServicesFramework.Instance.RequestAjaxAntiForgerySupport(); + + chkPayPalSandboxEnabled.CheckedChanged += OnChkPayPalSandboxChanged; + IncrementCrmVersionButton.Click += IncrementCrmVersion; + chkOverrideDefaultSettings.CheckedChanged += OverrideDefaultSettingsChanged; + chkEnableCompositeFiles.CheckedChanged += EnableCompositeFilesChanged; + + InitializeDropDownLists(); + + } + + /// + /// Initializes DropDownLists + /// + private void InitializeDropDownLists() + { + var undefinedItem = new ListItem(SharedConstants.Unspecified, String.Empty); + cboSplashTabId.UndefinedItem = undefinedItem; + cboHomeTabId.UndefinedItem = undefinedItem; + cboRegisterTabId.UndefinedItem = undefinedItem; + cboUserTabId.UndefinedItem = undefinedItem; + } + + private void EnableCompositeFilesChanged(object sender, EventArgs e) + { + ManageMinificationUi(); + } + + private void ManageMinificationUi() + { + var enableCompositeFiles = chkEnableCompositeFiles.Checked; + + if (!enableCompositeFiles) + { + chkMinifyCss.Checked = false; + chkMinifyJs.Checked = false; + } + + chkMinifyCss.Enabled = enableCompositeFiles; + chkMinifyJs.Enabled = enableCompositeFiles; + } + + private void OverrideDefaultSettingsChanged(object sender, EventArgs e) + { + BindClientResourceManagementUi(_portalId, chkOverrideDefaultSettings.Checked); + } + + private void IncrementCrmVersion(object sender, EventArgs e) + { + PortalController.IncrementCrmVersion(_portalId); + Response.Redirect(Request.RawUrl, true); // reload page + } + + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the control is loaded + /// + /// + /// + /// + /// [cnurse] 9/8/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + cmdDelete.Click += DeletePortal; + cmdRestore.Click += OnRestoreClick; + cmdSave.Click += OnSaveClick; + cmdUpdate.Click += UpdatePortal; + cmdVerification.Click += OnVerifyClick; + ctlDesktopModules.ItemChecked += ctlDesktopModules_ItemChecked; + + try + { + if ((Request.QueryString["pid"] != null) && (Globals.IsHostTab(PortalSettings.ActiveTab.TabID) || UserInfo.IsSuperUser)) + { + _portalId = Int32.Parse(Request.QueryString["pid"]); + cancelHyperLink.NavigateUrl = Globals.NavigateURL(); + } + else + { + _portalId = PortalId; + cancelHyperLink.Visible = false; + } + + ctlLogo.PortalId = ctlBackground.PortalId = ctlFavIcon.PortalId = _portalId; + + ////this needs to execute always to the client script code is registred in InvokePopupCal + + BindDesktopModules(); + + //If this is the first visit to the page, populate the site data + if (Page.IsPostBack == false) + { + BindPortal(_portalId, SelectedCultureCode); + } + + BindUserAccountSettings(_portalId); + + if (UserInfo.IsSuperUser) + { + hostSections.Visible = true; + cmdDelete.Visible = (_portalId != PortalId && !PortalController.IsMemberOfPortalGroup(_portalId)); + } + else + { + hostSections.Visible = false; + cmdDelete.Visible = false; + } + + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdDelete_Click runs when the Delete LinkButton is clicked. + /// It deletes the current portal form the Database. It can only run in Host + /// (SuperUser) mode + /// + /// + /// + /// + /// [cnurse] 9/9/2004 Modified + /// [VMasanas] 9/12/2004 Move skin deassignment to DeletePortalInfo. + /// [jmarino] 16/06/2011 Modify redirection after deletion of portal + /// + /// ----------------------------------------------------------------------------- + protected void DeletePortal(object sender, EventArgs e) + { + try + { + var objPortalController = new PortalController(); + PortalInfo objPortalInfo = objPortalController.GetPortal(_portalId); + if (objPortalInfo != null) + { + string strMessage = PortalController.DeletePortal(objPortalInfo, Globals.GetAbsoluteServerPath(Request)); + + if (string.IsNullOrEmpty(strMessage)) + { + var objEventLog = new EventLogController(); + objEventLog.AddLog("PortalName", objPortalInfo.PortalName, PortalSettings, UserId, EventLogController.EventLogType.PORTAL_DELETED); + + //Redirect to another site + if (_portalId == PortalId) + { + if (!string.IsNullOrEmpty(Host.HostURL)) + { + Response.Redirect(Globals.AddHTTP(Host.HostURL)); + } + else + { + Response.End(); + } + } + else + { + if (ViewState["UrlReferrer"] != null) + { + Response.Redirect(Convert.ToString(ViewState["UrlReferrer"]), true); + } + else + { + Response.Redirect(Globals.NavigateURL(), true); + } + } + } + else + { + Skin.AddModuleMessage(this, strMessage, ModuleMessage.ModuleMessageType.RedError); + } + } + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdRestore_Click runs when the Restore Default Stylesheet Linkbutton is clicked. + /// It reloads the default stylesheet (copies from _default Portal to current Portal) + /// + /// + /// + /// + /// [cnurse] 9/9/2004 Modified + /// + /// ----------------------------------------------------------------------------- + protected void OnRestoreClick(object sender, EventArgs e) + { + try + { + var portalController = new PortalController(); + PortalInfo portal = portalController.GetPortal(_portalId); + if (portal != null) + { + if (File.Exists(portal.HomeDirectoryMapPath + "portal.css")) + { + //delete existing style sheet + File.Delete(portal.HomeDirectoryMapPath + "portal.css"); + } + + //copy file from Host + if (File.Exists(Globals.HostMapPath + "portal.css")) + { + File.Copy(Globals.HostMapPath + "portal.css", portal.HomeDirectoryMapPath + "portal.css"); + } + } + LoadStyleSheet(portal); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdSave_Click runs when the Save Stylesheet Linkbutton is clicked. It saves + /// the edited Stylesheet + /// + /// + /// + /// + /// [cnurse] 9/9/2004 Modified + /// + /// ----------------------------------------------------------------------------- + protected void OnSaveClick(object sender, EventArgs e) + { + try + { + string strUploadDirectory = ""; + + var objPortalController = new PortalController(); + PortalInfo objPortal = objPortalController.GetPortal(_portalId); + if (objPortal != null) + { + strUploadDirectory = objPortal.HomeDirectoryMapPath; + } + + //reset attributes + if (File.Exists(strUploadDirectory + "portal.css")) + { + File.SetAttributes(strUploadDirectory + "portal.css", FileAttributes.Normal); + } + + //write CSS file + using (var writer = File.CreateText(strUploadDirectory + "portal.css")) + { + writer.WriteLine(txtStyleSheet.Text); + } + + //Clear client resource cache + var overrideSetting = PortalController.GetPortalSetting(ClientResourceSettings.OverrideDefaultSettingsKey, _portalId, "False"); + bool overridePortal; + if (bool.TryParse(overrideSetting, out overridePortal)) + { + if (overridePortal) + { + // increment this portal version only + PortalController.IncrementCrmVersion(_portalId); + } + else + { + // increment host version, do not increment other portal versions though. + HostController.Instance.IncrementCrmVersion(false); + } + } + } + catch (Exception exc) //Module failed to load + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdUpdate_Click runs when the Update LinkButton is clicked. + /// It saves the current Site Settings + /// + /// + /// + /// + /// [cnurse] 9/9/2004 Modified + /// [aprasad] 1/17/2011 New setting AutoAddPortalAlias + /// + /// ----------------------------------------------------------------------------- + protected void UpdatePortal(object sender, EventArgs e) + { + if (Page.IsValid) + { + try + { + var portalController = new PortalController(); + PortalInfo existingPortal = portalController.GetPortal(_portalId); + + string logo = String.Format("FileID={0}", ctlLogo.FileID); + string background = String.Format("FileID={0}", ctlBackground.FileID); + + //Refresh if Background or Logo file have changed + bool refreshPage = (background == existingPortal.BackgroundFile || logo == existingPortal.LogoFile); + + float hostFee = existingPortal.HostFee; + if (!String.IsNullOrEmpty(txtHostFee.Text)) + { + hostFee = float.Parse(txtHostFee.Text); + } + + int hostSpace = existingPortal.HostSpace; + if (!String.IsNullOrEmpty(txtHostSpace.Text)) + { + hostSpace = int.Parse(txtHostSpace.Text); + } + + int pageQuota = existingPortal.PageQuota; + if (!String.IsNullOrEmpty(txtPageQuota.Text)) + { + pageQuota = int.Parse(txtPageQuota.Text); + } + + int userQuota = existingPortal.UserQuota; + if (!String.IsNullOrEmpty(txtUserQuota.Text)) + { + userQuota = int.Parse(txtUserQuota.Text); + } + + int siteLogHistory = existingPortal.SiteLogHistory; + if (!String.IsNullOrEmpty(txtSiteLogHistory.Text)) + { + siteLogHistory = int.Parse(txtSiteLogHistory.Text); + } + + DateTime expiryDate = existingPortal.ExpiryDate; + if (datepickerExpiryDate.SelectedDate.HasValue) + { + expiryDate = datepickerExpiryDate.SelectedDate.Value; + } + + var intSplashTabId = cboSplashTabId.SelectedItemValueAsInt; + + var intHomeTabId = cboHomeTabId.SelectedItemValueAsInt; + + var intLoginTabId = Null.NullInteger; + if (cboLoginTabId.SelectedItem != null) + { + int.TryParse(cboLoginTabId.SelectedItem.Value, out intLoginTabId); + } + + var intRegisterTabId = cboRegisterTabId.SelectedItemValueAsInt; + + var intUserTabId = cboUserTabId.SelectedItemValueAsInt; + + var intSearchTabId = Null.NullInteger; + if (cboSearchTabId.SelectedItem != null) + { + int.TryParse(cboSearchTabId.SelectedItem.Value, out intSearchTabId); + } + + var portal = new PortalInfo + { + PortalID = _portalId, + PortalGroupID = existingPortal.PortalGroupID, + PortalName = txtPortalName.Text, + LogoFile = logo, + FooterText = txtFooterText.Text, + ExpiryDate = expiryDate, + UserRegistration = optUserRegistration.SelectedIndex, + BannerAdvertising = optBanners.SelectedIndex, + Currency = currencyCombo.SelectedItem.Value, + AdministratorId = Convert.ToInt32(cboAdministratorId.SelectedItem.Value), + HostFee = hostFee, + HostSpace = hostSpace, + PageQuota = pageQuota, + UserQuota = userQuota, + PaymentProcessor = + String.IsNullOrEmpty(processorCombo.SelectedValue) + ? "" + : processorCombo.SelectedItem.Text, + ProcessorUserId = txtUserId.Text, + ProcessorPassword = !string.IsNullOrEmpty(txtPassword.Text) ? txtPassword.Text : existingPortal.ProcessorPassword, + Description = txtDescription.Text, + KeyWords = txtKeyWords.Text, + BackgroundFile = background, + SiteLogHistory = siteLogHistory, + SplashTabId = intSplashTabId, + HomeTabId = intHomeTabId, + LoginTabId = intLoginTabId, + RegisterTabId = intRegisterTabId, + UserTabId = intUserTabId, + SearchTabId = intSearchTabId, + DefaultLanguage = existingPortal.DefaultLanguage, + HomeDirectory = lblHomeDirectory.Text, + CultureCode = SelectedCultureCode + }; + portalController.UpdatePortalInfo(portal); + + if (!refreshPage) + { + refreshPage = (PortalSettings.DefaultAdminSkin == editSkinCombo.SelectedValue) || + (PortalSettings.DefaultAdminContainer == editContainerCombo.SelectedValue); + } + + PortalController.UpdatePortalSetting(_portalId, ClientResourceSettings.OverrideDefaultSettingsKey, chkOverrideDefaultSettings.Checked.ToString(CultureInfo.InvariantCulture), false); + PortalController.UpdatePortalSetting(_portalId, ClientResourceSettings.EnableCompositeFilesKey, chkEnableCompositeFiles.Checked.ToString(CultureInfo.InvariantCulture), false); + PortalController.UpdatePortalSetting(_portalId, ClientResourceSettings.MinifyCssKey, chkMinifyCss.Checked.ToString(CultureInfo.InvariantCulture), false); + PortalController.UpdatePortalSetting(_portalId, ClientResourceSettings.MinifyJsKey, chkMinifyJs.Checked.ToString(CultureInfo.InvariantCulture), false); + + PortalController.UpdatePortalSetting(_portalId, "EnableSkinWidgets", chkSkinWidgestEnabled.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "DefaultAdminSkin", editSkinCombo.SelectedValue, false); + PortalController.UpdatePortalSetting(_portalId, "DefaultPortalSkin", portalSkinCombo.SelectedValue, false); + PortalController.UpdatePortalSetting(_portalId, "DefaultAdminContainer", editContainerCombo.SelectedValue, false); + PortalController.UpdatePortalSetting(_portalId, "DefaultPortalContainer", portalContainerCombo.SelectedValue, false); + PortalController.UpdatePortalSetting(_portalId, "EnablePopups", enablePopUpsCheckBox.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "InlineEditorEnabled", chkInlineEditor.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "HideFoldersEnabled", chkHideSystemFolders.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "ControlPanelMode", optControlPanelMode.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "ControlPanelVisibility", optControlPanelVisibility.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "ControlPanelSecurity", optControlPanelSecurity.SelectedItem.Value, false); + + PortalController.UpdatePortalSetting(_portalId, "MessagingThrottlingInterval", cboMsgThrottlingInterval.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "MessagingRecipientLimit", cboMsgRecipientLimit.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "MessagingAllowAttachments", optMsgAllowAttachments.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "MessagingProfanityFilters", optMsgProfanityFilters.SelectedItem.Value, false); + PortalController.UpdatePortalSetting(_portalId, "MessagingSendEmail", optMsgSendEmail.SelectedItem.Value, false); + + PortalController.UpdatePortalSetting(_portalId, "paypalsandbox", chkPayPalSandboxEnabled.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "paypalsubscriptionreturn", txtPayPalReturnURL.Text, false); + PortalController.UpdatePortalSetting(_portalId, "paypalsubscriptioncancelreturn", txtPayPalCancelURL.Text, false); + PortalController.UpdatePortalSetting(_portalId, "TimeZone", cboTimeZone.SelectedValue, false); + + PortalController.UpdatePortalSetting(_portalId, "HideLoginControl", chkHideLoginControl.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "EnableRegisterNotification", chkEnableRegisterNotification.Checked.ToString(), false); + + pagesExtensionPoint.SaveAction(_portalId, -1, -1); + + SiteSettingAdvancedSettingExtensionControl.SaveAction(_portalId, TabId, ModuleId); + SiteSettingsTabExtensionControl.SaveAction(_portalId, TabId, ModuleId); + + if (Config.GetFriendlyUrlProvider() == "advanced") + { + PortalController.UpdatePortalSetting(_portalId, DotNetNuke.Entities.Urls.FriendlyUrlSettings.RedirectOldProfileUrlSetting, redirectOldProfileUrls.Checked ? "Y" : "N", false); + } + + new FavIcon(_portalId).Update(ctlFavIcon.FileID); + + if (IsSuperUser()) + { + PortalController.UpdatePortalSetting(_portalId, "PortalAliasMapping", portalAliasModeButtonList.SelectedValue, false); + HostController.Instance.Update("AutoAddPortalAlias", chkAutoAddPortalAlias.Checked ? "Y" : "N", true); + + PortalController.UpdatePortalSetting(_portalId, "SSLEnabled", chkSSLEnabled.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "SSLEnforced", chkSSLEnforced.Checked.ToString(), false); + PortalController.UpdatePortalSetting(_portalId, "SSLURL", AddPortalAlias(txtSSLURL.Text, _portalId), false); + PortalController.UpdatePortalSetting(_portalId, "STDURL", AddPortalAlias(txtSTDURL.Text, _portalId), false); + } + + if(registrationFormType.SelectedValue == "1") + { + var setting = registrationFields.Text; + if (!setting.Contains("Email")) + { + Skin.AddModuleMessage(this, Localization.GetString("NoEmail", LocalResourceFile), ModuleMessage.ModuleMessageType.RedError); + return; + } + + if (!setting.Contains("DisplayName") && Convert.ToBoolean(requireUniqueDisplayName.Value)) + { + PortalController.UpdatePortalSetting(_portalId, "Registration_RegistrationFormType", "0", false); + Skin.AddModuleMessage(this, Localization.GetString("NoDisplayName", LocalResourceFile), ModuleMessage.ModuleMessageType.RedError); + return; + } + + PortalController.UpdatePortalSetting(_portalId, "Registration_RegistrationFields", setting); + } + + PortalController.UpdatePortalSetting(_portalId, "Registration_RegistrationFormType", registrationFormType.SelectedValue, false); + + foreach (DnnFormItemBase item in basicRegistrationSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + + foreach (DnnFormItemBase item in standardRegistrationSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + + foreach (DnnFormItemBase item in validationRegistrationSettings.Items) + { + try + { + var regex = new Regex(item.Value.ToString()); + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + catch + { + + string message = String.Format(Localization.GetString("InvalidRegularExpression", LocalResourceFile), + Localization.GetString(item.DataField, LocalResourceFile), item.Value); + DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, message, ModuleMessage.ModuleMessageType.RedError); + return; + } + } + + foreach (DnnFormItemBase item in passwordRegistrationSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + + foreach (DnnFormItemBase item in otherRegistrationSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + + foreach (DnnFormItemBase item in loginSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, item.Value.ToString()); + } + + PortalController.UpdatePortalSetting(_portalId, FriendlyUrlSettings.VanityUrlPrefixSetting, vanilyUrlPrefixTextBox.Text, false); + foreach (DnnFormItemBase item in profileSettings.Items) + { + PortalController.UpdatePortalSetting(_portalId, item.DataField, + item.Value.GetType().IsEnum + ? Convert.ToInt32(item.Value).ToString(CultureInfo.InvariantCulture) + : item.Value.ToString() + ); + } + + profileDefinitions.Update(); + + DataCache.ClearPortalCache(PortalId, false); + + //Redirect to this site to refresh only if admin skin changed or either of the images have changed + if (refreshPage) + { + Response.Redirect(Request.RawUrl, true); + } + + BindPortal(_portalId, SelectedCultureCode); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + finally + { + DataCache.ClearPortalCache(_portalId, false); + } + } + } + + protected void OnVerifyClick(object sender, EventArgs e) + { + if (!String.IsNullOrEmpty(txtVerification.Text) && txtVerification.Text.EndsWith(".html")) + { + if (!File.Exists(Globals.ApplicationMapPath + "\\" + txtVerification.Text)) + { + //write SiteMap verification file + using (var writer = File.CreateText(Globals.ApplicationMapPath + "\\" + txtVerification.Text)) + { + writer.WriteLine("google-site-verification: " + txtVerification.Text); + } + } + } + } + + protected void ctlDesktopModules_ItemChecked(object sender, Telerik.Web.UI.RadComboBoxItemEventArgs e) + { + if (e.Item != null) + { + if (!e.Item.Checked) // there is a bug in client side, the checked status.. + { + DesktopModuleController.AddDesktopModuleToPortal(_portalId, int.Parse(e.Item.Value), true, true); + } + else + { + DesktopModuleController.RemoveDesktopModuleFromPortal(_portalId, int.Parse(e.Item.Value), true); + } + + BindDesktopModules(); + } + } + + protected void OnChkPayPalSandboxChanged(object sender, EventArgs e) + { + processorLink.NavigateUrl = chkPayPalSandboxEnabled.Checked ? "https://developer.paypal.com" : Globals.AddHTTP(processorCombo.SelectedItem.Value); + } + + #endregion + + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/Template.ascx.cs b/Website/DesktopModules/Admin/Portals/Template.ascx.cs new file mode 100644 index 00000000000..a0edadd6c6b --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/Template.ascx.cs @@ -0,0 +1,887 @@ +#region Copyright +// +// DotNetNuke - http://www.dotnetnuke.com +// Copyright (c) 2002-2013 +// by DotNetNuke Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +// to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#endregion +#region Usings + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; + +using DotNetNuke.Common; +using DotNetNuke.Common.Lists; +using DotNetNuke.Common.Utilities; +using DotNetNuke.Entities.Modules; +using DotNetNuke.Entities.Portals; +using DotNetNuke.Entities.Profile; +using DotNetNuke.Entities.Tabs; +using DotNetNuke.Framework; +using DotNetNuke.Security.Permissions; +using DotNetNuke.Security.Roles; +using DotNetNuke.Services.Exceptions; +using DotNetNuke.Services.FileSystem; +using DotNetNuke.Services.Localization; +using DotNetNuke.UI.Skins.Controls; + +using ICSharpCode.SharpZipLib.Zip; + +using FileInfo = DotNetNuke.Services.FileSystem.FileInfo; +using System.Web.UI.WebControls; +using Telerik.Web.UI; +using System.Globalization; + +#endregion + +namespace DotNetNuke.Modules.Admin.Portals +{ + /// ----------------------------------------------------------------------------- + /// + /// The Template PortalModuleBase is used to export a Portal as a Template + /// + /// + /// + /// + /// [cnurse] 9/28/2004 Updated to reflect design changes for Help, 508 support + /// and localisation + /// + /// ----------------------------------------------------------------------------- + public partial class Template : PortalModuleBase + { + #region "Private Methods" + + /// ----------------------------------------------------------------------------- + /// + /// Serializes all Files + /// + /// Portal to serialize + /// The folder containing the files + /// + /// The serialization uses the xml attributes defined in FileInfo class. + /// + /// + /// [cnurse] 11/08/2004 Created + /// [cnurse] 05/20/2004 Extracted adding of file to zip to new FileSystemUtils method + /// + /// ----------------------------------------------------------------------------- + private void SerializeFiles(XmlWriter writer, PortalInfo objportal, string folderPath, ref ZipOutputStream zipFile) + { + var folderManager = FolderManager.Instance; + var objFolder = folderManager.GetFolder(objportal.PortalID, folderPath); + + writer.WriteStartElement("files"); + foreach (FileInfo objFile in folderManager.GetFiles(objFolder)) + { + //verify that the file exists on the file system + var filePath = objportal.HomeDirectoryMapPath + folderPath + objFile.FileName; + if (File.Exists(filePath)) + { + writer.WriteStartElement("file"); + + writer.WriteElementString("contenttype", objFile.ContentType); + writer.WriteElementString("extension", objFile.Extension); + writer.WriteElementString("filename", objFile.FileName); + writer.WriteElementString("height", objFile.Height.ToString()); + writer.WriteElementString("size", objFile.Size.ToString()); + writer.WriteElementString("width", objFile.Width.ToString()); + + writer.WriteEndElement(); + + FileSystemUtils.AddToZip(ref zipFile, filePath, objFile.FileName, folderPath); + } + } + writer.WriteEndElement(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Serializes all Folders including Permissions + /// + /// Portal to serialize + /// + /// The serialization uses the xml attributes defined in FolderInfo class. + /// + /// + /// [cnurse] 11/08/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void SerializeFolders(XmlWriter writer, PortalInfo objportal, ref ZipOutputStream zipFile) + { + //Sync db and filesystem before exporting so all required files are found + var folderManager = FolderManager.Instance; + folderManager.Synchronize(objportal.PortalID); + writer.WriteStartElement("folders"); + + foreach (FolderInfo folder in folderManager.GetFolders(objportal.PortalID)) + { + writer.WriteStartElement("folder"); + + writer.WriteElementString("folderpath", folder.FolderPath); + writer.WriteElementString("storagelocation", folder.StorageLocation.ToString()); + + //Serialize Folder Permissions + SerializeFolderPermissions(writer, objportal, folder.FolderPath); + + //Serialize files + SerializeFiles(writer, objportal, folder.FolderPath, ref zipFile); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Serializes all Folder Permissions + /// + /// Portal to serialize + /// The folder containing the files + /// + /// The serialization uses the xml attributes defined in FolderInfo class. + /// + /// + /// [cnurse] 11/08/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void SerializeFolderPermissions(XmlWriter writer, PortalInfo objportal, string folderPath) + { + FolderPermissionCollection permissions = FolderPermissionController.GetFolderPermissionsCollectionByFolder(objportal.PortalID, folderPath); + + writer.WriteStartElement("folderpermissions"); + + foreach (FolderPermissionInfo permission in permissions) + { + writer.WriteStartElement("permission"); + + writer.WriteElementString("permissioncode", permission.PermissionCode); + writer.WriteElementString("permissionkey", permission.PermissionKey); + writer.WriteElementString("rolename", permission.RoleName); + writer.WriteElementString("allowaccess", permission.AllowAccess.ToString().ToLowerInvariant()); + + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + /// ----------------------------------------------------------------------------- + /// + /// Serializes all Profile Definitions + /// + /// Portal to serialize + /// + /// The serialization uses the xml attributes defined in ProfilePropertyDefinition class. + /// + /// + /// + /// ----------------------------------------------------------------------------- + private void SerializeProfileDefinitions(XmlWriter writer, PortalInfo objportal) + { + var objListController = new ListController(); + ListEntryInfo objList; + + writer.WriteStartElement("profiledefinitions"); + foreach (ProfilePropertyDefinition objProfileProperty in + ProfileController.GetPropertyDefinitionsByPortal(objportal.PortalID, false, false)) + { + writer.WriteStartElement("profiledefinition"); + + writer.WriteElementString("propertycategory", objProfileProperty.PropertyCategory); + writer.WriteElementString("propertyname", objProfileProperty.PropertyName); + + objList = objListController.GetListEntryInfo(objProfileProperty.DataType); + if (objList == null) + { + writer.WriteElementString("datatype", "Unknown"); + } + else + { + writer.WriteElementString("datatype", objList.Value); + } + writer.WriteElementString("length", objProfileProperty.Length.ToString()); + writer.WriteElementString("defaultvisibility", Convert.ToInt32(objProfileProperty.DefaultVisibility).ToString()); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + private void SerializeTabs(XmlWriter writer, PortalInfo portal, Hashtable tabs, TabCollection tabCollection) + { + foreach (TabInfo tab in tabCollection.Values) + { + //if not deleted + if (!tab.IsDeleted) + { + XmlNode tabNode = null; + if (string.IsNullOrEmpty(tab.CultureCode) || tab.CultureCode == portal.DefaultLanguage) + { + // page in default culture and checked + if (ctlPages.CheckedNodes.Any(p => p.Value == tab.TabID.ToString(CultureInfo.InvariantCulture))) + tabNode = TabController.SerializeTab(new XmlDocument(), tabs, tab, portal, chkContent.Checked); + } + else + { + // check if default culture page is selected + TabInfo defaultTab = tab.DefaultLanguageTab; + if (defaultTab == null || ctlPages.CheckedNodes.Count(p => p.Value == defaultTab.TabID.ToString(CultureInfo.InvariantCulture)) > 0) + tabNode = TabController.SerializeTab(new XmlDocument(), tabs, tab, portal, chkContent.Checked); + } + + if (tabNode != null) + tabNode.WriteTo(writer); + } + } + + } + + /// ----------------------------------------------------------------------------- + /// + /// Serializes all portal Tabs + /// + /// + /// Portal to serialize + /// + /// Only portal tabs will be exported to the template, Admin tabs are not exported. + /// On each tab, all modules will also be exported. + /// + /// + /// [VMasanas] 23/09/2004 Created + /// + /// ----------------------------------------------------------------------------- + private void SerializeTabs(XmlWriter writer, PortalInfo portal) + { + var tabController = new TabController(); + + //supporting object to build the tab hierarchy + var tabs = new Hashtable(); + + writer.WriteStartElement("tabs"); + + if (chkMultilanguage.Checked) + { + //Process Default Language first + SerializeTabs(writer, portal, tabs, tabController.GetTabsByPortal(portal.PortalID).WithCulture(portal.DefaultLanguage, true)); + + //Process other locales + foreach (ListItem language in chkLanguages.Items) + { + if (language.Selected && language.Value != portal.DefaultLanguage) + SerializeTabs(writer, portal, tabs, tabController.GetTabsByPortal(portal.PortalID).WithCulture(language.Value, false)); + } + } + else + { + if (chkMultilanguage.Enabled) + { + // only export 1 language + string language = languageComboBox.SelectedValue; + SerializeTabs(writer, portal, tabs, tabController.GetTabsByPortal(portal.PortalID).WithCulture(language, true)); + } + else + { + SerializeTabs(writer, portal, tabs, tabController.GetTabsByPortal(portal.PortalID)); + } + } + + writer.WriteEndElement(); + } + + private void SetupSettings() + { + var portalController = new PortalController(); + var portalInfo = portalController.GetPortal(Convert.ToInt32(cboPortals.SelectedValue)); + + Dictionary settingsDictionary = PortalController.GetPortalSettingsDictionary(portalInfo.PortalID); + string setting; + bool contentLocalizable = false; + settingsDictionary.TryGetValue("ContentLocalizationEnabled", out setting); + + if (!String.IsNullOrEmpty(setting)) + { + bool.TryParse(setting, out contentLocalizable); + } + if (contentLocalizable) + { + chkMultilanguage.Enabled = true; + chkMultilanguage.Checked = true; + rowLanguages.Visible = true; + + BindLocales(portalInfo); + } + else + { + chkMultilanguage.Enabled = false; + chkMultilanguage.Checked = false; + rowLanguages.Visible = false; + rowMultiLanguage.Visible = false; + } + BindTree(portalInfo); + } + + private void BindLocales(PortalInfo portalInfo) + { + var locales = LocaleController.Instance.GetLocales(portalInfo.PortalID).Values; + MultiselectLanguages.Visible = false; + SingleSelectLanguages.Visible = false; + if (chkMultilanguage.Checked) + { + MultiselectLanguages.Visible = true; + chkLanguages.DataTextField = "EnglishName"; + chkLanguages.DataValueField = "Code"; + chkLanguages.DataSource = locales; + chkLanguages.DataBind(); + + foreach (ListItem item in chkLanguages.Items) + { + if (item.Value == portalInfo.DefaultLanguage) + { + item.Enabled = false; + item.Attributes.Add("title", string.Format(LocalizeString("DefaultLanguage"), item.Text)); + lblNote.Text = string.Format(LocalizeString("lblNote"), item.Text); + } + item.Selected = true; + } + + } + else + { + languageComboBox.BindData(true); + languageComboBox.SetLanguage(portalInfo.DefaultLanguage); + + SingleSelectLanguages.Visible = true; + lblNoteSingleLanguage.Text = string.Format(LocalizeString("lblNoteSingleLanguage"), new CultureInfo(portalInfo.DefaultLanguage).EnglishName); + + } + } + + #region Pages tree + private bool IsAdminTab(TabInfo tab) + { + var perms = tab.TabPermissions; + return perms.Cast().All(perm => perm.RoleName == PortalSettings.AdministratorRoleName || !perm.AllowAccess); + } + private bool IsRegisteredUserTab(TabInfo tab) + { + var perms = tab.TabPermissions; + return perms.Cast().Any(perm => perm.RoleName == PortalSettings.RegisteredRoleName && perm.AllowAccess); + } + private static bool IsSecuredTab(TabInfo tab) + { + var perms = tab.TabPermissions; + return perms.Cast().All(perm => perm.RoleName != "All Users" || !perm.AllowAccess); + } + + private string IconPortal + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_Portal.png"); + } + } + private string GetNodeStatusIcon(TabInfo tab) + { + if (tab.DisableLink) + { + return string.Format("\"\"", IconPageDisabled, LocalizeString("lblDisabled")); + } + + if (tab.IsVisible == false) + { + return string.Format("\"\"", IconPageHidden, LocalizeString("lblHidden")); + } + + return ""; + } + private string IconPageDisabled + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_Disabled.png"); + } + } + private string IconPageHidden + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_Hidden.png"); + } + } + private string AllUsersIcon + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_Everyone.png"); + } + } + private string AdminOnlyIcon + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_UserAdmin.png"); + } + } + private string IconHome + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_Home.png"); + } + } + private string RegisteredUsersIcon + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_User.png"); + } + } + private string SecuredIcon + { + get + { + return ResolveUrl("~/DesktopModules/Admin/Tabs/images/Icon_UserSecure.png"); + } + } + private string GetNodeIcon(TabInfo tab, out string toolTip) + { + toolTip = ""; + if (PortalSettings.HomeTabId == tab.TabID) + { + toolTip = LocalizeString("lblHome"); + return IconHome; + } + + if (IsSecuredTab(tab)) + { + if (IsAdminTab(tab)) + { + toolTip = LocalizeString("lblAdminOnly"); + return AdminOnlyIcon; + } + + if (IsRegisteredUserTab(tab)) + { + toolTip = LocalizeString("lblRegistered"); + return RegisteredUsersIcon; + } + + toolTip = LocalizeString("lblSecure"); + return SecuredIcon; + } + + toolTip = LocalizeString("lblEveryone"); + return AllUsersIcon; + } + + private void BindTree(PortalInfo portal) + { + ctlPages.Nodes.Clear(); + + var tabController = new TabController(); + var rootNode = new RadTreeNode + { + Text = PortalSettings.PortalName, + ImageUrl = IconPortal, + Value = Null.NullInteger.ToString(CultureInfo.InvariantCulture), + Expanded = true, + AllowEdit = false, + EnableContextMenu = true, + Checked = true + }; + rootNode.Attributes.Add("isPortalRoot", "True"); + + //var tabs = new TabCollection(); + List tabs; + if (chkMultilanguage.Checked) + { + tabs = TabController.GetPortalTabs(TabController.GetTabsBySortOrder(portal.PortalID, portal.DefaultLanguage, true), + Null.NullInteger, + false, + "<" + Localization.GetString("None_Specified") + ">", + true, + false, + true, + false, + false); + + //Tabs = tabController.GetTabsByPortal(portal.PortalID).WithCulture(portal.DefaultLanguage, true); + } + else + { + tabs = TabController.GetPortalTabs(TabController.GetTabsBySortOrder(portal.PortalID, languageComboBox.SelectedValue, true), + Null.NullInteger, + false, + "<" + Localization.GetString("None_Specified") + ">", + true, + false, + true, + false, + false); + //tabs = tabController.GetTabsByPortal(portal.PortalID); + } + + foreach (var tab in tabs) //.Values) + { + if (tab.Level == 0) + { + string tooltip; + var nodeIcon = GetNodeIcon(tab, out tooltip); + var node = new RadTreeNode + { + Text = string.Format("{0} {1}", tab.TabName, GetNodeStatusIcon(tab)), + Value = tab.TabID.ToString(CultureInfo.InvariantCulture), + AllowEdit = true, + ImageUrl = nodeIcon, + ToolTip = tooltip, + Checked = true + }; + + AddChildNodes(node, portal); + rootNode.Nodes.Add(node); + } + } + + ctlPages.Nodes.Add(rootNode); + } + private void AddChildNodes(RadTreeNode parentNode, PortalInfo portal) + { + parentNode.Nodes.Clear(); + + var parentId = int.Parse(parentNode.Value); + + var Tabs = new TabController().GetTabsByPortal(portal.PortalID).WithCulture(languageComboBox.SelectedValue, true).WithParentId(parentId); + + + foreach (var tab in Tabs) + { + if (tab.ParentId == parentId) + { + string tooltip; + var nodeIcon = GetNodeIcon(tab, out tooltip); + var node = new RadTreeNode + { + Text = string.Format("{0} {1}", tab.TabName, GetNodeStatusIcon(tab)), + Value = tab.TabID.ToString(CultureInfo.InvariantCulture), + AllowEdit = true, + ImageUrl = nodeIcon, + ToolTip = tooltip, + Checked = true + }; + AddChildNodes(node, portal); + parentNode.Nodes.Add(node); + } + } + } + #endregion + + #endregion + + #region "EventHandlers" + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + } + + /// ----------------------------------------------------------------------------- + /// + /// Page_Load runs when the control is loaded + /// + /// + /// + /// + /// + /// + /// [VMasanas] 23/09/2004 Created + /// + /// ----------------------------------------------------------------------------- + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + cmdCancel.Click += cmdCancel_Click; + cmdExport.Click += cmdExport_Click; + cboPortals.SelectedIndexChanged += cboPortals_SelectedIndexChanged; + try + { + if (!Page.IsPostBack) + { + var objportals = new PortalController(); + cboPortals.DataTextField = "PortalName"; + cboPortals.DataValueField = "PortalId"; + cboPortals.DataSource = objportals.GetPortals(); + cboPortals.DataBind(); + cboPortals.SelectedValue = PortalId.ToString(CultureInfo.InvariantCulture); + SetupSettings(); + } + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// cmdCancel_Click runs when the Cancel Button is clicked + /// + /// + /// + /// + /// [cnurse] 09/02/2008 Created + /// + /// ----------------------------------------------------------------------------- + private void cmdCancel_Click(object sender, EventArgs e) + { + try + { + Response.Redirect(Globals.NavigateURL(), true); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + /// ----------------------------------------------------------------------------- + /// + /// Exports the selected portal + /// + /// + /// + /// + /// Template will be saved in Portals\_default folder. + /// An extension of .template will be added to filename if not entered + /// + /// + /// [VMasanas] 23/09/2004 Created + /// [cnurse] 11/08/2004 Addition of files to template + /// [aprasad] 1/17/2011 New setting AutoAddPortalAlias + /// + /// ----------------------------------------------------------------------------- + private void cmdExport_Click(Object sender, EventArgs e) + { + try + { + // Validations + bool isValid = true; + + // Verify all ancestor pages are selected + foreach (RadTreeNode page in ctlPages.CheckedNodes) + { + if (page.ParentNode != null && page.ParentNode.Value != "-1" && !page.ParentNode.Checked) + isValid = false; + } + if (!isValid) + { + DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, LocalizeString("ErrorAncestorPages"), ModuleMessage.ModuleMessageType.RedError); + } + + if (ctlPages.CheckedNodes.Count == 0) + { + isValid = false; + DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, LocalizeString("ErrorPages"), ModuleMessage.ModuleMessageType.RedError); + } + + if (!Page.IsValid || !isValid) + { + return; + } + + ZipOutputStream resourcesFile; + var sb = new StringBuilder(); + var settings = new XmlWriterSettings(); + settings.ConformanceLevel = ConformanceLevel.Fragment; + settings.OmitXmlDeclaration = true; + settings.Indent = true; + + string filename; + filename = Globals.HostMapPath + txtTemplateName.Text; + if (!filename.EndsWith(".template")) + { + filename += ".template"; + } + XmlWriter writer = XmlWriter.Create(filename, settings); + + writer.WriteStartElement("portal"); + writer.WriteAttributeString("version", "5.0"); + + //Add template description + writer.WriteElementString("description", Server.HtmlEncode(txtDescription.Text)); + + //Serialize portal settings + PortalInfo objportal; + var objportals = new PortalController(); + objportal = objportals.GetPortal(Convert.ToInt32(cboPortals.SelectedValue)); + + writer.WriteStartElement("settings"); + + writer.WriteElementString("logofile", objportal.LogoFile); + writer.WriteElementString("footertext", objportal.FooterText); + writer.WriteElementString("userregistration", objportal.UserRegistration.ToString()); + writer.WriteElementString("banneradvertising", objportal.BannerAdvertising.ToString()); + writer.WriteElementString("defaultlanguage", objportal.DefaultLanguage); + + Dictionary settingsDictionary = PortalController.GetPortalSettingsDictionary(objportal.PortalID); + + string setting = ""; + settingsDictionary.TryGetValue("DefaultPortalSkin", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("skinsrc", setting); + } + settingsDictionary.TryGetValue("DefaultAdminSkin", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("skinsrcadmin", setting); + } + settingsDictionary.TryGetValue("DefaultPortalContainer", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("containersrc", setting); + } + settingsDictionary.TryGetValue("DefaultAdminContainer", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("containersrcadmin", setting); + } + settingsDictionary.TryGetValue("EnableSkinWidgets", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("enableskinwidgets", setting); + } + settingsDictionary.TryGetValue("portalaliasmapping", out setting); + if (!String.IsNullOrEmpty(setting)) + { + writer.WriteElementString("portalaliasmapping", setting); + } + + writer.WriteElementString("contentlocalizationenabled", chkMultilanguage.Checked.ToString()); + + settingsDictionary.TryGetValue("TimeZone", out setting); + if (!string.IsNullOrEmpty(setting)) + { + writer.WriteElementString("timezone", setting); + } + + writer.WriteElementString("hostspace", objportal.HostSpace.ToString()); + writer.WriteElementString("userquota", objportal.UserQuota.ToString()); + writer.WriteElementString("pagequota", objportal.PageQuota.ToString()); + + //End Portal Settings + writer.WriteEndElement(); + + var enabledLocales = LocaleController.Instance.GetLocales(objportal.PortalID); + if (enabledLocales.Count > 1) + { + writer.WriteStartElement("locales"); + if (chkMultilanguage.Checked) + { + foreach (ListItem item in chkLanguages.Items) + { + if (item.Selected) + { + writer.WriteElementString("locale", item.Value); + } + } + } + else + { + foreach (var enabledLocale in enabledLocales) + { + writer.WriteElementString("locale", enabledLocale.Value.Code); + } + + } + writer.WriteEndElement(); + + } + + if (chkProfile.Checked) + { + //Serialize Profile Definitions + SerializeProfileDefinitions(writer, objportal); + } + + if (chkModules.Checked) + { + //Serialize Portal Desktop Modules + DesktopModuleController.SerializePortalDesktopModules(writer, objportal.PortalID); + } + + if (chkRoles.Checked) + { + //Serialize Roles + RoleController.SerializeRoleGroups(writer, objportal.PortalID); + } + + //Serialize tabs + SerializeTabs(writer, objportal); + + if (chkFiles.Checked) + { + //Create Zip File to hold files + resourcesFile = new ZipOutputStream(File.Create(filename + ".resources")); + resourcesFile.SetLevel(6); + + //Serialize folders (while adding files to zip file) + SerializeFolders(writer, objportal, ref resourcesFile); + + //Finish and Close Zip file + resourcesFile.Finish(); + resourcesFile.Close(); + } + writer.WriteEndElement(); + + writer.Close(); + + DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, "", string.Format(Localization.GetString("ExportedMessage", LocalResourceFile), filename), ModuleMessage.ModuleMessageType.GreenSuccess); + } + catch (Exception exc) + { + Exceptions.ProcessModuleLoadException(this, exc); + } + } + + private void cboPortals_SelectedIndexChanged(object sender, EventArgs e) + { + SetupSettings(); + } + + protected void chkMultilanguage_OnCheckedChanged(object sender, EventArgs e) + { + var portalController = new PortalController(); + var portalInfo = portalController.GetPortal(Convert.ToInt32(cboPortals.SelectedValue)); + + BindLocales(portalInfo); + BindTree(portalInfo); + } + + #endregion + + + protected void languageComboBox_OnItemChanged(object sender, EventArgs e) + { + var portalController = new PortalController(); + var portalInfo = portalController.GetPortal(Convert.ToInt32(cboPortals.SelectedValue)); + BindTree(portalInfo); + } + } +} \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/module.css b/Website/DesktopModules/Admin/Portals/module.css new file mode 100644 index 00000000000..3868210255c --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/module.css @@ -0,0 +1,226 @@ +/* =========== Admin Settings Module Styling =========== */ +.dnnSiteSettings, .dnnPortalSignup, .dnnExportPortal { + width: 95%; + margin: 2em auto; +} +.dnnSiteSettings div.ssBasicSettings, .dnnSiteSettings div.ssAdvancedSettings, .dnnSiteSettings div.ssStylesheetEditor { + padding: 0; + margin-top: 1em; +} +.dnnSiteSettings .dnnFormItem input[type="text"], .dnnSiteSettings .dnnFormItem .dnnFormInput, .dnnSiteSettings .dnnFormItem textarea, .dnnPortalSignup .dnnFormItem input[type="text"], .dnnPortalSignup .dnnFormItem .dnnFormInput, .dnnPortalSignup .dnnFormItem textarea, .dnnExportPortal .dnnFormItem input[type="text"], .dnnExportPortal .dnnFormItem textarea { + width: 45%; +} +.dnnSiteSettings textarea { + min-height: 100px; +} +.dnnForm input[type="checkbox"] { + width: auto; +} +.dnnForm .dnnGrid td input[type="checkbox"] { + margin-left: 5px; + margin-right: 5px; +} +.ssbsPortalAppearance td span, .ssbsPortalAppearance td span.NormalBold { + font-weight: normal; +} +.dnnFormItem.ssbsAppearance label { + width: 20%; + text-align: right; + padding-right: 2%; + font-weight: bold; +} +.dnnFormItem.ssbsAppearance label label { + width: 100%; +} +.dnnSiteSettings .ssseContent textarea { + margin: 1em; + min-width: 52em; +} +.ssseContent ul.dnnActions { + padding: 0em 2em 3em; + border: none; + overflow: hidden; + clear: both; +} +.ssasPremiumModule td.dnnFormLabel { + width: 45%; + text-align: left; + font-weight: normal; + margin: 0; +} +.ssasPremiumModule td.dnnFormLabel + td{ + width: 8%; +} +.dnnSiteSettings div.dnnssStat { + border-top: 1px #ccc solid; + padding: 1em 0 4em; + overflow: hidden; +} +.dnnssStat p { + float: left; + padding-right: 2em; +} +p.dnnFormRequired span { + border-left: 5px #F00 solid; + padding-left: 0.5em; +} + +.dnnGrid.dnnPermissionsGrid { + float: none; +} +.dnnGrid label { + width: auto; + font-weight: normal; + text-align: left; + margin-top: 0; +} +.dnnGrid td input.dnnFormInput { + width: 42%; +} +.dnnPortalSignup .dnnFormMessage.dnnFormWarning { + max-width: 100%; +} +#dnnPortals .vLetterSearch li { + list-style-type: none; + display: inline; + padding-left: 1em; +} +.vLetterSearch { + padding-top: 10px; + padding-bottom: 10px; + text-align: center; +} +.dnnPortalSignup h2.dnnFormSectionHead a:hover { + background: #f1f1f1; +} +.dnnPortalSignup h2.dnnFormSectionHead a.dnnSectionExpanded { + background: inherit; +} +.dnnPortalSignup h2.dnnFormSectionHead a.dnnSectionExpanded:hover { + background: #f1f1f1; +} +.dnnPortalSignup .dnnFormRadioButtons input[type=radio] { + float: none; + clear: none; +} +.dnnPortalSignup .dnnFormRadioButtons label { + float: none; + display: inline; +} + +.dnnPortalSignup .dnnFormItem textarea { + min-height: 40px; +} +.crmHostSettingsSummary ul { + padding: 10px 0px 0px 40px; +} +.aspNetDisabled .dnnTooltip label span { + color: #999; +} + +fieldset .dnnForm { + width: inherit; +} +/* =========== End Admin Settings Module Styling =========== */ + +.dnnLabel{ + width: 25%; +} + +.dnnFormItem .dnnFormGroup .dnnLabel { + width: auto; + padding-top: 10px; +} + +.dnnFormItem .dnnFormGroup a.dnnFormHelp { + position: relative; +} + +.dnnFormItem .dnnFormGroup select.dnnCharacterList { + width: 150px; +} + +.dnnFormItem .dnnFormGroup .dnnExtensionsList { + width: 150px; +} + + +/* clean some form style */ +span.CommandButton input[type="image"]{ + display: none; +} + +span.CommandButton{ + border: none; +} + +a.CommandButton{ + background: whiteSmoke; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,whiteSmoke), color-stop(100%,#DFDFDF)); + -webkit-box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.4), inset 0px 1px 0px 0px rgba(255, 255, 255, 1); + box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.4), inset 0px 1px 0px 0px rgba(255, 255, 255, 1); + text-shadow: 0px 1px 0px white; + color: #555; + display: inline-block; + padding: 6px 6px; + cursor: pointer; + border: 1px solid #C2C2C2; + -webkit-border-radius: 3px; + border-radius: 3px; + color: #666; + font-weight: bold; + text-decoration: none; +} + +a[id$='IncrementCrmVersionButton']{ + margin-left: 25px; +} + +.asContentFriendlyUrls > .dnnFormItem > .dnnCheckbox { + padding-left: 10px; +} + +.ssasPortalAlias .dnnFormItem div.dnnFormGroup { + width: 68.5%; + padding-left: 0px; + padding-right: 0px; +} +.ssasPortalAlias .dnnFormItem .dnnFormGroup .dnnAliasesHeader { + clear: both; + overflow: hidden; + display: block; + margin-right: 5%; + margin-bottom: 10px; + text-align: right; +} + +.ssasPortalAlias .dnnFormItem .dnnGridItem input[type="text"], +.ssasPortalAlias .dnnFormItem .dnnGridAltItem input[type="text"]{ + margin-bottom: 0px; + width: 90%; +} + +.ssasPortalAlias .dnnFormItem .dnnFormGroup .dnnAliasesHeader .dnnSecondaryAction { + margin-bottom: 0px; +} + +.suTemplateInfo { + width:379px; display:inline-block +} + +.dnnLanguageCombo { + width: 450px; + float: left; +} + +.ssasPortalAlias .dnnGridItem .dnnLabel { + float: none; + padding-top: 0px; + padding-right: 0px; + margin-right: 0px; + +} + +#dnnSiteSettings .dnnUserVanityUrl { + width: 25%; +} diff --git a/Website/DesktopModules/Admin/Portals/portal.template.xsd b/Website/DesktopModules/Admin/Portals/portal.template.xsd new file mode 100644 index 00000000000..9f747ae8c0e --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/portal.template.xsd @@ -0,0 +1,536 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + + + + + Private + + + + + Public + + + + + Verified + + + + + + + + + None + + + + + Site + + + + + Host + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/portal.template.xsx b/Website/DesktopModules/Admin/Portals/portal.template.xsx new file mode 100644 index 00000000000..bd0da693193 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/portal.template.xsx @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/portals.ascx b/Website/DesktopModules/Admin/Portals/portals.ascx new file mode 100644 index 00000000000..4112651002b --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/portals.ascx @@ -0,0 +1,50 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.Modules.Admin.Portals.Portals" CodeFile="Portals.ascx.cs" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.UI.WebControls" Assembly="DotNetNuke.Web" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.UI.WebControls" Assembly="DotNetNuke" %> +
    +
      + + +
    • +
      +
      +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
    • +
    • +
    • +
    + +
    \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/signup.ascx b/Website/DesktopModules/Admin/Portals/signup.ascx new file mode 100644 index 00000000000..7adf726a1e0 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/signup.ascx @@ -0,0 +1,106 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.Modules.Admin.Portals.Signup" CodeFile="Signup.ascx.cs" %> +<%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %> +<%@ Register TagPrefix="dnn" TagName="SectionHead" Src="~/controls/SectionHeadControl.ascx" %> +<%@ Register TagPrefix="dnn" Assembly="DotNetNuke" Namespace="DotNetNuke.UI.WebControls"%> +<%@ Register TagPrefix="dnn" Assembly="DotNetNuke.Web" Namespace="DotNetNuke.Web.UI.WebControls"%> +
    +
    + +
    + + + + <%# Container.DataItem %> + +
    +
    + + + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
     
    +
    +
    +
    +
    + + +
    + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + + +
    +
    + + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    +
    +
      +
    • +
    • +
    +
    \ No newline at end of file diff --git a/Website/DesktopModules/Admin/Portals/sitesettings.ascx b/Website/DesktopModules/Admin/Portals/sitesettings.ascx new file mode 100644 index 00000000000..138fb0b9015 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/sitesettings.ascx @@ -0,0 +1,748 @@ +<%@ Control Inherits="DesktopModules.Admin.Portals.SiteSettings" Language="C#" + AutoEventWireup="false" EnableViewState="True" CodeFile="SiteSettings.ascx.cs" %> +<%@ Register TagPrefix="dnn" Assembly="DotNetNuke" Namespace="DotNetNuke.UI.WebControls" %> +<%@ Register TagPrefix="dnn" Assembly="DotNetNuke.Web" Namespace="DotNetNuke.Web.UI.WebControls" %> +<%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %> +<%@ Register TagPrefix="dnn" TagName="Audit" Src="~/controls/ModuleAuditControl.ascx" %> +<%@ Register TagPrefix="dnn" TagName="FilePickerUploader" Src="~/controls/filepickeruploader.ascx" %> +<%@ Register TagPrefix="dnn" TagName="ProfileDefinitions" Src="~/DesktopModules/Admin/Security/ProfileDefinitions.ascx" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %> +<%@ Register tagPrefix="dnnext" Namespace="DotNetNuke.ExtensionPoints" Assembly="DotNetNuke"%> + + + + +
    + +
      +
    • +
    • +
    • +
    • +
    +
    + +
    +

    + <%=LocalizeString("SiteDetails")%> +

    +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    + <%=LocalizeString("Marketing")%> +

    +
    + + +
    + + + +
    +
    + + + None + Site + Host + + +
    +
    +

    + + <%=LocalizeString("Appearance")%>

    +
    +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    + + +
    +
    +
    +
    + +
    +

    + <%=LocalizeString("Pages")%> +

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + +
    +
    +

    + <%=LocalizeString("SecuritySettings")%> +

    +
    +
    + + +
    +
    + + +
    +
    +

    + <%=LocalizeString("Payment")%> +

    +
    +
    + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    + <%=LocalizeString("Usability")%> +

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    +
    +

    + <%=LocalizeString("PortalAliases")%> +

    +
    +
    + + + + + + +
    +
    + + +
    +
    + +
    + +
    +
    +
    +

    + <%=LocalizeString("SSLSettings")%> +

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    + <%=LocalizeString("MessagingSettings")%> +

    +
    +
    + + +
    +
    + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    + + + + + +
    +
    +

    + <%=LocalizeString("HostSettings")%> +

    +
    +
    + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +

    + <%=LocalizeString("ClientResourceManagement")%> +

    +
    +
    + +
    +
    +
    + <%=LocalizeString("MinificationSettingsInfo.Title") %> +
    + <%= LocalizeString("MinificationSettingsInfo.Text")%> +
    +
    +
    + <%=LocalizeString("DebugEnabled.Title") %> +
    + <%= LocalizeString("DebugEnabled.Text")%> +
    +
    + + +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    + +

    + + <%=LocalizeString("Registration")%>

    +
    +
    + + + + + + + +
    +
    + + +
    +
    +
    + + + + + + + +
    +
    +
    +
    +
    + + + + + +
    +
    +
    + + + + + +
    +
    +
    + + +
    +
    + + + + + + + + +
    + + +
    +
    + + + + + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + + + + + +
    +
    +
    +

    + <%=LocalizeString("Login")%> +

    +
    +
    +
    + + + + + + + + + +
    +
    +
    +

    + <%=LocalizeString("Profile")%> +

    +
    +
    + + +
    +
    + +
    + +
    + + + +
    +
    +
    +
    +
    + + + + + + +
    + +
    +
    +
    +
    +
    +
    + +
      +
    • +
    • +
    • +
    • +
    +
    +
    +
    + + +
      +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    +
    + +
    +
    + diff --git a/Website/DesktopModules/Admin/Portals/template.ascx b/Website/DesktopModules/Admin/Portals/template.ascx new file mode 100644 index 00000000000..0868e5e55a4 --- /dev/null +++ b/Website/DesktopModules/Admin/Portals/template.ascx @@ -0,0 +1,105 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.Modules.Admin.Portals.Template" CodeFile="Template.ascx.cs" %> +<%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.UI.WebControls" Assembly="DotNetNuke.Web" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.UI.WebControls" Assembly="DotNetNuke" %> +
    +

    + + <%=LocalizeString("BasicSettings")%>

    +
    +
    + + +
    +
    + + + +
    +
    + + + +
    +
    +

    + + <%=LocalizeString("Settings")%>

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    + + +
    +

    + + +

    +
    +
    + +

    + + +

    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
      +
    • +
    • +
    • +
    • +
    +
    + diff --git a/Website/DesktopModules/Admin/ProfessionalPreview/App_LocalResources/ProfessionalPreview.ascx.resx b/Website/DesktopModules/Admin/ProfessionalPreview/App_LocalResources/ProfessionalPreview.ascx.resx new file mode 100644 index 00000000000..b07eb8ea2c4 --- /dev/null +++ b/Website/DesktopModules/Admin/ProfessionalPreview/App_LocalResources/ProfessionalPreview.ascx.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Professional Preview - License Activation + + + Professional Preview - Application Integrity + + + This feature is not available in the community edition, you can try this feature free <a href="http://www.dotnetnuke.com/Products/Professional-Edition-Trial.aspx">here</a>.<br />For the complete list of features in our commercial versions please see the list below. + + + Professional Preview - Health Monitoring + + + Professional Preview - Manage WebServices + + + Professional Preview - SearchCrawler Admin + + + Professional Preview - Security Center + + + Professional Preview - User Switcher + + \ No newline at end of file diff --git a/Website/DesktopModules/Admin/ProfessionalPreview/ProfessionalPreview.ascx b/Website/DesktopModules/Admin/ProfessionalPreview/ProfessionalPreview.ascx new file mode 100644 index 00000000000..c72c4861141 --- /dev/null +++ b/Website/DesktopModules/Admin/ProfessionalPreview/ProfessionalPreview.ascx @@ -0,0 +1,4 @@ +<%@ Control Inherits="DotNetNuke.Modules.Admin.ProfessionalPreview.ProfessionalPreview" Language="C#" AutoEventWireup="false" CodeFile="ProfessionalPreview.ascx.cs" %> + +
    +"); + menuSelector.before(mask); + mask.css({ + position: "absolute" + , width: menuSelector.outerWidth() + "px" + , height: menuSelector.outerHeight() + "px" + , left: menuSelector.position().left + "px" + , top: menuSelector.position().top + "px" + , opacity: 0 + }); + } + menuSelector.stop().fadeTo('fast', 1).show(); //Find sub and fade it in + } + + function hideAll() { + $controlPanel.find(opts.menuBorderSelector).stop().fadeTo('fast', 0, function () { //Fade to 0 opacity + if (!$.support.cssFloat) $(this).prev("iframe").remove(); + $(this).hide(); //after fading, hide it + }); + } + + //Set custom configurations + //This is the config used for showing the menue + var config = { + sensitivity: 2, // number = sensitivity threshold (must be 1 or higher) + interval: 200, // number = milliseconds for onMouseOver polling interval + over: megaHoverOver, // function = onMouseOver callback (REQUIRED) + timeout: 100, // number = milliseconds delay before onMouseOut + out: function () { return null; } // function = onMouseOut callback (REQUIRED) + }; + + //This is the config used for hiding the menue + var hideConfig = { + sensitivity: 2, // number = sensitivity threshold (must be 1 or higher) + interval: 1, // number = milliseconds for onMouseOver polling interval + over: function () { return; }, // function = onMouseOver callback (REQUIRED) + timeout: 300, // number = milliseconds delay before onMouseOut + out: function () { + if (canHide) hideAll(); + } // function = onMouseOut callback (REQUIRED) + }; + + $controlPanel.find(opts.menuBorderSelector).css({ 'opacity': '0' }); //Fade sub nav to 0 opacity on default + $controlPanel.find(opts.menuBorderSelector).find(opts.primaryActionSelector).css({ opacity: 1 }); //Compact IE7 + + $controlPanel.find(opts.menuItemSelector).mouseenter(EnableHide); //Hovering over CP will re-enable hiding. + + //hide menu if user double clicks while they are outside of the + //control panel + $(document).dblclick(function () { + if (!canHide) + hideAll(); + }); + + $controlPanel.dblclick(function (e) { + e.stopPropagation(); + }); + + //Hide menu if Esc key is pressed + $(document).keyup(function (e) { + if (e.keyCode == 27) { + hideAll(); + } + }); + + $controlPanel.find(opts.menuItemActionSelector).hoverIntent(config); //Trigger Hover intent with custom configurations + $controlPanel.find(opts.menuItemSelector).hoverIntent(hideConfig); + + //Hovering over a the dropdown will re-enable autohide + $controlPanel.find(opts.enableAutohideOnFocusSelector).focus(function () { + canHide = true; + }); + + //Hovering over a telerik dropdown will disable autohide + //need this to disable hide when the drop down expands beyond the menu body + $controlPanel.on('mouseover', opts.persistOnMouseoverSelector, function () { + canHide = false; + }); + + $controlPanel.on('click', opts.persistOnWaitForChangeSelector, function () { + forceShow = true; + canHide = false; + + setTimeout(function () { + $(document).one("click", function() { + forceShow = false; + canHide = true; + }); + }, 0); + }); + + $controlPanel.on('focus', opts.persistOnFocusSelector, function () { + canHide = false; + }); + + }); + }; + + $.fn.dnnControlPanel.defaultOptions = { + wrappingHtml: '
    ', + persistOnFocusSelector: 'select, input', + persistOnMouseoverSelector: '.rcbSlide li', + persistOnWaitForChangeSelector: '.RadComboBox', + enableAutohideOnFocusSelector: '.dnnadminmega .megaborder', + menuItemActionSelector: '.dnnadminmega > li > a', + menuItemSelector: '.dnnadminmega > li', + menuBorderSelector: '.megaborder', + primaryActionSelector: '.dnnPrimaryAction', + controlPanelWrapper: '#dnnCPWrap' + }; + + $(document).ready(function () { + $('.dnnControlPanel').dnnControlPanel(); + }); + +})(jQuery); \ No newline at end of file diff --git a/Website/Resources/ControlPanel/ControlPanel.js b/Website/Resources/ControlPanel/ControlPanel.js new file mode 100644 index 00000000000..54050edc98d --- /dev/null +++ b/Website/Resources/ControlPanel/ControlPanel.js @@ -0,0 +1 @@ +(function(a){a.fn.dnnControlPanel=function(c){var d=a.extend({},a.fn.dnnControlPanel.defaultOptions,c),b=this;return b.each(function(){var i=a(this);i.wrap(function(){return d.wrappingHtml});if(a('[id$="CommonTasksPanel"]').length>0){a('[id$="CommonTasksPanel"]').detach().appendTo("#dnnCommonTasks .megaborder")}else{a("#dnnCommonTasks").remove()}a('[id$="CurrentPagePanel"]').detach().appendTo("#dnnCurrentPage .megaborder");if(a('[id$="AdminPanel"]').length>0){a('[id$="AdminPanel"]').detach().appendTo("#dnnOtherTools .megaborder")}else{a("#dnnOtherTools").remove()}var h=a("#dnnCPWrap");if(h.hasClass("Pinned")){h.parent().css({paddingBottom:"0"})}else{a(document.body).css({marginTop:h.outerHeight()})}a.fn.dnnControlPanel.show=function(){i.parents(d.controlPanelWrapper).slideDown()};a.fn.dnnControlPanel.hide=function(){i.parents(d.controlPanelWrapper).slideUp()};var l=false,k=false,i=a(this);function m(){if(!k){l=true}}function j(){g();var o=a(this).parent().find(d.menuBorderSelector);if(!a.support.cssFloat&&o.prev("iframe").length==0){var n=a('');o.before(n);n.css({position:"absolute",width:o.outerWidth()+"px",height:o.outerHeight()+"px",left:o.position().left+"px",top:o.position().top+"px",opacity:0})}o.stop().fadeTo("fast",1).show()}function g(){i.find(d.menuBorderSelector).stop().fadeTo("fast",0,function(){if(!a.support.cssFloat){a(this).prev("iframe").remove()}a(this).hide()})}var f={sensitivity:2,interval:200,over:j,timeout:100,out:function(){return null}};var e={sensitivity:2,interval:1,over:function(){return},timeout:300,out:function(){if(l){g()}}};i.find(d.menuBorderSelector).css({opacity:"0"});i.find(d.menuBorderSelector).find(d.primaryActionSelector).css({opacity:1});i.find(d.menuItemSelector).mouseenter(m);a(document).dblclick(function(){if(!l){g()}});i.dblclick(function(n){n.stopPropagation()});a(document).keyup(function(n){if(n.keyCode==27){g()}});i.find(d.menuItemActionSelector).hoverIntent(f);i.find(d.menuItemSelector).hoverIntent(e);i.find(d.enableAutohideOnFocusSelector).focus(function(){l=true});i.on("mouseover",d.persistOnMouseoverSelector,function(){l=false});i.on("click",d.persistOnWaitForChangeSelector,function(){k=true;l=false;setTimeout(function(){a(document).one("click",function(){k=false;l=true})},0)});i.on("focus",d.persistOnFocusSelector,function(){l=false})})};a.fn.dnnControlPanel.defaultOptions={wrappingHtml:'
    ',persistOnFocusSelector:"select, input",persistOnMouseoverSelector:".rcbSlide li",persistOnWaitForChangeSelector:".RadComboBox",enableAutohideOnFocusSelector:".dnnadminmega .megaborder",menuItemActionSelector:".dnnadminmega > li > a",menuItemSelector:".dnnadminmega > li",menuBorderSelector:".megaborder",primaryActionSelector:".dnnPrimaryAction",controlPanelWrapper:"#dnnCPWrap"};a(document).ready(function(){a(".dnnControlPanel").dnnControlPanel()})})(jQuery); \ No newline at end of file diff --git a/Website/Resources/Dashboard/jquery.dashboard.js b/Website/Resources/Dashboard/jquery.dashboard.js new file mode 100644 index 00000000000..3d4393b0528 --- /dev/null +++ b/Website/Resources/Dashboard/jquery.dashboard.js @@ -0,0 +1,107 @@ +(function($) { + + $.fn.zebratable = function(options) { + + var defaults = { + tblClass: 'dashboardGrid', + altClass: 'dashboardTableAlt' + }; + var options = $.extend(defaults, options); + + return this.each(function() { + // all of our tables need common spacing - this overcomes bug + // in PropertyGrid which prevents you from assigning a CssClass in ascx file + $(this).addClass('dashboardGrid'); + + // if the table has headers then start with odd rows so we don't highlight the header + $(this).find(':has(th)').find('tr:odd').addClass('dashboardTableAlt'); + + // if the table doesn't have headers then start highlighting even rows so the top row is highlighted + $(this).find(':not(:has(th))').find('tr:even').addClass('dashboardTableAlt'); + + }); + }; + + /* + Delegate function allows us to use Selectors to handle events. + This allows us to use event bubbling and single event handler + which improves perf and makes eventhandling more dynamic. + */ + $.delegate = function(rules) { + return function(e) { + var target = jQuery(e.target); + for (var selector in rules) + if (target.is(selector)) { + return rules[selector].apply(this, jQuery.makeArray(arguments)); + } + } + } + + /* + // Simple JavaScript Templating + // John Resig - http://ejohn.org/ - MIT Licensed + */ + var _cache = {}; + + $.template = function template(str, data) { + // Figure out if we're getting a template, or if we need to + // load the template - and be sure to cache the result. + var fn = !/\W/.test(str) ? + _cache[str] = cache[str] || + template(document.getElementById(str).innerHTML) : + + // Generate a reusable function that will serve as a template + // generator (and which will be cached). + new Function("obj", + "var p=[],print=function(){p.push.apply(p,arguments);};" + + + // Introduce the data as local variables using with(){} + "with(obj){p.push('" + + + // Convert the template into pure JavaScript + str + .replace(/[\r\t\n]/g, " ") + .split("<#").join("\t") + .replace(/((^|#>)[^\t]*)'/g, "$1\r") + .replace(/\t=(.*?)#>/g, "',$1,'") + .split("\t").join("');") + .split("#>").join("p.push('") + .split("\r").join("\\'") + + "');}return p.join('');"); + + // Provide some basic currying to the user + return data ? fn(data) : fn; + }; +})(jQuery); + + +jQuery(document).ready(function($) { + var dlg = $.template('
    Empty Dialog
    ') + + $('#dashboardTabs div[id$="-tab"]').hide(); + $('#dashboardTabs div[id$="-tab"]:first').show(); + $('#tablist li:first a').addClass('active'); + $('#tablist li:first a').addClass('SubHead'); + + $('#dashboardTabs').click($.delegate({ + '.dashboardTab': function(e) { + $('#tablist li a').removeClass('active'); + $('#tablist li a').removeClass('SubHead'); + $(e.target).addClass('active'); + $(e.target).addClass('SubHead'); + var currentTab = $(e.target).attr('href'); + $('#dashboardTabs div[id$="-tab"]').hide(); + $(currentTab).show(); + return false; + } + })); + + $('#dashboardTabs div[id$="-tab"] table').zebratable(); + + // clean up to avoid memory leaks in certain versions of IE 6 + $(window).bind('unload', function() { + $('#dashboardTabs').unbind('click'); + }); + +}); + diff --git a/Website/Resources/FeedBrowser/scripts/fallback.js b/Website/Resources/FeedBrowser/scripts/fallback.js new file mode 100644 index 00000000000..baf4a7e8f11 --- /dev/null +++ b/Website/Resources/FeedBrowser/scripts/fallback.js @@ -0,0 +1,47 @@ + +// Fallback for Medium Trust when the main OPML file cannot be retrieved. +function defaultFeedBrowser() +{ + + var tabs = []; + with (DotNetNuke.UI.WebControls.FeedBrowser) + { + var tab2 = new TabInfo('Marketplace','http://marketplace.dotnetnuke.com/rssfeed.aspx?channel=marketplacesolutions&affiliateid=10054','marketplace'); + var tab2_0 = tab2.addSection(new SectionInfo('Modules', 'http://marketplace.dotnetnuke.com/feed-sp-2-10054.aspx')); + tab2_0.addCategory(new CategoryInfo('Community Management','http://marketplace.dotnetnuke.com/feed-sc-2-18-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Discussion/Forum','http://marketplace.dotnetnuke.com/feed-sc-2-19-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('Content Management','http://marketplace.dotnetnuke.com/feed-sc-2-2-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Data Management','http://marketplace.dotnetnuke.com/feed-sc-2-11-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('Document Management','http://marketplace.dotnetnuke.com/feed-sc-2-3-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('File Management','http://marketplace.dotnetnuke.com/feed-sc-2-6-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('eCommerce','http://marketplace.dotnetnuke.com/feed-sc-2-4-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Media Management','http://marketplace.dotnetnuke.com/feed-sc-2-5-10054.aspx',0)); + tab2_0.setDefaultCategory(7); + tab2_0.addCategory(new CategoryInfo('Image Viewer','http://marketplace.dotnetnuke.com/feed-sc-2-9-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('Photo Albums','http://marketplace.dotnetnuke.com/feed-sc-2-7-10054.aspx',1)); + tab2_0.addCategory(new CategoryInfo('Multi-Language','http://marketplace.dotnetnuke.com/feed-sc-2-14-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Navigation','http://marketplace.dotnetnuke.com/feed-sc-2-10-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Skinning/CSS Management','http://marketplace.dotnetnuke.com/feed-sc-2-16-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Time Management','http://marketplace.dotnetnuke.com/feed-sc-2-17-10054.aspx',0)); + tab2_0.addCategory(new CategoryInfo('Project Management','http://marketplace.dotnetnuke.com/feed-sc-2-8-10054.aspx',1)); + var tab2_1 = tab2.addSection(new SectionInfo('Skins', 'http://marketplace.dotnetnuke.com/feed-sp-3-10054.aspx')); + tab2_1.addCategory(new CategoryInfo('Skins','http://marketplace.dotnetnuke.com/feed-sc-3-20-10054.aspx',0)); + tab2_1.setDefaultCategory(0); + var tab2_2 = tab2.addSection(new SectionInfo('Other', 'http://marketplace.dotnetnuke.com/feed-sp-8-10054.aspx')); + tabs[tabs.length] = tab2; + var tab3 = new TabInfo('DotNetNuke','','dotnetnuke'); + var tab3_0 = tab3.addSection(new SectionInfo('Projects', 'http://www.dotnetnuke.com/')); + tab3_0.addCategory(new CategoryInfo('Modules','http://www.dotnetnuke.com/portals/25/SolutionsExplorer/Projects-Modules.xml',0)); + tab3_0.addCategory(new CategoryInfo('Providers','http://www.dotnetnuke.com/portals/25/SolutionsExplorer/Projects-Providers.xml',0)); + tab3_0.addCategory(new CategoryInfo('Utility','http://www.dotnetnuke.com/portals/25/SolutionsExplorer/Projects-Utility.xml',0)); + tab3_0.addCategory(new CategoryInfo('Core','http://www.dotnetnuke.com/portals/25/SolutionsExplorer/Projects-Core.xml',0)); + tab3_0.addCategory(new CategoryInfo('Component','http://www.dotnetnuke.com/portals/25/SolutionsExplorer/Projects-Component.xml',0)); + tabs[tabs.length] = tab3; + var tab4 = new TabInfo('About',''); + var tab4_0 = tab4.addSection(new SectionInfo('Solutions Explorer', 'http://www.dotnetnuke.com/portals/25/SolutionsExplorer/SolutionsExplorerInfo.xml')); + var tab4_1 = tab4.addSection(new SectionInfo('DotNetNuke Marketplace', 'http://www.dotnetnuke.com/portals/25/SolutionsExplorer/MarketplaceInfo.xml')); + var tab4_2 = tab4.addSection(new SectionInfo('Coming Soon', 'http://www.dotnetnuke.com/portals/25/SolutionsExplorer/ComingSoon.xml')); + tabs[tabs.length] = tab4; + } + return(tabs); +} diff --git a/Website/Resources/FeedBrowser/scripts/feedbrowser.js b/Website/Resources/FeedBrowser/scripts/feedbrowser.js new file mode 100644 index 00000000000..c6f7577f0c5 --- /dev/null +++ b/Website/Resources/FeedBrowser/scripts/feedbrowser.js @@ -0,0 +1,774 @@ +/* + DotNetNuke - http://www.dotnetnuke.com + Copyright (c) 2002-2013 + by DotNetNuke Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ''' ----------------------------------------------------------------------------- + ''' + ''' This script renders a simple RSS browser. The UI consists of Tabs which can + ''' contain Sections, which contain hierarchical Categories. Each Category points + ''' to an RSS feed that is displayed to the user. The overall UI is rendered from + ''' one or more OPML files. + ''' + ''' Ensure that ~/Resources/Shared/scripts/init.js is called from the browser before calling this script + ''' This script will fail if the required AJAX libraries loaded by init.js are not present. + ''' + ''' + ''' + ''' + ''' Version 1.0.0: Feb. 28, 2007, Nik Kalyani, nik.kalyani@dotnetnuke.com + ''' + ''' ----------------------------------------------------------------------------- +*/ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// F E E D B R O W S E R // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// BEGIN: Namespace management + +Type.registerNamespace("DotNetNuke.UI.WebControls.FeedBrowser"); + +// END: Namespace management + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BEGIN: Browser class // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DotNetNuke.UI.WebControls.FeedBrowser.Browser = function(instanceVarName, tabStripInstance, rssProxyUrl, elementIdPrefix, allowHtmlDescription, theme, defaultTemplate, resourcesFolderUrl) +{ + DotNetNuke.UI.WebControls.FeedBrowser.Browser.initializeBase(this, [instanceVarName, resourcesFolderUrl, theme, elementIdPrefix]); + this._control = "FeedBrowser"; + this._theme = (typeof(theme) == "undefined" ? "Platinum" : theme); + + this._tabStripInstance = tabStripInstance; + this._templates = []; + this._headers = []; + this._tabs = []; + this._defaultTemplate = (typeof(defaultTemplate) == "undefined" ? "default" : defaultTemplate); + this._rssProxyUrl = (typeof(rssProxyUrl) == "undefined" ? "http://pipes.yahoo.com/pipes/Aqn6j8_H2xG4_N_1JhOy0Q/run?_render=json&_callback=[CALLBACK]&feedUrl=" : rssProxyUrl); + this._allowHtmlDescription = (typeof(allowHtmlDescription) == "undefined" ? true : allowHtmlDescription); + + this._ignoreAsyncContent = false; + // this.opmlProxyUrl = "http://xoxotools.ning.com/outlineconvert.php?output=json&classes=&submit=Convert&callback=[CALLBACK]&url="; + +} + +DotNetNuke.UI.WebControls.FeedBrowser.Browser.prototype = +{ + getDefaultTemplate : + function() + { + return(this._defaultTemplate); + }, + + getRssProxyUrl : + function(callback) + { + return(this._rssProxyUrl.replace("[CALLBACK]", callback)); + }, + + getAllowHtmlDescription : + function() + { + return(this._allowHtmlDescription); + }, + + getTabStripInstance : + function() + { + return(this._tabStripInstance); + }, + + setDefaultTemplate : + function(defaultTemplate) + { + this._defaultTemplate = defaultTemplate; + }, + + setRssProxyUrl : + function(rssProxyUrl) + { + this._rssProxyUrl = rssProxyUrl; + }, + + setAllowHtmlDescription : + function(allowHtmlDescription) + { + this._allowHtmlDescription = allowHtmlDescription; + }, + + setTabStripInstance : + function(tabStripInstance) + { + this._tabStripInstance = tabStripInstance; + }, + + getTemplates : + function() + { + return(this._templates); + }, + + getHeaders : + function() + { + return(this._headers); + }, + + // BEGIN: render + // Renders the complete FeedBrowser user interface + render : + function() + { + // add updated templates + try + { + var fbScript = document.createElement("script"); + fbScript.type = "text/javascript"; + fbScript.src = "http://www.dotnetnuke.com/Portals/25/SolutionsExplorer/scripts/templates.js"; + document.getElementsByTagName("head")[0].appendChild(fbScript); + } + catch(e) + { + } + this.addStyleSheet(); + + var html = new Sys.StringBuilder(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append("
     
     
    "); + html.append("
    X  
    "); + html.append(""); + html.append("
      
     
    "); + + document.write(html.toString()); + + try + { + for(var t in htmlTemplates) + this._templates[t] = htmlTemplates[t]; + } + catch(e) + { + } + + try + { + for(var t in htmlHeaders) + this._headers[t] = htmlHeaders[t]; + } + catch(e) + { + } + + // templates.js should be called prior to the script reaching this point + if (!this._templates["default"]) + { + this._templates["default"] = + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
    [[title]]
    ' + + '[[description]]' + + '


    '; + } + + this._tabStripInstance.setContainerId(this._elementIdPrefix + "TabsContainer"); + this._tabStripInstance.setContext(this._instanceVarName); + this._tabStripInstance.setTheme(this._theme); + this._tabStripInstance.setResourcesFolderUrl(this._resourcesFolderUrl); + this._tabStripInstance.setClickHandler("tabClickHandler"); + this._tabStripInstance.setTabCollection(this._tabs); + this._tabStripInstance.render(); + }, + // END: render + + getTabs : + function() // returns array of TabInfo objects + { + return(this._tabs); + }, + + setTabs : + function(tabs) + { + this._tabs = tabs; + }, + + getTabsList : + function() // returns tab labels as a comma-separated list + { + var list = ""; + for(var t=0; t < this._tabs.length; t++) + list += (list == "" ? "" : ",") + this._tabs[t].label; + return(list); + }, + + addTab : + function(tabInfo) // adds a TabInfo object to the private tabs collection + { + this._tabs[this._tabs.length] = tabInfo; + return(tabInfo); + } +} +DotNetNuke.UI.WebControls.FeedBrowser.Browser.registerClass("DotNetNuke.UI.WebControls.FeedBrowser.Browser", DotNetNuke.UI.WebControls.BaseControl); +// END: Browser class + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BEGIN: TabInfo class // +// Defines the structure for a single tab // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DotNetNuke.UI.WebControls.FeedBrowser.TabInfo = function(label, opmlUrl, template) +{ + this._label = label; + this._sections = []; + this._opmlUrl = opmlUrl; + if (template) + this._template = template; + else + this._template = ""; +} + +DotNetNuke.UI.WebControls.FeedBrowser.TabInfo.prototype = +{ + getLabel : + function() // this is the only required data item for the TabStrip.TabInfo interface + { + return(this._label); + }, + + getOpmlUrl : + function() + { + return(this._opmlUrl); + }, + + getTemplate : + function() + { + return(this._template); + }, + + getSections : + function() // returns array of sectionInfo objects + { + return(this._sections); + }, + + addSection : + function(sectionInfo) // adds a sectionInfo object to the private sections collection + { + this._sections[this._sections.length] = sectionInfo; + return(sectionInfo); + } +} +DotNetNuke.UI.WebControls.FeedBrowser.TabInfo.registerClass("DotNetNuke.UI.WebControls.FeedBrowser.TabInfo"); +// END: TabInfo class + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BEGIN: SectionInfo class // +// Defines the structure for a single section // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DotNetNuke.UI.WebControls.FeedBrowser.SectionInfo = function(label, searchUrl, template) +{ + this._categories = []; + this._defaultCategoryIndex = 0; + this._label = label; + this._searchUrl = searchUrl; + if (template) + this._template = template; + else + this._template = ""; +} + +DotNetNuke.UI.WebControls.FeedBrowser.SectionInfo.prototype = +{ + getLabel : + function() + { + return(this._label); + }, + + getSearchUrl : + function() + { + return(this._searchUrl); + }, + + getTemplate : + function() + { + return(this._template); + }, + + getCategories : + function() // returns array of categoryInfo objects + { + return(this._categories); + }, + + addCategory : + function(categoryInfo) // adds a categoryInfo object to the private categories collection + { + this._categories[this._categories.length] = categoryInfo; + return(categoryInfo); + }, + + setDefaultCategory : + function(index) + { + if ((index < this._categories.length) && (index > -1)) + this._defaultCategoryIndex = index; + }, + + getDefaultCategory : + function() + { + return(this._defaultCategoryIndex); + } +} + +DotNetNuke.UI.WebControls.FeedBrowser.SectionInfo.registerClass("DotNetNuke.UI.WebControls.FeedBrowser.SectionInfo"); +// END: SectionInfo class + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BEGIN: CategoryInfo class // +// Defines the structure for a single category // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo = function(label, feedUrl, depth, template) +{ + this._label = label + this._feedUrl = feedUrl; + this._depth = (depth > -1 ? depth : 0); + if (template) + this._template = template; + else + this._template = ""; +} + +DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo.prototype = +{ + getLabel : + function() + { + return(this._label); + }, + + getFeedUrl : + function() + { + return(this._feedUrl); + }, + + getEncodedFeedUrl : + function() + { + var url = this._feedUrl + (this._feedUrl.indexOf("?") > -1 ? "&" : "?") + "random=" + this.getCacheKey(); + return(url.urlEncode()); + }, + + getDepth : + function() + { + return(this._depth); + }, + + getTemplate : + function() + { + return(this._template); + }, + + getCacheKey : + function() + { + var now = new Date(); + var year = now.getYear(); + var month = (now.getMonth() > 10 ? "" : "0") + now.getMonth(); + var hour = now.getHours(); + var minutes = now.getMinutes() - (now.getMinutes() % 5); + var modMinutes = (minutes > 10 ? "" : "0") + minutes; + return(year + month + hour + modMinutes); + } + +} +DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo.registerClass("DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo"); +// END: CategoryInfo class + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// BEGIN: RssInfo class // +// Defines the structure for a single RSS feed // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +DotNetNuke.UI.WebControls.FeedBrowser.RssInfo = function(feed, template, header, allowHtml) +{ + this.formattedItems = []; + var itemCollection = feed.value["items"]; + var feedHeader = []; + + if (header) + feedHeader[0] = header; + + for(var item in itemCollection) + { + var itemData = []; + if (typeof(itemCollection[item]) == "object") + { + var ivalues = DotNetNuke.UI.WebControls.Utility.recurseElement("", itemCollection[item]); + for(var iv in ivalues) + itemData[iv] = ivalues[iv]; + } + else + itemData[item] = itemCollection[item]; + + var formattedItem = template; + + // If the template is a function (i.e. begins with "@@") then treat it differently + // as we would a normal HTML template + if( formattedItem.substr(0,2) == "@@" ) + { + // First pass -- replace data tokens surrounded by [[ ]] + for(var attribute in itemData) + { + var dataValue = (allowHtml ? itemData[attribute].xmlEntityReplace() : itemData[attribute]); + // Replace the token with the actual data value + formattedItem = formattedItem + .replaceAll("[[" + attribute + "]]", dataValue + .replaceAll("'","'") + .replaceAll("\"",""") + .replaceAll(",",",") + .replaceAll("\n"," ")); + } + + // And lastly -- since template begins with @@, we treat it as a function + formattedItem = eval(formattedItem.substr(2)); + } + else // Normal template + { + // First pass -- replace data tokens surrounded by [[ ]] + for(var attribute in itemData) + { + var dataValue = (allowHtml ? itemData[attribute].xmlEntityReplace() : itemData[attribute]); + // Replace the token with the actual data value. Do not do any special processing + formattedItem = formattedItem.replaceAll("[[" + attribute + "]]", dataValue); + } + } + + this.formattedItems[this.formattedItems.length] = formattedItem; + } + + this.formattedItems = feedHeader.concat(this.formattedItems.sort()); +} +DotNetNuke.UI.WebControls.FeedBrowser.RssInfo.registerClass("DotNetNuke.UI.WebControls.FeedBrowser.RssInfo"); +// END: RssInfo class + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STATIC METHODS // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// BEGIN: renderSectionMenu +// Renders the section menu i.e. the link items that appear just below the tabstrip in the FeedBrowser UI +DotNetNuke.UI.WebControls.FeedBrowser.renderSectionMenu = function(containerId, instanceVarName, clickHandler, displaySectionIndex, currentTabIndex) +{ + + var container = $get(containerId); + if (!container) return; + + var selectedSection = -99; + try + { + var instance = eval(instanceVarName); + instance._ignoreAsyncContent = false; + var tabs = instance.getTabs(); + var sections = tabs[currentTabIndex].getSections(); + var stylePrefix = instance.getStylePrefix(); + + if (sections.length > 0) + { + if ((displaySectionIndex != null) && (displaySectionIndex < sections.length)) + selectedSection = displaySectionIndex; + if (selectedSection == -99) + selectedSection = 0; + var sectionHTML = "
      "; + for(var t = 0; t < sections.length; t++) + { + sectionHTML += "
    • "; + + } + sectionHTML += "
    "; + container.innerHTML = sectionHTML; + } + else + container.innerHTML = " "; + } + catch(e) + { + container.innerHTML = e.message; + } + try + { + eval(clickHandler + "(\"" + instanceVarName + "\"," + selectedSection + "," + currentTabIndex + ")"); + } + catch(e) + { + container.innerHTML = e.message; + } +} +// END: renderSectionMenu + + +// BEGIN: renderCategoryMenu +// Renders the category menu i.e. the link items that appear to the left in the FeedBrowser UI +DotNetNuke.UI.WebControls.FeedBrowser.renderCategoryMenu = function(containerId, instanceVarName, clickHandler, displayCategoryIndex, currentSectionIndex, currentTabIndex) +{ + + var container = $get(containerId); + if (!container) return; + + var selectedCategory = -99; + try + { + var instance = eval(instanceVarName); + instance._ignoreAsyncContent = false; + var tabs = instance.getTabs(); + var sections = tabs[currentTabIndex].getSections(); + var categories = sections[currentSectionIndex].getCategories(); + var stylePrefix = instance.getStylePrefix(); + + if (categories.length > 0) + { + if (displayCategoryIndex == -1) + displayCategoryIndex = sections[currentSectionIndex].getDefaultCategory(); + + if (displayCategoryIndex < categories.length) + selectedCategory = displayCategoryIndex; + + if (selectedCategory == -99) + selectedCategory = 0; + + var categoryHTML = new Sys.StringBuilder(""); + + if (typeof(sections[currentSectionIndex].getSearchUrl()) != "undefined") + { + categoryHTML.append(""); + } + + for(var t = 0; t < categories.length; t++) + { + categoryHTML.append(""); + categoryHTML.append(""); + } + categoryHTML.append("
    "); + categoryHTML.append(""); + categoryHTML.append("
     
    "); + if (categories[t].getDepth() > 0) + { + for(var d=0; d < categories[t].getDepth(); d++) + categoryHTML.append("
     
    "); + } + categoryHTML.append(categories[t].getLabel() + "
     
    "); + container.innerHTML = categoryHTML.toString(); + try + { + eval(clickHandler + "(\"" + instanceVarName + "\"," + selectedCategory + "," + currentSectionIndex + "," + currentTabIndex + ")"); + } + catch(e) + { + container.innerHTML = e.message; + } + } + else + { + container.innerHTML = " "; + DotNetNuke.UI.WebControls.FeedBrowser.renderFeed(instance.getElementIdPrefix() + "ContentContainer", instanceVarName, -2, currentSectionIndex, currentTabIndex); + } + } + catch(e) + { + container.innerHTML = e.message; + } +} +// END: renderCategoryMenu + + +// BEGIN: renderFeed +// Renders feed items using the specified template for each item +DotNetNuke.UI.WebControls.FeedBrowser.renderFeed = function(containerId, instanceVarName, currentCategoryIndex, currentSectionIndex, currentTabIndex, keyword) +{ + var container = $get(containerId); + if (!container) return; + + try + { + var instance = eval(instanceVarName); + + var tabs = instance.getTabs(); + var sections = tabs[currentTabIndex].getSections(); + var stylePrefix = instance.getStylePrefix(); + var categoryInfo = null; + + if (currentCategoryIndex == -1) + { + var searchUrl = sections[currentSectionIndex].getSearchUrl(); + if (searchUrl.indexOf("[KEYWORD]") > -1) + searchUrl = searchUrl.replace("[KEYWORD]", escape(keyword)); + else + searchUrl += (searchUrl.indexOf("?") > -1 ? "&" : "?") + "keyword=" + escape(keyword); + categoryInfo = new DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo("Search", searchUrl, 0); + } + else if (currentCategoryIndex == -2) + { + instance._ignoreAsyncContent = true; + categoryInfo = new DotNetNuke.UI.WebControls.FeedBrowser.CategoryInfo("Feed", sections[currentSectionIndex].getSearchUrl(), 0) + } + else + { + var categories = sections[currentSectionIndex].getCategories(); + categoryInfo = categories[currentCategoryIndex]; + } + + if (categoryInfo) + { + container.innerHTML = instance.displayLoader(); + var template = ""; + if (categoryInfo.getTemplate() != "") + template = categoryInfo.getTemplate(); + else if (sections[currentSectionIndex].getTemplate() != "") + template = sections[currentSectionIndex].getTemplate(); + else if (tabs[currentTabIndex].getTemplate() != "") + template = tabs[currentTabIndex].getTemplate(); + else + template = instance.getDefaultTemplate(); + if (template.substring(0,2) == "@@") + { + instance._ignoreAsyncContent = true; + var frameHeight = template.substring(2,10); + var newHtml = ""; + container.innerHTML = newHtml; + } + else + { + // Create a new function + var counter = 0; + try + { + while(eval(instanceVarName + counter)) + counter++; + } + catch(e) + { + } + + // Dynamically create a callback function and pass to it the instance name and callback data + eval(instanceVarName + counter + " = new Function(\"data\", \"rssRenderingHandler('" + instanceVarName + "', '" + template + "', data)\")"); + + var newScript = document.createElement("script"); + newScript.type = "text/javascript"; + newScript.src = instance.getRssProxyUrl(instanceVarName + counter) + categoryInfo.getEncodedFeedUrl(); + + document.getElementsByTagName("head")[0].appendChild(newScript); + } + } + else + container.innerHTML = " "; + } + catch(e) + { + container.innerHTML = e.message; + } +} +// END: renderFeed + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// EVENT HANDLERS // +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +function tabClickHandler(instanceVarName, tabIndex) +{ + var instance = eval(instanceVarName); + DotNetNuke.UI.WebControls.FeedBrowser.renderSectionMenu(instance.getElementIdPrefix() + "SectionsContainer", instanceVarName, "sectionClickHandler", 0, tabIndex); +} + +function sectionClickHandler(instanceVarName, sectionIndex, tabIndex) +{ + var instance = eval(instanceVarName); + DotNetNuke.UI.WebControls.FeedBrowser.renderCategoryMenu(instance.getElementIdPrefix() + "CategoriesContainer", instanceVarName, "categoryClickHandler", -1, sectionIndex, tabIndex); +} + +function categoryClickHandler(instanceVarName, categoryIndex, sectionIndex, tabIndex) +{ + var instance = eval(instanceVarName); + DotNetNuke.UI.WebControls.FeedBrowser.renderFeed(instance.getElementIdPrefix() + "ContentContainer", instanceVarName, categoryIndex, sectionIndex, tabIndex); +} + +function searchClickHandler(instanceVarName, sectionIndex, tabIndex) +{ + var instance = eval(instanceVarName); + + var keywordField = $get(instance.getElementIdPrefix() + "FBKeyword"); + var keyword = keywordField.value.trim(); + if (keyword == "") return; + + DotNetNuke.UI.WebControls.FeedBrowser.renderFeed(instance.getElementIdPrefix() + "ContentContainer", instanceVarName, -1, sectionIndex, tabIndex, keyword); +} + +function rssRenderingHandler(instanceVarName, template, result) +{ + var instance = eval(instanceVarName); + + // The user may have clicked another node while an async call is in the process + // of retrieving data. This ensures that if the call returns in such a situation + // it will be ignored instead of over-writing content. + if (instance._ignoreAsyncContent) + return; + + // Extract template from feed or fallback to default + var tmp = ""; + if (result != null) + { + var templateHtml = instance.getTemplates()[template]; + var headerHtml = instance.getHeaders()[template]; + + if (typeof(templateHtml) == "undefined") + templateHtml = instance.getTemplates()["default"]; + var feedInfo = new DotNetNuke.UI.WebControls.FeedBrowser.RssInfo(result, templateHtml, headerHtml, instance.getAllowHtmlDescription()); + + var items = feedInfo.formattedItems; + for(var i in items) + tmp += items[i]; + } + + // if (tmp.indexOf("' + +'' + + '[[title]]' + +'' + +'' + + '' + + '[[description]]' + + '' + + '' + +'

    '; + + + +// Marketplace template +htmlTemplates['marketplace'] = +'@@marketplaceItemRenderer("[[title]]","[[link]]","[[description]]","[[enclosure.url]]",[[dnnmp:isReviewed]],"[[dnnmp:overview]]","[[dnnmp:vendor]]","[[dnnmp:vendorLink]]","[[dnnmp:price]]".split(".")[0])'; + + +// DotNetNuke template +htmlTemplates['dotnetnuke'] = + +'' + +'' + + '' + +'' + +'' + + '' + + '' + +'
    [[title]]
    ' + + '[[description]]' + + '


    '; + +// Hosting template +htmlTemplates['hosting'] = + +'' + +'' + + '' + +'' + +'' + + '' + + '' + +'
    [[title]]
    ' + + '[[description]]' + + '


    '; + + +htmlHeaders['dotnetnuke'] = '
    '; +htmlHeaders['marketplace'] = '
    '; + +// Used by Marketplace template +function marketplacePreviewHandler(url) +{ + var previewBrowser = $get("PreviewBrowser"); + previewBrowser.contentWindow.location.replace(url); + previewBrowser.style.visibility = "hidden"; + var preview = $get("PreviewContainer"); + preview.style.display = "block"; + previewBrowser.style.visibility = "visible"; +} + +function marketplaceItemRenderer(title, url, description, imageUrl, isReviewed, overviewUrl, vendor, vendorUrl, price) +{ + var itemTemplate = ''; + + if (isReviewed) + { + itemTemplate += + '' + // Add a comment to force reviewed products to be grouped first + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
    ' + title + '
    by ' + vendor + '
    ' + + '' + + '

    from $' + price + '

    ' + + '

    ' + + 'Info | ' + + 'BUY
    ' + + '

    '+ + '
    ' + + description + + '
    '; + } + else + { + itemTemplate += + '' + // Add a comment to force non-reviewed products to be grouped first + '' + + '' + + '' + + '' + + ''; + + var firstSentence = description.indexOf(". "); + if (firstSentence > -1) + itemTemplate += + '' + + '' + + '' + + '
    ' + title + '
    by ' + vendor + '
    from $' + price + ' BUY
    ' + + description.substr(0, firstSentence+1) + + '
    '; + } + + return(itemTemplate); +} diff --git a/Website/Resources/FeedBrowser/themes/graphite/graphite.css b/Website/Resources/FeedBrowser/themes/graphite/graphite.css new file mode 100644 index 00000000000..dd9edeca449 --- /dev/null +++ b/Website/Resources/FeedBrowser/themes/graphite/graphite.css @@ -0,0 +1,184 @@ +/**************************************************************************************/ +/* BEGIN: Overall Layout */ +/**************************************************************************************/ + +.FeedBrowser-Graphite-MainTable +{ + border: 1px solid #dddddd; + width: 100%; + background-color: White; +} + +td.FeedBrowser-Graphite-NavTop +{ + background-image: url(nav-top-bar.gif); + background-repeat: repeat-x; + height: 51px; + width: 100%; + margin: 0px; +} + +.FeedBrowser-Graphite-NavLeft +{ + background-image: url(nav-left.gif); + background-repeat: repeat-y; + margin: 0px; +} + +.FeedBrowser-Graphite-NavLeftCurve +{ + background-image: url(nav-left-curve.gif); + background-repeat: no-repeat; + width: 250px; + height: 36px; + margin: 0px; +} + +.FeedBrowser-Graphite-NavBottom +{ + background-image: url(nav-bottom-bar.gif); + background-repeat: repeat-x; + height: 39px; + margin: 0px; +} + +.FeedBrowser-Graphite-Loader +{ + background-image: url(loading.gif); + background-position: center center; + background-repeat: no-repeat; + height: 100px; +} + +/**************************************************************************************/ +/* BEGIN: Sections */ +/**************************************************************************************/ +ul.FeedBrowser-Graphite-SectionMenu, +ul.FeedBrowser-Graphite-SectionMenu li +{ + list-style: none; + padding: 0px 0px 0px 15px; + margin: 0px; + white-space: nowrap; +} + + +ul.FeedBrowser-Graphite-SectionMenu li +{ + float: left; + text-align: center; + cursor: pointer; +} + +li.FeedBrowser-Graphite-SectionMenu-Selected, +li.FeedBrowser-Graphite-SectionMenu-Normal +{ + list-style: none; +} + +/**************************************************************************************/ +/* BEGIN: Categories */ +/**************************************************************************************/ +table.FeedBrowser-Graphite-Category +{ + padding-left: 10px; + width: 250px; +} + +.FeedBrowser-Graphite-Category .Off +{ + height: 34px; + color: #333333; + cursor: pointer; +} + +.FeedBrowser-Graphite-Category .On +{ + height: 34px; + border-top: 1px solid #dddddd; + border-bottom: 1px solid #dddddd; + cursor: pointer; +} + +.FeedBrowser-Graphite-Category .Indent +{ + width: 15px; + height: 20px; + overflow: hidden; + float: left; +} + +.FeedBrowser-Graphite-Category .Pointer +{ + padding: 0px; + background-image: url(pointer.gif); + background-repeat: no-repeat; + background-position: top left; + width: 69px; + overflow: hidden; +} + +.FeedBrowser-Graphite-Category .NoPointer +{ + padding: 0px; + width: 69px; +} + +.FeedBrowser-Graphite-Category .SearchBox +{ + width: 140px; + border:1px solid #dddddd; + height: 20px; +} + +.FeedBrowser-Graphite-Category .SearchButton +{ + width: 24px; + height: 20px; + background-image: url(search.gif); + background-repeat: no-repeat; + border-width: 0px; + cursor: pointer; +} + +/**************************************************************************************/ +/* BEGIN: Content */ +/**************************************************************************************/ + +.FeedBrowser-Graphite-Content +{ + width: 99%; + height: 300px; +} + +/**************************************************************************************/ +/* BEGIN: Balloon */ +/**************************************************************************************/ + +.FeedBrowser-Graphite-PreviewContainer +{ + position:absolute; + left:50%; + width:500px; + margin-top:50px; + margin-left:-266px; + padding:5px; + background-color:#eee; + border: 1px solid #777777; + display: none; + z-index: 1000; + text-align: center; +} + +.FeedBrowser-Graphite-PreviewContainerTitle +{ + background-color: #e0e0e0; + color: Black; +} + +.FeedBrowser-Graphite-PreviewBrowser +{ + width: 490px; + height: 490px; + border: 0px; +} \ No newline at end of file diff --git a/Website/Resources/FeedBrowser/themes/graphite/loading.gif b/Website/Resources/FeedBrowser/themes/graphite/loading.gif new file mode 100644 index 00000000000..f864d5fd38b Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/loading.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/nav-bottom-bar.gif b/Website/Resources/FeedBrowser/themes/graphite/nav-bottom-bar.gif new file mode 100644 index 00000000000..dbb6e894af1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/nav-bottom-bar.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/nav-left-curve.gif b/Website/Resources/FeedBrowser/themes/graphite/nav-left-curve.gif new file mode 100644 index 00000000000..c6326ee60e1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/nav-left-curve.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/nav-left.gif b/Website/Resources/FeedBrowser/themes/graphite/nav-left.gif new file mode 100644 index 00000000000..608f3c57e54 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/nav-left.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/nav-top-bar.gif b/Website/Resources/FeedBrowser/themes/graphite/nav-top-bar.gif new file mode 100644 index 00000000000..203f42c2d9f Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/nav-top-bar.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/pointer.gif b/Website/Resources/FeedBrowser/themes/graphite/pointer.gif new file mode 100644 index 00000000000..35db2d3b067 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/pointer.gif differ diff --git a/Website/Resources/FeedBrowser/themes/graphite/search.gif b/Website/Resources/FeedBrowser/themes/graphite/search.gif new file mode 100644 index 00000000000..d5ac486eef1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/graphite/search.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/loading.gif b/Website/Resources/FeedBrowser/themes/platinum/loading.gif new file mode 100644 index 00000000000..f864d5fd38b Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/loading.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/nav-bottom-bar.gif b/Website/Resources/FeedBrowser/themes/platinum/nav-bottom-bar.gif new file mode 100644 index 00000000000..dbb6e894af1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/nav-bottom-bar.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/nav-left-curve.gif b/Website/Resources/FeedBrowser/themes/platinum/nav-left-curve.gif new file mode 100644 index 00000000000..c6326ee60e1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/nav-left-curve.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/nav-left.gif b/Website/Resources/FeedBrowser/themes/platinum/nav-left.gif new file mode 100644 index 00000000000..608f3c57e54 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/nav-left.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/nav-top-bar.gif b/Website/Resources/FeedBrowser/themes/platinum/nav-top-bar.gif new file mode 100644 index 00000000000..203f42c2d9f Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/nav-top-bar.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/platinum.css b/Website/Resources/FeedBrowser/themes/platinum/platinum.css new file mode 100644 index 00000000000..bc009921c44 --- /dev/null +++ b/Website/Resources/FeedBrowser/themes/platinum/platinum.css @@ -0,0 +1,184 @@ +/**************************************************************************************/ +/* BEGIN: Overall Layout */ +/**************************************************************************************/ + +.FeedBrowser-Platinum-MainTable +{ + border: 1px solid #dddddd; + width: 100%; + background-color: White; +} + +td.FeedBrowser-Platinum-NavTop +{ + background-image: url(nav-top-bar.gif); + background-repeat: repeat-x; + height: 51px; + width: 100%; + margin: 0px; +} + +.FeedBrowser-Platinum-NavLeft +{ + background-image: url(nav-left.gif); + background-repeat: repeat-y; + margin: 0px; +} + +.FeedBrowser-Platinum-NavLeftCurve +{ + background-image: url(nav-left-curve.gif); + background-repeat: no-repeat; + width: 250px; + height: 36px; + margin: 0px; +} + +.FeedBrowser-Platinum-NavBottom +{ + background-image: url(nav-bottom-bar.gif); + background-repeat: repeat-x; + height: 39px; + margin: 0px; +} + +.FeedBrowser-Platinum-Loader +{ + background-image: url(loading.gif); + background-position: center center; + background-repeat: no-repeat; + height: 100px; +} + +/**************************************************************************************/ +/* BEGIN: Sections */ +/**************************************************************************************/ +ul.FeedBrowser-Platinum-SectionMenu, +ul.FeedBrowser-Platinum-SectionMenu li +{ + list-style: none; + padding: 0px 0px 0px 15px; + margin: 0px; + white-space: nowrap; +} + + +ul.FeedBrowser-Platinum-SectionMenu li +{ + float: left; + text-align: center; + cursor: pointer; +} + +li.FeedBrowser-Platinum-SectionMenu-Selected, +li.FeedBrowser-Platinum-SectionMenu-Normal +{ + list-style: none; +} + +/**************************************************************************************/ +/* BEGIN: Categories */ +/**************************************************************************************/ +table.FeedBrowser-Platinum-Category +{ + padding-left: 10px; + width: 250px; +} + +.FeedBrowser-Platinum-Category .Off +{ + height: 34px; + color: #333333; + cursor: pointer; +} + +.FeedBrowser-Platinum-Category .On +{ + height: 34px; + border-top: 1px solid #dddddd; + border-bottom: 1px solid #dddddd; + cursor: pointer; +} + +.FeedBrowser-Platinum-Category .Indent +{ + width: 15px; + height: 20px; + overflow: hidden; + float: left; +} + +.FeedBrowser-Platinum-Category .Pointer +{ + padding: 0px; + background-image: url(pointer.gif); + background-repeat: no-repeat; + background-position: top left; + width: 69px; + overflow: hidden; +} + +.FeedBrowser-Platinum-Category .NoPointer +{ + padding: 0px; + width: 69px; +} + +.FeedBrowser-Platinum-Category .SearchBox +{ + width: 140px; + border:1px solid #dddddd; + height: 20px; +} + +.FeedBrowser-Platinum-Category .SearchButton +{ + width: 24px; + height: 20px; + background-image: url(search.gif); + background-repeat: no-repeat; + border-width: 0px; + cursor: pointer; +} + +/**************************************************************************************/ +/* BEGIN: Content */ +/**************************************************************************************/ + +.FeedBrowser-Platinum-Content +{ + width: 99%; + height: 300px; +} + +/**************************************************************************************/ +/* BEGIN: Balloon */ +/**************************************************************************************/ + +.FeedBrowser-Platinum-PreviewContainer +{ + position:absolute; + left:50%; + width:500px; + margin-top:50px; + margin-left:-266px; + padding:5px; + background-color:#eee; + border: 1px solid #777777; + display: none; + z-index: 1000; + text-align: center; +} + +.FeedBrowser-Platinum-PreviewContainerTitle +{ + background-color: #e0e0e0; + color: Black; +} + +.FeedBrowser-Platinum-PreviewBrowser +{ + width: 490px; + height: 490px; + border: 0px; +} \ No newline at end of file diff --git a/Website/Resources/FeedBrowser/themes/platinum/pointer.gif b/Website/Resources/FeedBrowser/themes/platinum/pointer.gif new file mode 100644 index 00000000000..35db2d3b067 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/pointer.gif differ diff --git a/Website/Resources/FeedBrowser/themes/platinum/search.gif b/Website/Resources/FeedBrowser/themes/platinum/search.gif new file mode 100644 index 00000000000..d5ac486eef1 Binary files /dev/null and b/Website/Resources/FeedBrowser/themes/platinum/search.gif differ diff --git a/Website/Resources/Search/Search.js b/Website/Resources/Search/Search.js new file mode 100644 index 00000000000..2943532fba0 --- /dev/null +++ b/Website/Resources/Search/Search.js @@ -0,0 +1,78 @@ +(function ($, dnn) { + var isDropDownVisible = false; + var searchSkinObject = null; + var toggleDropDown = function(eventElement) { + var choices = $get('SearchChoices'); + if (isDropDownVisible) { + choices.style.display = 'none'; + isDropDownVisible = false; + } else { + choices.style.display = 'block'; + isDropDownVisible = true; + + var clickEvent = function(e) { + if (isDropDownVisible && e.target.id != "SearchIcon" && e.target.id.indexOf("downArrow") == -1) { + toggleDropDown(); + $(document).unbind("click", clickEvent); + } + }; + + $(document).bind("click", clickEvent); + } + }; + + var selectSearch = function(eventElement) { + toggleDropDown(eventElement); + $get('SearchIcon').style.backgroundImage = dnn.getVar(eventElement.target.id + 'Url'); + + /* We use 'W' and 'S' to keep our code consistent with the old search skin object */ + if (eventElement.target.id.indexOf("Web") > 0) { + dnn.setVar('SearchIconSelected', 'W'); + if(searchSkinObject) + searchSkinObject.settings.searchType = 'W'; + } else { + dnn.setVar('SearchIconSelected', 'S'); + if (searchSkinObject) + searchSkinObject.settings.searchType = 'S'; + } + }; + + var searchHilite = function(eventElement) { + eventElement.target.className = 'searchHilite'; + }; + + var searchDefault = function(eventElement) { + eventElement.target.className = 'searchDefault'; + }; + + var initSearch = function() { + var searchIcon = $get('SearchIcon'); + if (dnn.getVar('SearchIconSelected') == 'S') { + searchIcon.style.backgroundImage = dnn.getVar('SearchIconSiteUrl'); + } else { + searchIcon.style.backgroundImage = dnn.getVar('SearchIconWebUrl'); + } + $addHandler(searchIcon, 'click', toggleDropDown); + + var siteIcon = $get('SearchIconSite'); + siteIcon.style.backgroundImage = dnn.getVar('SearchIconSiteUrl'); + $addHandler(siteIcon, 'click', selectSearch); + $addHandler(siteIcon, 'mouseover', searchHilite); + $addHandler(siteIcon, 'mouseout', searchDefault); + + var webIcon = $get('SearchIconWeb'); + webIcon.style.backgroundImage = dnn.getVar('SearchIconWebUrl'); + $addHandler(webIcon, 'click', selectSearch); + $addHandler(webIcon, 'mouseover', searchHilite); + $addHandler(webIcon, 'mouseout', searchDefault); + + /* Set the default display style to resolve DOM bug */ + $get('SearchChoices').style.display = 'none'; + }; + + dnn.initDropdownSearch = function (skinObject) { + searchSkinObject = skinObject; + initSearch(); + }; + +})(jQuery, window.dnn); diff --git a/Website/Resources/Search/SearchSkinObjectPreview.css b/Website/Resources/Search/SearchSkinObjectPreview.css new file mode 100644 index 00000000000..c08cc967243 --- /dev/null +++ b/Website/Resources/Search/SearchSkinObjectPreview.css @@ -0,0 +1,101 @@ +.searchInputContainer { + display: inline-block !important; + margin: 0 -3px 0 0 !important; + position: relative !important; +} + .searchInputContainer > input[type="text"]::-ms-clear { + display: none; + } + + .searchInputContainer a.dnnSearchBoxClearText { + display: block !important; + position: absolute !important; + right: 10px !important; + width: 16px !important; + height: 16px !important; + background: none !important; + cursor: pointer; + margin: 7px 0 7px 0; + z-index: 20; + } + + .searchInputContainer a.dnnSearchBoxClearText.dnnShow { + background: url(../../../images/search/clearText.png) center center no-repeat !important; + } + +ul.searchSkinObjectPreview { + position: absolute; + top: 100%; + right: 0; + background: #fff; + margin: 0; + list-style: none; + border: 1px solid #c9c9c9; + width: 350px; + z-index: 200; + padding: 0; +} + +ul.searchSkinObjectPreview li { + list-style: none !important; +} + + ul.searchSkinObjectPreview > li { + padding: 6px 12px 6px 22px; + border-top: 1px solid #c9c9c9; + color: #666; + cursor: pointer; + position: relative; + margin: 0; + text-transform: none; + } + + ul.searchSkinObjectPreview > li:hover { + background-color: #e8f1fa; + color: #333; + } + + ul.searchSkinObjectPreview > li > span { + } + + ul.searchSkinObjectPreview > li > span > b { + font-weight: bold; + color: #000; + } + + ul.searchSkinObjectPreview > li p { + margin: 0; + font-size: 10px; + line-height: 1.2em; + color: #999; + font-style: italic; + white-space: normal; + } + + ul.searchSkinObjectPreview > li p b { + color: #000; + } + + ul.searchSkinObjectPreview > li.searchSkinObjectPreview_group { + padding: 6px 12px 6px 12px; + font-weight: bold; + color: #000; + border-bottom: 2px solid #000; + cursor: inherit; + } + + ul.searchSkinObjectPreview > li.searchSkinObjectPreview_group:hover { + background-color: #fff; + color: #000; + } + + ul.searchSkinObjectPreview > li > a.searchSkinObjectPreview_more { + display: inline !important; + position: static !important; + background: none !important; + z-index: inherit !important; + width: auto !important; + height: auto !important; + text-indent: inherit !important; + float: none !important; + } diff --git a/Website/Resources/Search/SearchSkinObjectPreview.js b/Website/Resources/Search/SearchSkinObjectPreview.js new file mode 100644 index 00000000000..f727460ee87 --- /dev/null +++ b/Website/Resources/Search/SearchSkinObjectPreview.js @@ -0,0 +1,184 @@ +(function ($) { + if (typeof dnn == 'undefined') window.dnn = {}; + if (typeof dnn.searchSkinObject == 'undefined') { + dnn.searchSkinObject = function (options) { + var settings = { + delayTriggerAutoSearch: 100, + minCharRequiredTriggerAutoSearch: 2, + searchType: 'S', + enableWildSearch: true, + cultureCode: 'en-US' + }; + this.settings = $.extend({}, settings, options); + }; + dnn.searchSkinObject.prototype = { + _ignoreKeyCodes: [9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45], + init: function () { + var throttle = null, self = this; + var makeUrl = function (val, service) { + var url = service ? service.getServiceRoot('internalservices') + 'searchService/preview' : null; + if (!url) return null; + var params = {}; + params['keywords'] = val.replace(/^\s+|\s+$/g, ''); + if (!self.settings.enableWildSearch) params["forceWild"] = "0"; + params['culture'] = self.settings.cultureCode; + if (self.settings.portalId >= 0) + params['portal'] = self.settings.portalId; + var urlAppend = []; + $.each(params, function (index, value) { + urlAppend.push([index, encodeURIComponent(value)].join('=')); + }); + + if (urlAppend.length) { + url += url.indexOf('?') === -1 ? '?' : '&'; + url += urlAppend.join('&'); + } + return url; + }; + + var generatePreviewTemplate = function (data) { + var $wrap = $('.searchInputContainer'); + var preview = $('.searchSkinObjectPreview', $wrap); + if (preview.length) + preview.remove(); + + var markup = '
      '; + if (data && data.length) { + for (var i = 0; i < data.length; i++) { + var group = data[i]; + if (group.Results && group.Results.length) { + var groupTitle = group.DocumentTypeName; + markup += '
    • ' + groupTitle + '
    • '; + for (var j = 0; j < group.Results.length; j++) { + var item = group.Results[j]; + var itemTitle = item.Title; + var itemUrl = item.DocumentUrl; + var itemSnippet = item.Snippet; + markup += '
    • ' + itemTitle + ''; + if (itemSnippet) + markup += '

      ' + itemSnippet + '

    • '; + else + markup += ''; + } // end for group items + } + } // end for group + + var moreResults = $wrap.attr('data-moreresults'); + markup += '
    • ' + moreResults + '
    • '; + markup += '
    '; + } + else { + var noResult = $wrap.attr('data-noresult'); + markup += '
  • ' + noResult + '
  • '; + } + + $wrap.append(markup); + preview = $('.searchSkinObjectPreview', $wrap); + + //attach click event + $('li', preview).on('click', function () { + var navigateUrl = $(this).attr('data-url'); + if (navigateUrl) { + window.location.href = navigateUrl; + } + return false; + }); + + //attach see more + $('.searchSkinObjectPreview_more', $wrap).on('click', function () { + var href = $wrap.next().attr('href'); + var code = href.replace('javascript:', ''); + eval(code); + return false; + }); + }; + + $('.searchInputContainer a.dnnSearchBoxClearText').on('click', function () { + var $this = $(this); + var $wrap = $this.parent(); + $('.searchInputContainer input').val('').focus(); + $this.removeClass('dnnShow'); + $('.searchSkinObjectPreview', $wrap).remove(); + return false; + }); + + $('.searchInputContainer').next().on('click', function() { + var $this = $(this); + var inputBox = $this.prev().find('input[type="text"]'); + var val = inputBox.val(); + if (val.length) { + return true; + } + return false; + }); + + $('.searchInputContainer input').on('keyup', function(e) { + var k = e.keyCode || e.witch; + if (self._ignoreKeyCodes.indexOf(k) > -1) return; + + var $this = $(this); + var $wrap = $this.parent(); + var val = $this.val(); + if (!val) { + + $('a.dnnSearchBoxClearText', $wrap).removeClass('dnnShow'); + $('.searchSkinObjectPreview', $wrap).remove(); + } else { + $('a.dnnSearchBoxClearText', $wrap).addClass('dnnShow'); + + if (self.settings.searchType != 'S' || + val.length < self.settings.minCharRequiredTriggerAutoSearch) return; + + if (throttle) { + clearTimeout(throttle); + delete throttle; + } + + throttle = setTimeout(function() { + var service = $.dnnSF ? $.dnnSF(-1) : null; + var url = makeUrl(val, service); + if (url) { + $.ajax({ + url: url, + beforeSend: service ? service.setModuleHeaders : null, + success: function(result) { + if (result) + generatePreviewTemplate(result); + }, + error: function() { + }, + type: 'GET', + dataType: 'json', + contentType: "application/json" + }); + } + }, self.settings.delayTriggerAutoSearch); + } + }) + .on('paste', function() { + $(this).triggerHandler('keyup'); + }) + .on('keypress', function(e) { + var k = e.keyCode || e.which; + if (k == 13) { + var $this = $(this); + var $wrap = $this.parent(); + var val = $this.val(); + if (val.length) { + var href = $wrap.next().attr('href'); + if (!href) { + // dropdown search + href = $wrap.parent().next().attr('href'); + } + var code = href.replace('javascript:', ''); + eval(code); + e.preventDefault(); + } else { + e.preventDefault(); + } + } + }); + } + }; + } +})(jQuery); diff --git a/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.css b/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.css new file mode 100644 index 00000000000..d49a38f3837 --- /dev/null +++ b/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.css @@ -0,0 +1,33 @@ +.composeMessageDialog .dnnLeft .dnnFormItem{border-bottom:solid 1px #eee;width:400px;} +.composeMessageDialog .dnnLeft .dnnFormItem img{vertical-align:middle;float:right;} +.composeMessageDialog .dnnLeft button{cursor:pointer;padding:0.5em 1em;border:none;} +.composeMessageDialog .dnnFormItem label, .composeMessageDialog .dnnFormItem .dnnFormLabel, .composeMessageDialog .dnnFormItem .dnnTooltip{width: 25%;} +ul.token-input-list-facebook{width: 46%; margin-bottom: 18px;} +div.token-input-dropdown-facebook ul li img{padding-right:10px;vertical-align:middle;} +/* MESSAGE ATTACHMENTS */ +.composeMessageDialog .messageAttachments { + width:300px; + float:right; +} +.composeMessageDialog .messageAttachments ul li{ + overflow:auto; + list-style:none; + border-bottom:1px solid #ddd; + margin-bottom:5px; +} +.composeMessageDialog .messageAttachments ul li a{ + float:left; + font-size:12px; + text-decoration:none; +} +.composeMessageDialog .messageAttachments a.removeAttachment{ + float:right; + display:block; + padding:3px; + width:10px; height:10px; + background:url(images/delete.png) no-repeat 3px 3px; + opacity:0.75; +} +.composeMessageDialog .messageAttachments a.removeAttachment:hover{ + opacity:1; +} \ No newline at end of file diff --git a/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.js b/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.js new file mode 100644 index 00000000000..946b6596833 --- /dev/null +++ b/Website/Resources/Shared/components/ComposeMessage/ComposeMessage.js @@ -0,0 +1,328 @@ +(function ($) { + $.fn.dnnComposeMessage = function (options) { + var opts = $.extend({}, $.fn.dnnComposeMessage.defaultOptions, options), + $wrap = $(opts.openTriggerScope), + html, + composeMessageDialog, + canSend = false, + users = [], + roles = [], + attachments = []; + + opts.serviceurlbase = opts.servicesFramework.getServiceRoot('InternalServices') + 'MessagingService/'; + + //construct the form + html = "
    "; + html += "
    "; + html += "
    "; + html += "
    '); + m_oSPDebugCtl = document.all('my__Debug'); + } + + if (m_oSPDebugCtl != null) + m_oSPDebugCtl.value += '[' + m_iSPTotalTimer + '] ' + s + sT + '\n'; + else + m_sSPDebugText += '[' + m_iSPTotalTimer + '] ' + s + sT + '\n'; + + m_iSPTimer = new Date(); + } + + if (window.__smartNav != null) + window.setTimeout(spm_fixSmartNav, 1000); + function spm_fixSmartNav() + { + if (window.__smartNav != null) + { + if (document.readyState == 'complete') + { + var o = spm_getById('SolpartMenuDI'); + if (o != null) + { + if (o.length == null) + { + if (o.xml != null) + spm_initMyMenu(o, o.parentElement); + } + else + { + for (var i=0; i +<%@ Register TagPrefix="wc" Namespace="DotNetNuke.UI.WebControls" Assembly="CountryListBox" %> +<%@ Register TagPrefix="dnn" TagName="label" Src="~/controls/labelControl.ascx" %> +
    +
    + + + + +
    +
    + + +
    +
    + + + + +
    +
    + +
    + +
    + + + +
    +
    + + + + + + +
    +
    + + + + +
    +
    + + + + +
    +
    + + + + +
    +
    + + + + +
    +
    \ No newline at end of file diff --git a/Website/controls/duallistcontrol.ascx b/Website/controls/duallistcontrol.ascx new file mode 100644 index 00000000000..49a991d32bc --- /dev/null +++ b/Website/controls/duallistcontrol.ascx @@ -0,0 +1,35 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.DualListControl" %> + + + + + + + + + + + +
    Available Assigned
    + + + + + + + + + + + + + + + + + + +
     
    +
    + +
    diff --git a/Website/controls/filepickeruploader.ascx b/Website/controls/filepickeruploader.ascx new file mode 100644 index 00000000000..ce4c8dd9bb3 --- /dev/null +++ b/Website/controls/filepickeruploader.ascx @@ -0,0 +1,52 @@ +<%@ Control Language="C#" AutoEventWireup="true" Inherits="DotNetNuke.Web.UI.WebControls.DnnFilePickerUploader" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.UI.WebControls" Assembly="DotNetNuke.Web" %> + +
    +
    + <%= FolderLabel %> +
    +
    + <%= FileLabel %> +
    +
    + +
    +
    +
    + + <%= DropFileLabel %> + +
    +
    +
    + +
    +
    +
    + + +
    + \ No newline at end of file diff --git a/Website/controls/help.ascx b/Website/controls/help.ascx new file mode 100644 index 00000000000..220a821ab98 --- /dev/null +++ b/Website/controls/help.ascx @@ -0,0 +1,17 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.Help" %> + +
    +
    +
    + +
    +
      +
    • +
    • +
    • +
    • +
    +
    +
    +
    +
    diff --git a/Website/controls/helpbuttoncontrol.ascx b/Website/controls/helpbuttoncontrol.ascx new file mode 100644 index 00000000000..8413466b5ca --- /dev/null +++ b/Website/controls/helpbuttoncontrol.ascx @@ -0,0 +1,8 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.HelpButtonControl" targetSchema="http://schemas.microsoft.com/intellisense/ie5" %> +<%@ Register TagPrefix="dnn" Assembly="DotNetNuke.Web" Namespace="DotNetNuke.Web.UI.WebControls" %> + + + + + + \ No newline at end of file diff --git a/Website/controls/icon_help_32px.gif b/Website/controls/icon_help_32px.gif new file mode 100644 index 00000000000..fda481faf37 Binary files /dev/null and b/Website/controls/icon_help_32px.gif differ diff --git a/Website/controls/labelcontrol.ascx b/Website/controls/labelcontrol.ascx new file mode 100644 index 00000000000..b7e448f59fd --- /dev/null +++ b/Website/controls/labelcontrol.ascx @@ -0,0 +1,16 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.LabelControl" %> +
    + + + + +
    + + +
    +
    +
    + diff --git a/Website/controls/moduleauditcontrol.ascx b/Website/controls/moduleauditcontrol.ascx new file mode 100644 index 00000000000..ffe5e882a84 --- /dev/null +++ b/Website/controls/moduleauditcontrol.ascx @@ -0,0 +1,5 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.ModuleAuditControl" %> +
    +

    +

    +
    \ No newline at end of file diff --git a/Website/controls/sectionheadcontrol.ascx b/Website/controls/sectionheadcontrol.ascx new file mode 100644 index 00000000000..bf24aef4660 --- /dev/null +++ b/Website/controls/sectionheadcontrol.ascx @@ -0,0 +1,10 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.SectionHeadControl" + TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> +
    + +   + +
    + +
    +
    diff --git a/Website/controls/skincontrol.ascx b/Website/controls/skincontrol.ascx new file mode 100644 index 00000000000..f75f670add3 --- /dev/null +++ b/Website/controls/skincontrol.ascx @@ -0,0 +1,6 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.Skins.SkinControl" %> +<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.UI.WebControls" Assembly="DotNetNuke" %> +   +
    +  + diff --git a/Website/controls/skinthumbnailcontrol.ascx b/Website/controls/skinthumbnailcontrol.ascx new file mode 100644 index 00000000000..36df4b40560 --- /dev/null +++ b/Website/controls/skinthumbnailcontrol.ascx @@ -0,0 +1,4 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.Skins.SkinThumbNailControl" targetSchema="http://schemas.microsoft.com/intellisense/ie5"%> +
    + +
    diff --git a/Website/controls/texteditor.ascx b/Website/controls/texteditor.ascx new file mode 100644 index 00000000000..c763c86bf20 --- /dev/null +++ b/Website/controls/texteditor.ascx @@ -0,0 +1,22 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.TextEditor" %> +<%@ Register TagPrefix="dnn" TagName="label" Src="~/controls/labelControl.ascx" %> +
    + + + + + + + +
    + +
    + + +
    +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/Website/controls/urlcontrol.ascx b/Website/controls/urlcontrol.ascx new file mode 100644 index 00000000000..4584e637ef5 --- /dev/null +++ b/Website/controls/urlcontrol.ascx @@ -0,0 +1,58 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.UrlControl" %> +
    + + + + + + +
    + + + + + +
    +
    + + + + + +
    + +
    + + +
    +
    +
    + +
    + + +
    +
    +
    + + + +
    +
    + + + + + + + + + + + +
    + + + +
    +
    diff --git a/Website/controls/urltrackingcontrol.ascx b/Website/controls/urltrackingcontrol.ascx new file mode 100644 index 00000000000..48c0254d362 --- /dev/null +++ b/Website/controls/urltrackingcontrol.ascx @@ -0,0 +1,54 @@ +<%@ Control Language="C#" AutoEventWireup="false" Explicit="true" Inherits="DotNetNuke.UI.UserControls.URLTrackingControl" %> +
    +
    + + + +
    +
    + + +
    + +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    + + + +
    +
    + + + +
    +
      +
    • +
    + + + + + + + + + + + + + +
    +
    \ No newline at end of file diff --git a/Website/controls/user.ascx b/Website/controls/user.ascx new file mode 100644 index 00000000000..5c727b00300 --- /dev/null +++ b/Website/controls/user.ascx @@ -0,0 +1,76 @@ +<%@ Control Language="C#" AutoEventWireup="false" Inherits="DotNetNuke.UI.UserControls.User" %> +<%@ Register TagPrefix="wc" Namespace="DotNetNuke.UI.WebControls" Assembly="CountryListBox" %> +<%@ Register TagPrefix="dnn" TagName="label" Src="~/controls/labelControl.ascx" %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +  * +
    + +  * +
    + + + * + +
    + +  * +
    + +  * + +
    + +  * + +
    + +
    + +
    diff --git a/Website/development.config b/Website/development.config new file mode 100644 index 00000000000..b6dd00dab74 --- /dev/null +++ b/Website/development.config @@ -0,0 +1,351 @@ + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Website/favicon.ico b/Website/favicon.ico new file mode 100644 index 00000000000..a050b08afd0 Binary files /dev/null and b/Website/favicon.ico differ diff --git a/Website/images/1x1.GIF b/Website/images/1x1.GIF new file mode 100644 index 00000000000..35d42e808f0 Binary files /dev/null and b/Website/images/1x1.GIF differ diff --git a/Website/images/403-3.gif b/Website/images/403-3.gif new file mode 100644 index 00000000000..17d19c7909f Binary files /dev/null and b/Website/images/403-3.gif differ diff --git a/Website/images/Blue-Info.gif b/Website/images/Blue-Info.gif new file mode 100644 index 00000000000..bd69cbe5bd1 Binary files /dev/null and b/Website/images/Blue-Info.gif differ diff --git a/Website/images/Branding/DNN_logo.png b/Website/images/Branding/DNN_logo.png new file mode 100644 index 00000000000..fa71e119ae0 Binary files /dev/null and b/Website/images/Branding/DNN_logo.png differ diff --git a/Website/images/Branding/Logo.png b/Website/images/Branding/Logo.png new file mode 100644 index 00000000000..ee773aec5f2 Binary files /dev/null and b/Website/images/Branding/Logo.png differ diff --git a/Website/images/Branding/iconbar_logo.png b/Website/images/Branding/iconbar_logo.png new file mode 100644 index 00000000000..8646fa030f6 Binary files /dev/null and b/Website/images/Branding/iconbar_logo.png differ diff --git a/Website/images/Branding/logo.gif b/Website/images/Branding/logo.gif new file mode 100644 index 00000000000..dbb3cf3650a Binary files /dev/null and b/Website/images/Branding/logo.gif differ diff --git a/Website/images/FileManager/DNNExplorer_Cancel.gif b/Website/images/FileManager/DNNExplorer_Cancel.gif new file mode 100644 index 00000000000..76ebeb11ec3 Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_Cancel.gif differ diff --git a/Website/images/FileManager/DNNExplorer_OK.gif b/Website/images/FileManager/DNNExplorer_OK.gif new file mode 100644 index 00000000000..955949c50ba Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_OK.gif differ diff --git a/Website/images/FileManager/DNNExplorer_Unzip.gif b/Website/images/FileManager/DNNExplorer_Unzip.gif new file mode 100644 index 00000000000..f848de0cfd4 Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_Unzip.gif differ diff --git a/Website/images/FileManager/DNNExplorer_edit.gif b/Website/images/FileManager/DNNExplorer_edit.gif new file mode 100644 index 00000000000..1a014b2f0d3 Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_edit.gif differ diff --git a/Website/images/FileManager/DNNExplorer_edit_disabled.gif b/Website/images/FileManager/DNNExplorer_edit_disabled.gif new file mode 100644 index 00000000000..eaa5578b4bd Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_edit_disabled.gif differ diff --git a/Website/images/FileManager/DNNExplorer_folder.small.gif b/Website/images/FileManager/DNNExplorer_folder.small.gif new file mode 100644 index 00000000000..4fca8e6d5fe Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_folder.small.gif differ diff --git a/Website/images/FileManager/DNNExplorer_trash.gif b/Website/images/FileManager/DNNExplorer_trash.gif new file mode 100644 index 00000000000..1027dfac833 Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_trash.gif differ diff --git a/Website/images/FileManager/DNNExplorer_trash_disabled.gif b/Website/images/FileManager/DNNExplorer_trash_disabled.gif new file mode 100644 index 00000000000..3324ebebd0e Binary files /dev/null and b/Website/images/FileManager/DNNExplorer_trash_disabled.gif differ diff --git a/Website/images/FileManager/FolderPropertiesDisabled.gif b/Website/images/FileManager/FolderPropertiesDisabled.gif new file mode 100644 index 00000000000..de873aad29e Binary files /dev/null and b/Website/images/FileManager/FolderPropertiesDisabled.gif differ diff --git a/Website/images/FileManager/FolderPropertiesEnabled.gif b/Website/images/FileManager/FolderPropertiesEnabled.gif new file mode 100644 index 00000000000..3b67be8c73a Binary files /dev/null and b/Website/images/FileManager/FolderPropertiesEnabled.gif differ diff --git a/Website/images/FileManager/Icons/ClosedFolder.gif b/Website/images/FileManager/Icons/ClosedFolder.gif new file mode 100644 index 00000000000..534e5387d2b Binary files /dev/null and b/Website/images/FileManager/Icons/ClosedFolder.gif differ diff --git a/Website/images/FileManager/Icons/Copy.gif b/Website/images/FileManager/Icons/Copy.gif new file mode 100644 index 00000000000..aaf50abd438 Binary files /dev/null and b/Website/images/FileManager/Icons/Copy.gif differ diff --git a/Website/images/FileManager/Icons/Move.gif b/Website/images/FileManager/Icons/Move.gif new file mode 100644 index 00000000000..bf97ae8d86f Binary files /dev/null and b/Website/images/FileManager/Icons/Move.gif differ diff --git a/Website/images/FileManager/Icons/arj.gif b/Website/images/FileManager/Icons/arj.gif new file mode 100644 index 00000000000..ee243a969c7 Binary files /dev/null and b/Website/images/FileManager/Icons/arj.gif differ diff --git a/Website/images/FileManager/Icons/asa.gif b/Website/images/FileManager/Icons/asa.gif new file mode 100644 index 00000000000..5d410cc4397 Binary files /dev/null and b/Website/images/FileManager/Icons/asa.gif differ diff --git a/Website/images/FileManager/Icons/asax.gif b/Website/images/FileManager/Icons/asax.gif new file mode 100644 index 00000000000..5d410cc4397 Binary files /dev/null and b/Website/images/FileManager/Icons/asax.gif differ diff --git a/Website/images/FileManager/Icons/ascx.gif b/Website/images/FileManager/Icons/ascx.gif new file mode 100644 index 00000000000..a26cef1ec4b Binary files /dev/null and b/Website/images/FileManager/Icons/ascx.gif differ diff --git a/Website/images/FileManager/Icons/asmx.gif b/Website/images/FileManager/Icons/asmx.gif new file mode 100644 index 00000000000..2e8902ee774 Binary files /dev/null and b/Website/images/FileManager/Icons/asmx.gif differ diff --git a/Website/images/FileManager/Icons/asp.gif b/Website/images/FileManager/Icons/asp.gif new file mode 100644 index 00000000000..5d410cc4397 Binary files /dev/null and b/Website/images/FileManager/Icons/asp.gif differ diff --git a/Website/images/FileManager/Icons/aspx.gif b/Website/images/FileManager/Icons/aspx.gif new file mode 100644 index 00000000000..c3ff96c0f02 Binary files /dev/null and b/Website/images/FileManager/Icons/aspx.gif differ diff --git a/Website/images/FileManager/Icons/au.gif b/Website/images/FileManager/Icons/au.gif new file mode 100644 index 00000000000..2ed036461b4 Binary files /dev/null and b/Website/images/FileManager/Icons/au.gif differ diff --git a/Website/images/FileManager/Icons/avi.gif b/Website/images/FileManager/Icons/avi.gif new file mode 100644 index 00000000000..151c0dc0ef1 Binary files /dev/null and b/Website/images/FileManager/Icons/avi.gif differ diff --git a/Website/images/FileManager/Icons/bat.gif b/Website/images/FileManager/Icons/bat.gif new file mode 100644 index 00000000000..475137d1c15 Binary files /dev/null and b/Website/images/FileManager/Icons/bat.gif differ diff --git a/Website/images/FileManager/Icons/bmp.gif b/Website/images/FileManager/Icons/bmp.gif new file mode 100644 index 00000000000..19ac6bd2c0e Binary files /dev/null and b/Website/images/FileManager/Icons/bmp.gif differ diff --git a/Website/images/FileManager/Icons/cab.gif b/Website/images/FileManager/Icons/cab.gif new file mode 100644 index 00000000000..ee243a969c7 Binary files /dev/null and b/Website/images/FileManager/Icons/cab.gif differ diff --git a/Website/images/FileManager/Icons/chm.gif b/Website/images/FileManager/Icons/chm.gif new file mode 100644 index 00000000000..b7573e02d80 Binary files /dev/null and b/Website/images/FileManager/Icons/chm.gif differ diff --git a/Website/images/FileManager/Icons/com.gif b/Website/images/FileManager/Icons/com.gif new file mode 100644 index 00000000000..0f99d84e4b9 Binary files /dev/null and b/Website/images/FileManager/Icons/com.gif differ diff --git a/Website/images/FileManager/Icons/config.gif b/Website/images/FileManager/Icons/config.gif new file mode 100644 index 00000000000..27b79b28209 Binary files /dev/null and b/Website/images/FileManager/Icons/config.gif differ diff --git a/Website/images/FileManager/Icons/cs.gif b/Website/images/FileManager/Icons/cs.gif new file mode 100644 index 00000000000..d7ac47bc7e8 Binary files /dev/null and b/Website/images/FileManager/Icons/cs.gif differ diff --git a/Website/images/FileManager/Icons/css.gif b/Website/images/FileManager/Icons/css.gif new file mode 100644 index 00000000000..d7e6a5dceac Binary files /dev/null and b/Website/images/FileManager/Icons/css.gif differ diff --git a/Website/images/FileManager/Icons/disco.gif b/Website/images/FileManager/Icons/disco.gif new file mode 100644 index 00000000000..0cdb4258327 Binary files /dev/null and b/Website/images/FileManager/Icons/disco.gif differ diff --git a/Website/images/FileManager/Icons/dll.gif b/Website/images/FileManager/Icons/dll.gif new file mode 100644 index 00000000000..ff4ce1996f5 Binary files /dev/null and b/Website/images/FileManager/Icons/dll.gif differ diff --git a/Website/images/FileManager/Icons/doc.gif b/Website/images/FileManager/Icons/doc.gif new file mode 100644 index 00000000000..83e7ded6adf Binary files /dev/null and b/Website/images/FileManager/Icons/doc.gif differ diff --git a/Website/images/FileManager/Icons/exe.gif b/Website/images/FileManager/Icons/exe.gif new file mode 100644 index 00000000000..0f99d84e4b9 Binary files /dev/null and b/Website/images/FileManager/Icons/exe.gif differ diff --git a/Website/images/FileManager/Icons/file.gif b/Website/images/FileManager/Icons/file.gif new file mode 100644 index 00000000000..b91cd9ea482 Binary files /dev/null and b/Website/images/FileManager/Icons/file.gif differ diff --git a/Website/images/FileManager/Icons/gif.gif b/Website/images/FileManager/Icons/gif.gif new file mode 100644 index 00000000000..4e66341779a Binary files /dev/null and b/Website/images/FileManager/Icons/gif.gif differ diff --git a/Website/images/FileManager/Icons/hlp.gif b/Website/images/FileManager/Icons/hlp.gif new file mode 100644 index 00000000000..b7573e02d80 Binary files /dev/null and b/Website/images/FileManager/Icons/hlp.gif differ diff --git a/Website/images/FileManager/Icons/htm.gif b/Website/images/FileManager/Icons/htm.gif new file mode 100644 index 00000000000..7e94faa604b Binary files /dev/null and b/Website/images/FileManager/Icons/htm.gif differ diff --git a/Website/images/FileManager/Icons/html.gif b/Website/images/FileManager/Icons/html.gif new file mode 100644 index 00000000000..7e94faa604b Binary files /dev/null and b/Website/images/FileManager/Icons/html.gif differ diff --git a/Website/images/FileManager/Icons/inc.gif b/Website/images/FileManager/Icons/inc.gif new file mode 100644 index 00000000000..5d410cc4397 Binary files /dev/null and b/Website/images/FileManager/Icons/inc.gif differ diff --git a/Website/images/FileManager/Icons/ini.gif b/Website/images/FileManager/Icons/ini.gif new file mode 100644 index 00000000000..d7e6a5dceac Binary files /dev/null and b/Website/images/FileManager/Icons/ini.gif differ diff --git a/Website/images/FileManager/Icons/jpg.gif b/Website/images/FileManager/Icons/jpg.gif new file mode 100644 index 00000000000..fbeee6b13d9 Binary files /dev/null and b/Website/images/FileManager/Icons/jpg.gif differ diff --git a/Website/images/FileManager/Icons/js.gif b/Website/images/FileManager/Icons/js.gif new file mode 100644 index 00000000000..d527712becb Binary files /dev/null and b/Website/images/FileManager/Icons/js.gif differ diff --git a/Website/images/FileManager/Icons/log.gif b/Website/images/FileManager/Icons/log.gif new file mode 100644 index 00000000000..00629862c4c Binary files /dev/null and b/Website/images/FileManager/Icons/log.gif differ diff --git a/Website/images/FileManager/Icons/mdb.gif b/Website/images/FileManager/Icons/mdb.gif new file mode 100644 index 00000000000..1136bba008a Binary files /dev/null and b/Website/images/FileManager/Icons/mdb.gif differ diff --git a/Website/images/FileManager/Icons/mid.gif b/Website/images/FileManager/Icons/mid.gif new file mode 100644 index 00000000000..1db370a4e99 Binary files /dev/null and b/Website/images/FileManager/Icons/mid.gif differ diff --git a/Website/images/FileManager/Icons/midi.gif b/Website/images/FileManager/Icons/midi.gif new file mode 100644 index 00000000000..17bcdc5a4bc Binary files /dev/null and b/Website/images/FileManager/Icons/midi.gif differ diff --git a/Website/images/FileManager/Icons/mov.gif b/Website/images/FileManager/Icons/mov.gif new file mode 100644 index 00000000000..151c0dc0ef1 Binary files /dev/null and b/Website/images/FileManager/Icons/mov.gif differ diff --git a/Website/images/FileManager/Icons/mp3.gif b/Website/images/FileManager/Icons/mp3.gif new file mode 100644 index 00000000000..1db370a4e99 Binary files /dev/null and b/Website/images/FileManager/Icons/mp3.gif differ diff --git a/Website/images/FileManager/Icons/mpeg.gif b/Website/images/FileManager/Icons/mpeg.gif new file mode 100644 index 00000000000..151c0dc0ef1 Binary files /dev/null and b/Website/images/FileManager/Icons/mpeg.gif differ diff --git a/Website/images/FileManager/Icons/mpg.gif b/Website/images/FileManager/Icons/mpg.gif new file mode 100644 index 00000000000..151c0dc0ef1 Binary files /dev/null and b/Website/images/FileManager/Icons/mpg.gif differ diff --git a/Website/images/FileManager/Icons/pdf.gif b/Website/images/FileManager/Icons/pdf.gif new file mode 100644 index 00000000000..13c17b5a565 Binary files /dev/null and b/Website/images/FileManager/Icons/pdf.gif differ diff --git a/Website/images/FileManager/Icons/ppt.gif b/Website/images/FileManager/Icons/ppt.gif new file mode 100644 index 00000000000..4f4c8c5d6a1 Binary files /dev/null and b/Website/images/FileManager/Icons/ppt.gif differ diff --git a/Website/images/FileManager/Icons/sys.gif b/Website/images/FileManager/Icons/sys.gif new file mode 100644 index 00000000000..ff4ce1996f5 Binary files /dev/null and b/Website/images/FileManager/Icons/sys.gif differ diff --git a/Website/images/FileManager/Icons/tif.gif b/Website/images/FileManager/Icons/tif.gif new file mode 100644 index 00000000000..bc2eb41ae65 Binary files /dev/null and b/Website/images/FileManager/Icons/tif.gif differ diff --git a/Website/images/FileManager/Icons/txt.gif b/Website/images/FileManager/Icons/txt.gif new file mode 100644 index 00000000000..00629862c4c Binary files /dev/null and b/Website/images/FileManager/Icons/txt.gif differ diff --git a/Website/images/FileManager/Icons/vb.gif b/Website/images/FileManager/Icons/vb.gif new file mode 100644 index 00000000000..3f5e0a4e8c3 Binary files /dev/null and b/Website/images/FileManager/Icons/vb.gif differ diff --git a/Website/images/FileManager/Icons/vbs.gif b/Website/images/FileManager/Icons/vbs.gif new file mode 100644 index 00000000000..7ef9dd95bb5 Binary files /dev/null and b/Website/images/FileManager/Icons/vbs.gif differ diff --git a/Website/images/FileManager/Icons/vsdisco.gif b/Website/images/FileManager/Icons/vsdisco.gif new file mode 100644 index 00000000000..0cdb4258327 Binary files /dev/null and b/Website/images/FileManager/Icons/vsdisco.gif differ diff --git a/Website/images/FileManager/Icons/wav.gif b/Website/images/FileManager/Icons/wav.gif new file mode 100644 index 00000000000..1db370a4e99 Binary files /dev/null and b/Website/images/FileManager/Icons/wav.gif differ diff --git a/Website/images/FileManager/Icons/wri.gif b/Website/images/FileManager/Icons/wri.gif new file mode 100644 index 00000000000..3d49674c149 Binary files /dev/null and b/Website/images/FileManager/Icons/wri.gif differ diff --git a/Website/images/FileManager/Icons/xls.gif b/Website/images/FileManager/Icons/xls.gif new file mode 100644 index 00000000000..68fd2cafb3a Binary files /dev/null and b/Website/images/FileManager/Icons/xls.gif differ diff --git a/Website/images/FileManager/Icons/xml.gif b/Website/images/FileManager/Icons/xml.gif new file mode 100644 index 00000000000..a3513618f06 Binary files /dev/null and b/Website/images/FileManager/Icons/xml.gif differ diff --git a/Website/images/FileManager/Icons/zip.gif b/Website/images/FileManager/Icons/zip.gif new file mode 100644 index 00000000000..ee243a969c7 Binary files /dev/null and b/Website/images/FileManager/Icons/zip.gif differ diff --git a/Website/images/FileManager/MoveFirst.gif b/Website/images/FileManager/MoveFirst.gif new file mode 100644 index 00000000000..ae655be2ab9 Binary files /dev/null and b/Website/images/FileManager/MoveFirst.gif differ diff --git a/Website/images/FileManager/MoveLast.gif b/Website/images/FileManager/MoveLast.gif new file mode 100644 index 00000000000..b62fc938210 Binary files /dev/null and b/Website/images/FileManager/MoveLast.gif differ diff --git a/Website/images/FileManager/MoveNext.gif b/Website/images/FileManager/MoveNext.gif new file mode 100644 index 00000000000..eed84255e00 Binary files /dev/null and b/Website/images/FileManager/MoveNext.gif differ diff --git a/Website/images/FileManager/MovePrevious.gif b/Website/images/FileManager/MovePrevious.gif new file mode 100644 index 00000000000..b18f5e912a0 Binary files /dev/null and b/Website/images/FileManager/MovePrevious.gif differ diff --git a/Website/images/FileManager/ToolBarAddFolderDisabled.gif b/Website/images/FileManager/ToolBarAddFolderDisabled.gif new file mode 100644 index 00000000000..5dc711080ca Binary files /dev/null and b/Website/images/FileManager/ToolBarAddFolderDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarAddFolderEnabled.gif b/Website/images/FileManager/ToolBarAddFolderEnabled.gif new file mode 100644 index 00000000000..890c0dcdd3a Binary files /dev/null and b/Website/images/FileManager/ToolBarAddFolderEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarCopyDisabled.gif b/Website/images/FileManager/ToolBarCopyDisabled.gif new file mode 100644 index 00000000000..05bb3e68c05 Binary files /dev/null and b/Website/images/FileManager/ToolBarCopyDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarCopyEnabled.gif b/Website/images/FileManager/ToolBarCopyEnabled.gif new file mode 100644 index 00000000000..08dc29c32e8 Binary files /dev/null and b/Website/images/FileManager/ToolBarCopyEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarDelFolderDisabled.gif b/Website/images/FileManager/ToolBarDelFolderDisabled.gif new file mode 100644 index 00000000000..a5b6bb6e07c Binary files /dev/null and b/Website/images/FileManager/ToolBarDelFolderDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarDelFolderEnabled.gif b/Website/images/FileManager/ToolBarDelFolderEnabled.gif new file mode 100644 index 00000000000..9e48d863bb4 Binary files /dev/null and b/Website/images/FileManager/ToolBarDelFolderEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarDeleteDisabled.gif b/Website/images/FileManager/ToolBarDeleteDisabled.gif new file mode 100644 index 00000000000..150da904ff3 Binary files /dev/null and b/Website/images/FileManager/ToolBarDeleteDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarDeleteEnabled.gif b/Website/images/FileManager/ToolBarDeleteEnabled.gif new file mode 100644 index 00000000000..76ebeb11ec3 Binary files /dev/null and b/Website/images/FileManager/ToolBarDeleteEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarEmailDisabled.gif b/Website/images/FileManager/ToolBarEmailDisabled.gif new file mode 100644 index 00000000000..f7b83edd6e3 Binary files /dev/null and b/Website/images/FileManager/ToolBarEmailDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarEmailEnabled.gif b/Website/images/FileManager/ToolBarEmailEnabled.gif new file mode 100644 index 00000000000..3d65d6fa9cc Binary files /dev/null and b/Website/images/FileManager/ToolBarEmailEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarFilterDisabled.gif b/Website/images/FileManager/ToolBarFilterDisabled.gif new file mode 100644 index 00000000000..5d62769ffb4 Binary files /dev/null and b/Website/images/FileManager/ToolBarFilterDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarFilterEnabled.gif b/Website/images/FileManager/ToolBarFilterEnabled.gif new file mode 100644 index 00000000000..ce6aeacd8ce Binary files /dev/null and b/Website/images/FileManager/ToolBarFilterEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarMoveDisabled.gif b/Website/images/FileManager/ToolBarMoveDisabled.gif new file mode 100644 index 00000000000..6021dd29b35 Binary files /dev/null and b/Website/images/FileManager/ToolBarMoveDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarMoveEnabled.gif b/Website/images/FileManager/ToolBarMoveEnabled.gif new file mode 100644 index 00000000000..1bb12ac3859 Binary files /dev/null and b/Website/images/FileManager/ToolBarMoveEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarRefreshDisabled.gif b/Website/images/FileManager/ToolBarRefreshDisabled.gif new file mode 100644 index 00000000000..bff7c7cb575 Binary files /dev/null and b/Website/images/FileManager/ToolBarRefreshDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarRefreshEnabled.gif b/Website/images/FileManager/ToolBarRefreshEnabled.gif new file mode 100644 index 00000000000..147f98ba04d Binary files /dev/null and b/Website/images/FileManager/ToolBarRefreshEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarSynchronizeDisabled.gif b/Website/images/FileManager/ToolBarSynchronizeDisabled.gif new file mode 100644 index 00000000000..d59bd0e5a52 Binary files /dev/null and b/Website/images/FileManager/ToolBarSynchronizeDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarSynchronizeEnabled.gif b/Website/images/FileManager/ToolBarSynchronizeEnabled.gif new file mode 100644 index 00000000000..4907c07b819 Binary files /dev/null and b/Website/images/FileManager/ToolBarSynchronizeEnabled.gif differ diff --git a/Website/images/FileManager/ToolBarUploadDisabled.gif b/Website/images/FileManager/ToolBarUploadDisabled.gif new file mode 100644 index 00000000000..ba41dea840b Binary files /dev/null and b/Website/images/FileManager/ToolBarUploadDisabled.gif differ diff --git a/Website/images/FileManager/ToolBarUploadEnabled.gif b/Website/images/FileManager/ToolBarUploadEnabled.gif new file mode 100644 index 00000000000..2c4a1b120aa Binary files /dev/null and b/Website/images/FileManager/ToolBarUploadEnabled.gif differ diff --git a/Website/images/FileManager/checked.gif b/Website/images/FileManager/checked.gif new file mode 100644 index 00000000000..f46ce61a02e Binary files /dev/null and b/Website/images/FileManager/checked.gif differ diff --git a/Website/images/FileManager/files/Download.gif b/Website/images/FileManager/files/Download.gif new file mode 100644 index 00000000000..6d9c46a54df Binary files /dev/null and b/Website/images/FileManager/files/Download.gif differ diff --git a/Website/images/FileManager/files/Edit.gif b/Website/images/FileManager/files/Edit.gif new file mode 100644 index 00000000000..bd2f7bffd74 Binary files /dev/null and b/Website/images/FileManager/files/Edit.gif differ diff --git a/Website/images/FileManager/files/NewFile.gif b/Website/images/FileManager/files/NewFile.gif new file mode 100644 index 00000000000..e6da5cb51a4 Binary files /dev/null and b/Website/images/FileManager/files/NewFile.gif differ diff --git a/Website/images/FileManager/files/NewFolder.gif b/Website/images/FileManager/files/NewFolder.gif new file mode 100644 index 00000000000..3f618801482 Binary files /dev/null and b/Website/images/FileManager/files/NewFolder.gif differ diff --git a/Website/images/FileManager/files/NewFolder_Disabled.gif b/Website/images/FileManager/files/NewFolder_Disabled.gif new file mode 100644 index 00000000000..6eddb74ca67 Binary files /dev/null and b/Website/images/FileManager/files/NewFolder_Disabled.gif differ diff --git a/Website/images/FileManager/files/NewFolder_Rollover.gif b/Website/images/FileManager/files/NewFolder_Rollover.gif new file mode 100644 index 00000000000..ee3307f9743 Binary files /dev/null and b/Website/images/FileManager/files/NewFolder_Rollover.gif differ diff --git a/Website/images/FileManager/files/OK.gif b/Website/images/FileManager/files/OK.gif new file mode 100644 index 00000000000..5e2a3b0c2a6 Binary files /dev/null and b/Website/images/FileManager/files/OK.gif differ diff --git a/Website/images/FileManager/files/OK_Disabled.gif b/Website/images/FileManager/files/OK_Disabled.gif new file mode 100644 index 00000000000..3f42c7c5d38 Binary files /dev/null and b/Website/images/FileManager/files/OK_Disabled.gif differ diff --git a/Website/images/FileManager/files/OK_Rollover.gif b/Website/images/FileManager/files/OK_Rollover.gif new file mode 100644 index 00000000000..efb42dd1aa2 Binary files /dev/null and b/Website/images/FileManager/files/OK_Rollover.gif differ diff --git a/Website/images/FileManager/files/OpenFolder.gif b/Website/images/FileManager/files/OpenFolder.gif new file mode 100644 index 00000000000..e9360318b2c Binary files /dev/null and b/Website/images/FileManager/files/OpenFolder.gif differ diff --git a/Website/images/FileManager/files/ParentFolder.gif b/Website/images/FileManager/files/ParentFolder.gif new file mode 100644 index 00000000000..14302bcc46d Binary files /dev/null and b/Website/images/FileManager/files/ParentFolder.gif differ diff --git a/Website/images/FileManager/files/ParentFolder_Disabled.gif b/Website/images/FileManager/files/ParentFolder_Disabled.gif new file mode 100644 index 00000000000..ef36bbe13ac Binary files /dev/null and b/Website/images/FileManager/files/ParentFolder_Disabled.gif differ diff --git a/Website/images/FileManager/files/ParentFolder_Rollover.gif b/Website/images/FileManager/files/ParentFolder_Rollover.gif new file mode 100644 index 00000000000..3c281576bec Binary files /dev/null and b/Website/images/FileManager/files/ParentFolder_Rollover.gif differ diff --git a/Website/images/FileManager/files/Properties.gif b/Website/images/FileManager/files/Properties.gif new file mode 100644 index 00000000000..dc962e470df Binary files /dev/null and b/Website/images/FileManager/files/Properties.gif differ diff --git a/Website/images/FileManager/files/Recycle.gif b/Website/images/FileManager/files/Recycle.gif new file mode 100644 index 00000000000..27697bcd443 Binary files /dev/null and b/Website/images/FileManager/files/Recycle.gif differ diff --git a/Website/images/FileManager/files/Recycle_Rollover.gif b/Website/images/FileManager/files/Recycle_Rollover.gif new file mode 100644 index 00000000000..f31364391e3 Binary files /dev/null and b/Website/images/FileManager/files/Recycle_Rollover.gif differ diff --git a/Website/images/FileManager/files/Rename.gif b/Website/images/FileManager/files/Rename.gif new file mode 100644 index 00000000000..446fc17b37f Binary files /dev/null and b/Website/images/FileManager/files/Rename.gif differ diff --git a/Website/images/FileManager/files/Rename_Disabled.gif b/Website/images/FileManager/files/Rename_Disabled.gif new file mode 100644 index 00000000000..dff8a60d04f Binary files /dev/null and b/Website/images/FileManager/files/Rename_Disabled.gif differ diff --git a/Website/images/FileManager/files/Rename_Rollover.gif b/Website/images/FileManager/files/Rename_Rollover.gif new file mode 100644 index 00000000000..8b52233813d Binary files /dev/null and b/Website/images/FileManager/files/Rename_Rollover.gif differ diff --git a/Website/images/FileManager/files/ToolSep.gif b/Website/images/FileManager/files/ToolSep.gif new file mode 100644 index 00000000000..7291c8f2cd6 Binary files /dev/null and b/Website/images/FileManager/files/ToolSep.gif differ diff --git a/Website/images/FileManager/files/ToolThumb.gif b/Website/images/FileManager/files/ToolThumb.gif new file mode 100644 index 00000000000..b095ce3e595 Binary files /dev/null and b/Website/images/FileManager/files/ToolThumb.gif differ diff --git a/Website/images/FileManager/files/Upload.gif b/Website/images/FileManager/files/Upload.gif new file mode 100644 index 00000000000..04cd7fc9bcb Binary files /dev/null and b/Website/images/FileManager/files/Upload.gif differ diff --git a/Website/images/FileManager/files/Upload_Disabled.gif b/Website/images/FileManager/files/Upload_Disabled.gif new file mode 100644 index 00000000000..a8f601fbb6e Binary files /dev/null and b/Website/images/FileManager/files/Upload_Disabled.gif differ diff --git a/Website/images/FileManager/files/Upload_Rollover.gif b/Website/images/FileManager/files/Upload_Rollover.gif new file mode 100644 index 00000000000..c0b6aead949 Binary files /dev/null and b/Website/images/FileManager/files/Upload_Rollover.gif differ diff --git a/Website/images/FileManager/files/Write.gif b/Website/images/FileManager/files/Write.gif new file mode 100644 index 00000000000..fe34e760b4d Binary files /dev/null and b/Website/images/FileManager/files/Write.gif differ diff --git a/Website/images/FileManager/files/blank.gif b/Website/images/FileManager/files/blank.gif new file mode 100644 index 00000000000..ee311d08e1c Binary files /dev/null and b/Website/images/FileManager/files/blank.gif differ diff --git a/Website/images/FileManager/files/desc.gif b/Website/images/FileManager/files/desc.gif new file mode 100644 index 00000000000..f8431f2321b Binary files /dev/null and b/Website/images/FileManager/files/desc.gif differ diff --git a/Website/images/FileManager/files/unknown.gif b/Website/images/FileManager/files/unknown.gif new file mode 100644 index 00000000000..b6c55fb2986 Binary files /dev/null and b/Website/images/FileManager/files/unknown.gif differ diff --git a/Website/images/FileManager/files/zip.gif b/Website/images/FileManager/files/zip.gif new file mode 100644 index 00000000000..ee243a969c7 Binary files /dev/null and b/Website/images/FileManager/files/zip.gif differ diff --git a/Website/images/FileManager/unchecked.gif b/Website/images/FileManager/unchecked.gif new file mode 100644 index 00000000000..fc10d87c16c Binary files /dev/null and b/Website/images/FileManager/unchecked.gif differ diff --git a/Website/images/Flags/None.gif b/Website/images/Flags/None.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/None.gif differ diff --git a/Website/images/Flags/af-ZA.gif b/Website/images/Flags/af-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/af-ZA.gif differ diff --git a/Website/images/Flags/am-ET.gif b/Website/images/Flags/am-ET.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/am-ET.gif differ diff --git a/Website/images/Flags/ar-AE.gif b/Website/images/Flags/ar-AE.gif new file mode 100644 index 00000000000..6d7b07d061e Binary files /dev/null and b/Website/images/Flags/ar-AE.gif differ diff --git a/Website/images/Flags/ar-BH.gif b/Website/images/Flags/ar-BH.gif new file mode 100644 index 00000000000..b447aeff3e5 Binary files /dev/null and b/Website/images/Flags/ar-BH.gif differ diff --git a/Website/images/Flags/ar-DZ.gif b/Website/images/Flags/ar-DZ.gif new file mode 100644 index 00000000000..5e423573e34 Binary files /dev/null and b/Website/images/Flags/ar-DZ.gif differ diff --git a/Website/images/Flags/ar-EG.gif b/Website/images/Flags/ar-EG.gif new file mode 100644 index 00000000000..8ba6a31c3b0 Binary files /dev/null and b/Website/images/Flags/ar-EG.gif differ diff --git a/Website/images/Flags/ar-IQ.gif b/Website/images/Flags/ar-IQ.gif new file mode 100644 index 00000000000..f692c1c642e Binary files /dev/null and b/Website/images/Flags/ar-IQ.gif differ diff --git a/Website/images/Flags/ar-JO.gif b/Website/images/Flags/ar-JO.gif new file mode 100644 index 00000000000..2745cea7226 Binary files /dev/null and b/Website/images/Flags/ar-JO.gif differ diff --git a/Website/images/Flags/ar-KW.gif b/Website/images/Flags/ar-KW.gif new file mode 100644 index 00000000000..065ab43ece2 Binary files /dev/null and b/Website/images/Flags/ar-KW.gif differ diff --git a/Website/images/Flags/ar-LB.gif b/Website/images/Flags/ar-LB.gif new file mode 100644 index 00000000000..d3d37ba24f4 Binary files /dev/null and b/Website/images/Flags/ar-LB.gif differ diff --git a/Website/images/Flags/ar-LY.gif b/Website/images/Flags/ar-LY.gif new file mode 100644 index 00000000000..559710c61d8 Binary files /dev/null and b/Website/images/Flags/ar-LY.gif differ diff --git a/Website/images/Flags/ar-MA.gif b/Website/images/Flags/ar-MA.gif new file mode 100644 index 00000000000..0d7bf24043a Binary files /dev/null and b/Website/images/Flags/ar-MA.gif differ diff --git a/Website/images/Flags/ar-OM.gif b/Website/images/Flags/ar-OM.gif new file mode 100644 index 00000000000..5762c5dbca6 Binary files /dev/null and b/Website/images/Flags/ar-OM.gif differ diff --git a/Website/images/Flags/ar-QA.gif b/Website/images/Flags/ar-QA.gif new file mode 100644 index 00000000000..b30f0a1db97 Binary files /dev/null and b/Website/images/Flags/ar-QA.gif differ diff --git a/Website/images/Flags/ar-SA.gif b/Website/images/Flags/ar-SA.gif new file mode 100644 index 00000000000..7bba3792763 Binary files /dev/null and b/Website/images/Flags/ar-SA.gif differ diff --git a/Website/images/Flags/ar-SY.gif b/Website/images/Flags/ar-SY.gif new file mode 100644 index 00000000000..0bc3d95e267 Binary files /dev/null and b/Website/images/Flags/ar-SY.gif differ diff --git a/Website/images/Flags/ar-TN.gif b/Website/images/Flags/ar-TN.gif new file mode 100644 index 00000000000..9d59a69998f Binary files /dev/null and b/Website/images/Flags/ar-TN.gif differ diff --git a/Website/images/Flags/ar-YE.gif b/Website/images/Flags/ar-YE.gif new file mode 100644 index 00000000000..4edbdbf4282 Binary files /dev/null and b/Website/images/Flags/ar-YE.gif differ diff --git a/Website/images/Flags/arn-CL.gif b/Website/images/Flags/arn-CL.gif new file mode 100644 index 00000000000..971a6dcd183 Binary files /dev/null and b/Website/images/Flags/arn-CL.gif differ diff --git a/Website/images/Flags/as-IN.gif b/Website/images/Flags/as-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/as-IN.gif differ diff --git a/Website/images/Flags/az-AZ-Cyrl.gif b/Website/images/Flags/az-AZ-Cyrl.gif new file mode 100644 index 00000000000..7f077ee0e30 Binary files /dev/null and b/Website/images/Flags/az-AZ-Cyrl.gif differ diff --git a/Website/images/Flags/az-AZ-Latn.gif b/Website/images/Flags/az-AZ-Latn.gif new file mode 100644 index 00000000000..7f077ee0e30 Binary files /dev/null and b/Website/images/Flags/az-AZ-Latn.gif differ diff --git a/Website/images/Flags/az-Cyrl-AZ.gif b/Website/images/Flags/az-Cyrl-AZ.gif new file mode 100644 index 00000000000..7f077ee0e30 Binary files /dev/null and b/Website/images/Flags/az-Cyrl-AZ.gif differ diff --git a/Website/images/Flags/az-Latn-AZ.gif b/Website/images/Flags/az-Latn-AZ.gif new file mode 100644 index 00000000000..7f077ee0e30 Binary files /dev/null and b/Website/images/Flags/az-Latn-AZ.gif differ diff --git a/Website/images/Flags/ba-RU.gif b/Website/images/Flags/ba-RU.gif new file mode 100644 index 00000000000..15bad9c1ead Binary files /dev/null and b/Website/images/Flags/ba-RU.gif differ diff --git a/Website/images/Flags/be-BY.gif b/Website/images/Flags/be-BY.gif new file mode 100644 index 00000000000..28aee3dfb84 Binary files /dev/null and b/Website/images/Flags/be-BY.gif differ diff --git a/Website/images/Flags/bg-BG.gif b/Website/images/Flags/bg-BG.gif new file mode 100644 index 00000000000..bca112c707d Binary files /dev/null and b/Website/images/Flags/bg-BG.gif differ diff --git a/Website/images/Flags/bn-BD.gif b/Website/images/Flags/bn-BD.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/bn-BD.gif differ diff --git a/Website/images/Flags/bn-IN.gif b/Website/images/Flags/bn-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/bn-IN.gif differ diff --git a/Website/images/Flags/bo-CN.gif b/Website/images/Flags/bo-CN.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/bo-CN.gif differ diff --git a/Website/images/Flags/br-FR.gif b/Website/images/Flags/br-FR.gif new file mode 100644 index 00000000000..ba4c44abd47 Binary files /dev/null and b/Website/images/Flags/br-FR.gif differ diff --git a/Website/images/Flags/bs-Cyrl-BA.gif b/Website/images/Flags/bs-Cyrl-BA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/bs-Cyrl-BA.gif differ diff --git a/Website/images/Flags/bs-Latn-BA.gif b/Website/images/Flags/bs-Latn-BA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/bs-Latn-BA.gif differ diff --git a/Website/images/Flags/ca-ES.gif b/Website/images/Flags/ca-ES.gif new file mode 100644 index 00000000000..6d47e647f10 Binary files /dev/null and b/Website/images/Flags/ca-ES.gif differ diff --git a/Website/images/Flags/co-FR.gif b/Website/images/Flags/co-FR.gif new file mode 100644 index 00000000000..ba4c44abd47 Binary files /dev/null and b/Website/images/Flags/co-FR.gif differ diff --git a/Website/images/Flags/cs-CZ.gif b/Website/images/Flags/cs-CZ.gif new file mode 100644 index 00000000000..2462779f23c Binary files /dev/null and b/Website/images/Flags/cs-CZ.gif differ diff --git a/Website/images/Flags/cy-GB.gif b/Website/images/Flags/cy-GB.gif new file mode 100644 index 00000000000..711c74473e1 Binary files /dev/null and b/Website/images/Flags/cy-GB.gif differ diff --git a/Website/images/Flags/da-DK.gif b/Website/images/Flags/da-DK.gif new file mode 100644 index 00000000000..ff45105fd67 Binary files /dev/null and b/Website/images/Flags/da-DK.gif differ diff --git a/Website/images/Flags/de-AT.gif b/Website/images/Flags/de-AT.gif new file mode 100644 index 00000000000..8ade0b65909 Binary files /dev/null and b/Website/images/Flags/de-AT.gif differ diff --git a/Website/images/Flags/de-CH.gif b/Website/images/Flags/de-CH.gif new file mode 100644 index 00000000000..247e1ff2d65 Binary files /dev/null and b/Website/images/Flags/de-CH.gif differ diff --git a/Website/images/Flags/de-DE.gif b/Website/images/Flags/de-DE.gif new file mode 100644 index 00000000000..a98f4c72bf5 Binary files /dev/null and b/Website/images/Flags/de-DE.gif differ diff --git a/Website/images/Flags/de-LI.gif b/Website/images/Flags/de-LI.gif new file mode 100644 index 00000000000..ad19af6c5d3 Binary files /dev/null and b/Website/images/Flags/de-LI.gif differ diff --git a/Website/images/Flags/de-LU.gif b/Website/images/Flags/de-LU.gif new file mode 100644 index 00000000000..47ee0c135b1 Binary files /dev/null and b/Website/images/Flags/de-LU.gif differ diff --git a/Website/images/Flags/div-MV.gif b/Website/images/Flags/div-MV.gif new file mode 100644 index 00000000000..c88ed794a30 Binary files /dev/null and b/Website/images/Flags/div-MV.gif differ diff --git a/Website/images/Flags/dsb-DE.gif b/Website/images/Flags/dsb-DE.gif new file mode 100644 index 00000000000..a98f4c72bf5 Binary files /dev/null and b/Website/images/Flags/dsb-DE.gif differ diff --git a/Website/images/Flags/dv-MV.gif b/Website/images/Flags/dv-MV.gif new file mode 100644 index 00000000000..c88ed794a30 Binary files /dev/null and b/Website/images/Flags/dv-MV.gif differ diff --git a/Website/images/Flags/el-GR.gif b/Website/images/Flags/el-GR.gif new file mode 100644 index 00000000000..1727aefbbdf Binary files /dev/null and b/Website/images/Flags/el-GR.gif differ diff --git a/Website/images/Flags/en-029.gif b/Website/images/Flags/en-029.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/en-029.gif differ diff --git a/Website/images/Flags/en-AU.gif b/Website/images/Flags/en-AU.gif new file mode 100644 index 00000000000..54d87f4de88 Binary files /dev/null and b/Website/images/Flags/en-AU.gif differ diff --git a/Website/images/Flags/en-BZ.gif b/Website/images/Flags/en-BZ.gif new file mode 100644 index 00000000000..7d98549e1b8 Binary files /dev/null and b/Website/images/Flags/en-BZ.gif differ diff --git a/Website/images/Flags/en-CA.gif b/Website/images/Flags/en-CA.gif new file mode 100644 index 00000000000..1c5d4397789 Binary files /dev/null and b/Website/images/Flags/en-CA.gif differ diff --git a/Website/images/Flags/en-CB.gif b/Website/images/Flags/en-CB.gif new file mode 100644 index 00000000000..2ac57d330ed Binary files /dev/null and b/Website/images/Flags/en-CB.gif differ diff --git a/Website/images/Flags/en-GB.gif b/Website/images/Flags/en-GB.gif new file mode 100644 index 00000000000..711c74473e1 Binary files /dev/null and b/Website/images/Flags/en-GB.gif differ diff --git a/Website/images/Flags/en-IE.gif b/Website/images/Flags/en-IE.gif new file mode 100644 index 00000000000..8466d3e7919 Binary files /dev/null and b/Website/images/Flags/en-IE.gif differ diff --git a/Website/images/Flags/en-IN.gif b/Website/images/Flags/en-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/en-IN.gif differ diff --git a/Website/images/Flags/en-JM.gif b/Website/images/Flags/en-JM.gif new file mode 100644 index 00000000000..a8554672356 Binary files /dev/null and b/Website/images/Flags/en-JM.gif differ diff --git a/Website/images/Flags/en-MY.gif b/Website/images/Flags/en-MY.gif new file mode 100644 index 00000000000..3203db3e47d Binary files /dev/null and b/Website/images/Flags/en-MY.gif differ diff --git a/Website/images/Flags/en-NZ.gif b/Website/images/Flags/en-NZ.gif new file mode 100644 index 00000000000..4f6409ad4b4 Binary files /dev/null and b/Website/images/Flags/en-NZ.gif differ diff --git a/Website/images/Flags/en-PH.gif b/Website/images/Flags/en-PH.gif new file mode 100644 index 00000000000..3e8b52e097d Binary files /dev/null and b/Website/images/Flags/en-PH.gif differ diff --git a/Website/images/Flags/en-SG.gif b/Website/images/Flags/en-SG.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/en-SG.gif differ diff --git a/Website/images/Flags/en-TT.gif b/Website/images/Flags/en-TT.gif new file mode 100644 index 00000000000..68aff2db944 Binary files /dev/null and b/Website/images/Flags/en-TT.gif differ diff --git a/Website/images/Flags/en-US.gif b/Website/images/Flags/en-US.gif new file mode 100644 index 00000000000..fa1b1a43006 Binary files /dev/null and b/Website/images/Flags/en-US.gif differ diff --git a/Website/images/Flags/en-ZA.gif b/Website/images/Flags/en-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/en-ZA.gif differ diff --git a/Website/images/Flags/en-ZW.gif b/Website/images/Flags/en-ZW.gif new file mode 100644 index 00000000000..9d3006c7103 Binary files /dev/null and b/Website/images/Flags/en-ZW.gif differ diff --git a/Website/images/Flags/es-AR.gif b/Website/images/Flags/es-AR.gif new file mode 100644 index 00000000000..a5d9ef32ff9 Binary files /dev/null and b/Website/images/Flags/es-AR.gif differ diff --git a/Website/images/Flags/es-BO.gif b/Website/images/Flags/es-BO.gif new file mode 100644 index 00000000000..63252223bf7 Binary files /dev/null and b/Website/images/Flags/es-BO.gif differ diff --git a/Website/images/Flags/es-CL.gif b/Website/images/Flags/es-CL.gif new file mode 100644 index 00000000000..971a6dcd183 Binary files /dev/null and b/Website/images/Flags/es-CL.gif differ diff --git a/Website/images/Flags/es-CO.gif b/Website/images/Flags/es-CO.gif new file mode 100644 index 00000000000..0b8ed1298d5 Binary files /dev/null and b/Website/images/Flags/es-CO.gif differ diff --git a/Website/images/Flags/es-CR.gif b/Website/images/Flags/es-CR.gif new file mode 100644 index 00000000000..e8050901eef Binary files /dev/null and b/Website/images/Flags/es-CR.gif differ diff --git a/Website/images/Flags/es-DO.gif b/Website/images/Flags/es-DO.gif new file mode 100644 index 00000000000..5f12c5eb15f Binary files /dev/null and b/Website/images/Flags/es-DO.gif differ diff --git a/Website/images/Flags/es-EC.gif b/Website/images/Flags/es-EC.gif new file mode 100644 index 00000000000..014bab15ecf Binary files /dev/null and b/Website/images/Flags/es-EC.gif differ diff --git a/Website/images/Flags/es-ES.gif b/Website/images/Flags/es-ES.gif new file mode 100644 index 00000000000..4b1f7549cd1 Binary files /dev/null and b/Website/images/Flags/es-ES.gif differ diff --git a/Website/images/Flags/es-GT.gif b/Website/images/Flags/es-GT.gif new file mode 100644 index 00000000000..545353f3fb5 Binary files /dev/null and b/Website/images/Flags/es-GT.gif differ diff --git a/Website/images/Flags/es-HN.gif b/Website/images/Flags/es-HN.gif new file mode 100644 index 00000000000..661f83ba608 Binary files /dev/null and b/Website/images/Flags/es-HN.gif differ diff --git a/Website/images/Flags/es-MX.gif b/Website/images/Flags/es-MX.gif new file mode 100644 index 00000000000..79878e25625 Binary files /dev/null and b/Website/images/Flags/es-MX.gif differ diff --git a/Website/images/Flags/es-NI.gif b/Website/images/Flags/es-NI.gif new file mode 100644 index 00000000000..d534c7093a3 Binary files /dev/null and b/Website/images/Flags/es-NI.gif differ diff --git a/Website/images/Flags/es-PA.gif b/Website/images/Flags/es-PA.gif new file mode 100644 index 00000000000..75b2cec33c3 Binary files /dev/null and b/Website/images/Flags/es-PA.gif differ diff --git a/Website/images/Flags/es-PE.gif b/Website/images/Flags/es-PE.gif new file mode 100644 index 00000000000..8aa1fa6b41b Binary files /dev/null and b/Website/images/Flags/es-PE.gif differ diff --git a/Website/images/Flags/es-PR.gif b/Website/images/Flags/es-PR.gif new file mode 100644 index 00000000000..bb9192660ee Binary files /dev/null and b/Website/images/Flags/es-PR.gif differ diff --git a/Website/images/Flags/es-PY.gif b/Website/images/Flags/es-PY.gif new file mode 100644 index 00000000000..b6ce140ed72 Binary files /dev/null and b/Website/images/Flags/es-PY.gif differ diff --git a/Website/images/Flags/es-SV.gif b/Website/images/Flags/es-SV.gif new file mode 100644 index 00000000000..501428015b4 Binary files /dev/null and b/Website/images/Flags/es-SV.gif differ diff --git a/Website/images/Flags/es-US.gif b/Website/images/Flags/es-US.gif new file mode 100644 index 00000000000..fa1b1a43006 Binary files /dev/null and b/Website/images/Flags/es-US.gif differ diff --git a/Website/images/Flags/es-UY.gif b/Website/images/Flags/es-UY.gif new file mode 100644 index 00000000000..3a5294d77fd Binary files /dev/null and b/Website/images/Flags/es-UY.gif differ diff --git a/Website/images/Flags/es-VE.gif b/Website/images/Flags/es-VE.gif new file mode 100644 index 00000000000..f0b6160506d Binary files /dev/null and b/Website/images/Flags/es-VE.gif differ diff --git a/Website/images/Flags/et-EE.gif b/Website/images/Flags/et-EE.gif new file mode 100644 index 00000000000..47073681fc2 Binary files /dev/null and b/Website/images/Flags/et-EE.gif differ diff --git a/Website/images/Flags/eu-ES.gif b/Website/images/Flags/eu-ES.gif new file mode 100644 index 00000000000..d19593d1bc0 Binary files /dev/null and b/Website/images/Flags/eu-ES.gif differ diff --git a/Website/images/Flags/fa-IR.gif b/Website/images/Flags/fa-IR.gif new file mode 100644 index 00000000000..32564557513 Binary files /dev/null and b/Website/images/Flags/fa-IR.gif differ diff --git a/Website/images/Flags/fi-FI.gif b/Website/images/Flags/fi-FI.gif new file mode 100644 index 00000000000..b31f1155b35 Binary files /dev/null and b/Website/images/Flags/fi-FI.gif differ diff --git a/Website/images/Flags/fil-PH.gif b/Website/images/Flags/fil-PH.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/fil-PH.gif differ diff --git a/Website/images/Flags/fo-FO.gif b/Website/images/Flags/fo-FO.gif new file mode 100644 index 00000000000..76514bd8111 Binary files /dev/null and b/Website/images/Flags/fo-FO.gif differ diff --git a/Website/images/Flags/fr-BE.gif b/Website/images/Flags/fr-BE.gif new file mode 100644 index 00000000000..c0aa55eb655 Binary files /dev/null and b/Website/images/Flags/fr-BE.gif differ diff --git a/Website/images/Flags/fr-CA.gif b/Website/images/Flags/fr-CA.gif new file mode 100644 index 00000000000..1c5d4397789 Binary files /dev/null and b/Website/images/Flags/fr-CA.gif differ diff --git a/Website/images/Flags/fr-CH.gif b/Website/images/Flags/fr-CH.gif new file mode 100644 index 00000000000..247e1ff2d65 Binary files /dev/null and b/Website/images/Flags/fr-CH.gif differ diff --git a/Website/images/Flags/fr-FR.gif b/Website/images/Flags/fr-FR.gif new file mode 100644 index 00000000000..ba4c44abd47 Binary files /dev/null and b/Website/images/Flags/fr-FR.gif differ diff --git a/Website/images/Flags/fr-LU.gif b/Website/images/Flags/fr-LU.gif new file mode 100644 index 00000000000..47ee0c135b1 Binary files /dev/null and b/Website/images/Flags/fr-LU.gif differ diff --git a/Website/images/Flags/fr-MC.gif b/Website/images/Flags/fr-MC.gif new file mode 100644 index 00000000000..3d88705dec5 Binary files /dev/null and b/Website/images/Flags/fr-MC.gif differ diff --git a/Website/images/Flags/fy-NL.gif b/Website/images/Flags/fy-NL.gif new file mode 100644 index 00000000000..ca4085fbb51 Binary files /dev/null and b/Website/images/Flags/fy-NL.gif differ diff --git a/Website/images/Flags/ga-IE.gif b/Website/images/Flags/ga-IE.gif new file mode 100644 index 00000000000..8466d3e7919 Binary files /dev/null and b/Website/images/Flags/ga-IE.gif differ diff --git a/Website/images/Flags/gd-GB.gif b/Website/images/Flags/gd-GB.gif new file mode 100644 index 00000000000..711c74473e1 Binary files /dev/null and b/Website/images/Flags/gd-GB.gif differ diff --git a/Website/images/Flags/gl-ES.gif b/Website/images/Flags/gl-ES.gif new file mode 100644 index 00000000000..ca6b8d9d5e9 Binary files /dev/null and b/Website/images/Flags/gl-ES.gif differ diff --git a/Website/images/Flags/gsw-FR.gif b/Website/images/Flags/gsw-FR.gif new file mode 100644 index 00000000000..ba4c44abd47 Binary files /dev/null and b/Website/images/Flags/gsw-FR.gif differ diff --git a/Website/images/Flags/gu-IN.gif b/Website/images/Flags/gu-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/gu-IN.gif differ diff --git a/Website/images/Flags/ha-Latn-NG.gif b/Website/images/Flags/ha-Latn-NG.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/ha-Latn-NG.gif differ diff --git a/Website/images/Flags/he-IL.gif b/Website/images/Flags/he-IL.gif new file mode 100644 index 00000000000..2c01cfb3373 Binary files /dev/null and b/Website/images/Flags/he-IL.gif differ diff --git a/Website/images/Flags/hi-IN.gif b/Website/images/Flags/hi-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/hi-IN.gif differ diff --git a/Website/images/Flags/hr-BA.gif b/Website/images/Flags/hr-BA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/hr-BA.gif differ diff --git a/Website/images/Flags/hr-HR.gif b/Website/images/Flags/hr-HR.gif new file mode 100644 index 00000000000..0ee0cf11bc1 Binary files /dev/null and b/Website/images/Flags/hr-HR.gif differ diff --git a/Website/images/Flags/hsb-DE.gif b/Website/images/Flags/hsb-DE.gif new file mode 100644 index 00000000000..a98f4c72bf5 Binary files /dev/null and b/Website/images/Flags/hsb-DE.gif differ diff --git a/Website/images/Flags/hu-HU.gif b/Website/images/Flags/hu-HU.gif new file mode 100644 index 00000000000..bfa66ffb7fd Binary files /dev/null and b/Website/images/Flags/hu-HU.gif differ diff --git a/Website/images/Flags/hy-AM.gif b/Website/images/Flags/hy-AM.gif new file mode 100644 index 00000000000..76137e8dd91 Binary files /dev/null and b/Website/images/Flags/hy-AM.gif differ diff --git a/Website/images/Flags/id-ID.gif b/Website/images/Flags/id-ID.gif new file mode 100644 index 00000000000..540a1ca694a Binary files /dev/null and b/Website/images/Flags/id-ID.gif differ diff --git a/Website/images/Flags/ig-NG.gif b/Website/images/Flags/ig-NG.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/ig-NG.gif differ diff --git a/Website/images/Flags/ii-CN.gif b/Website/images/Flags/ii-CN.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/ii-CN.gif differ diff --git a/Website/images/Flags/is-IS.gif b/Website/images/Flags/is-IS.gif new file mode 100644 index 00000000000..b0c9d7c2764 Binary files /dev/null and b/Website/images/Flags/is-IS.gif differ diff --git a/Website/images/Flags/it-CH.gif b/Website/images/Flags/it-CH.gif new file mode 100644 index 00000000000..247e1ff2d65 Binary files /dev/null and b/Website/images/Flags/it-CH.gif differ diff --git a/Website/images/Flags/it-IT.gif b/Website/images/Flags/it-IT.gif new file mode 100644 index 00000000000..efb4b237d52 Binary files /dev/null and b/Website/images/Flags/it-IT.gif differ diff --git a/Website/images/Flags/iu-Cans-CA.gif b/Website/images/Flags/iu-Cans-CA.gif new file mode 100644 index 00000000000..1c5d4397789 Binary files /dev/null and b/Website/images/Flags/iu-Cans-CA.gif differ diff --git a/Website/images/Flags/iu-Latn-CA.gif b/Website/images/Flags/iu-Latn-CA.gif new file mode 100644 index 00000000000..1c5d4397789 Binary files /dev/null and b/Website/images/Flags/iu-Latn-CA.gif differ diff --git a/Website/images/Flags/ja-JP.gif b/Website/images/Flags/ja-JP.gif new file mode 100644 index 00000000000..924557eb4bb Binary files /dev/null and b/Website/images/Flags/ja-JP.gif differ diff --git a/Website/images/Flags/ka-GE.gif b/Website/images/Flags/ka-GE.gif new file mode 100644 index 00000000000..d622235ee59 Binary files /dev/null and b/Website/images/Flags/ka-GE.gif differ diff --git a/Website/images/Flags/kk-KZ.gif b/Website/images/Flags/kk-KZ.gif new file mode 100644 index 00000000000..6f06b2dbf8b Binary files /dev/null and b/Website/images/Flags/kk-KZ.gif differ diff --git a/Website/images/Flags/kl-GL.gif b/Website/images/Flags/kl-GL.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/kl-GL.gif differ diff --git a/Website/images/Flags/km-KH.gif b/Website/images/Flags/km-KH.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/km-KH.gif differ diff --git a/Website/images/Flags/kn-IN.gif b/Website/images/Flags/kn-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/kn-IN.gif differ diff --git a/Website/images/Flags/ko-KR.gif b/Website/images/Flags/ko-KR.gif new file mode 100644 index 00000000000..ec2414e50ad Binary files /dev/null and b/Website/images/Flags/ko-KR.gif differ diff --git a/Website/images/Flags/kok-IN.gif b/Website/images/Flags/kok-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/kok-IN.gif differ diff --git a/Website/images/Flags/ky-KG.gif b/Website/images/Flags/ky-KG.gif new file mode 100644 index 00000000000..3a1fe46ceb8 Binary files /dev/null and b/Website/images/Flags/ky-KG.gif differ diff --git a/Website/images/Flags/lb-LU.gif b/Website/images/Flags/lb-LU.gif new file mode 100644 index 00000000000..47ee0c135b1 Binary files /dev/null and b/Website/images/Flags/lb-LU.gif differ diff --git a/Website/images/Flags/lo-LA.gif b/Website/images/Flags/lo-LA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/lo-LA.gif differ diff --git a/Website/images/Flags/lt-LT.gif b/Website/images/Flags/lt-LT.gif new file mode 100644 index 00000000000..8e4a649dbed Binary files /dev/null and b/Website/images/Flags/lt-LT.gif differ diff --git a/Website/images/Flags/lv-LV.gif b/Website/images/Flags/lv-LV.gif new file mode 100644 index 00000000000..fe8396dfda7 Binary files /dev/null and b/Website/images/Flags/lv-LV.gif differ diff --git a/Website/images/Flags/mi-NZ.gif b/Website/images/Flags/mi-NZ.gif new file mode 100644 index 00000000000..4f6409ad4b4 Binary files /dev/null and b/Website/images/Flags/mi-NZ.gif differ diff --git a/Website/images/Flags/mk-MK.gif b/Website/images/Flags/mk-MK.gif new file mode 100644 index 00000000000..2c10b07c0d0 Binary files /dev/null and b/Website/images/Flags/mk-MK.gif differ diff --git a/Website/images/Flags/ml-IN.gif b/Website/images/Flags/ml-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/ml-IN.gif differ diff --git a/Website/images/Flags/mn-MN.gif b/Website/images/Flags/mn-MN.gif new file mode 100644 index 00000000000..4376b4082fb Binary files /dev/null and b/Website/images/Flags/mn-MN.gif differ diff --git a/Website/images/Flags/mn-Mong-CN.gif b/Website/images/Flags/mn-Mong-CN.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/mn-Mong-CN.gif differ diff --git a/Website/images/Flags/moh-CA.gif b/Website/images/Flags/moh-CA.gif new file mode 100644 index 00000000000..1c5d4397789 Binary files /dev/null and b/Website/images/Flags/moh-CA.gif differ diff --git a/Website/images/Flags/mr-IN.gif b/Website/images/Flags/mr-IN.gif new file mode 100644 index 00000000000..bb2ee592711 Binary files /dev/null and b/Website/images/Flags/mr-IN.gif differ diff --git a/Website/images/Flags/ms-BN.gif b/Website/images/Flags/ms-BN.gif new file mode 100644 index 00000000000..56a46ef5aba Binary files /dev/null and b/Website/images/Flags/ms-BN.gif differ diff --git a/Website/images/Flags/ms-MY.gif b/Website/images/Flags/ms-MY.gif new file mode 100644 index 00000000000..3203db3e47d Binary files /dev/null and b/Website/images/Flags/ms-MY.gif differ diff --git a/Website/images/Flags/mt-MT.gif b/Website/images/Flags/mt-MT.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/mt-MT.gif differ diff --git a/Website/images/Flags/nb-NO.gif b/Website/images/Flags/nb-NO.gif new file mode 100644 index 00000000000..2096e61cc92 Binary files /dev/null and b/Website/images/Flags/nb-NO.gif differ diff --git a/Website/images/Flags/ne-NP.gif b/Website/images/Flags/ne-NP.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/ne-NP.gif differ diff --git a/Website/images/Flags/nl-BE.gif b/Website/images/Flags/nl-BE.gif new file mode 100644 index 00000000000..c0aa55eb655 Binary files /dev/null and b/Website/images/Flags/nl-BE.gif differ diff --git a/Website/images/Flags/nl-NL.gif b/Website/images/Flags/nl-NL.gif new file mode 100644 index 00000000000..ca4085fbb51 Binary files /dev/null and b/Website/images/Flags/nl-NL.gif differ diff --git a/Website/images/Flags/nn-NO.gif b/Website/images/Flags/nn-NO.gif new file mode 100644 index 00000000000..2096e61cc92 Binary files /dev/null and b/Website/images/Flags/nn-NO.gif differ diff --git a/Website/images/Flags/nso-ZA.gif b/Website/images/Flags/nso-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/nso-ZA.gif differ diff --git a/Website/images/Flags/oc-FR.gif b/Website/images/Flags/oc-FR.gif new file mode 100644 index 00000000000..ba4c44abd47 Binary files /dev/null and b/Website/images/Flags/oc-FR.gif differ diff --git a/Website/images/Flags/or-IN.gif b/Website/images/Flags/or-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/or-IN.gif differ diff --git a/Website/images/Flags/pa-IN.gif b/Website/images/Flags/pa-IN.gif new file mode 100644 index 00000000000..bb2ee592711 Binary files /dev/null and b/Website/images/Flags/pa-IN.gif differ diff --git a/Website/images/Flags/pl-PL.gif b/Website/images/Flags/pl-PL.gif new file mode 100644 index 00000000000..71bb920c384 Binary files /dev/null and b/Website/images/Flags/pl-PL.gif differ diff --git a/Website/images/Flags/prs-AF.gif b/Website/images/Flags/prs-AF.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/prs-AF.gif differ diff --git a/Website/images/Flags/ps-AF.gif b/Website/images/Flags/ps-AF.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/ps-AF.gif differ diff --git a/Website/images/Flags/pt-BR.gif b/Website/images/Flags/pt-BR.gif new file mode 100644 index 00000000000..57991959b02 Binary files /dev/null and b/Website/images/Flags/pt-BR.gif differ diff --git a/Website/images/Flags/pt-PT.gif b/Website/images/Flags/pt-PT.gif new file mode 100644 index 00000000000..e231f33c485 Binary files /dev/null and b/Website/images/Flags/pt-PT.gif differ diff --git a/Website/images/Flags/qut-GT.gif b/Website/images/Flags/qut-GT.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/qut-GT.gif differ diff --git a/Website/images/Flags/quz-BO.gif b/Website/images/Flags/quz-BO.gif new file mode 100644 index 00000000000..63252223bf7 Binary files /dev/null and b/Website/images/Flags/quz-BO.gif differ diff --git a/Website/images/Flags/quz-EC.gif b/Website/images/Flags/quz-EC.gif new file mode 100644 index 00000000000..014bab15ecf Binary files /dev/null and b/Website/images/Flags/quz-EC.gif differ diff --git a/Website/images/Flags/quz-PE.gif b/Website/images/Flags/quz-PE.gif new file mode 100644 index 00000000000..8aa1fa6b41b Binary files /dev/null and b/Website/images/Flags/quz-PE.gif differ diff --git a/Website/images/Flags/rm-CH.gif b/Website/images/Flags/rm-CH.gif new file mode 100644 index 00000000000..247e1ff2d65 Binary files /dev/null and b/Website/images/Flags/rm-CH.gif differ diff --git a/Website/images/Flags/ro-RO.gif b/Website/images/Flags/ro-RO.gif new file mode 100644 index 00000000000..a2e3374fd41 Binary files /dev/null and b/Website/images/Flags/ro-RO.gif differ diff --git a/Website/images/Flags/ru-RU.gif b/Website/images/Flags/ru-RU.gif new file mode 100644 index 00000000000..15bad9c1ead Binary files /dev/null and b/Website/images/Flags/ru-RU.gif differ diff --git a/Website/images/Flags/rw-RW.gif b/Website/images/Flags/rw-RW.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/rw-RW.gif differ diff --git a/Website/images/Flags/sa-IN.gif b/Website/images/Flags/sa-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/sa-IN.gif differ diff --git a/Website/images/Flags/sah-RU.gif b/Website/images/Flags/sah-RU.gif new file mode 100644 index 00000000000..15bad9c1ead Binary files /dev/null and b/Website/images/Flags/sah-RU.gif differ diff --git a/Website/images/Flags/se-FI.gif b/Website/images/Flags/se-FI.gif new file mode 100644 index 00000000000..b31f1155b35 Binary files /dev/null and b/Website/images/Flags/se-FI.gif differ diff --git a/Website/images/Flags/se-NO.gif b/Website/images/Flags/se-NO.gif new file mode 100644 index 00000000000..2096e61cc92 Binary files /dev/null and b/Website/images/Flags/se-NO.gif differ diff --git a/Website/images/Flags/se-SE.gif b/Website/images/Flags/se-SE.gif new file mode 100644 index 00000000000..136670fd849 Binary files /dev/null and b/Website/images/Flags/se-SE.gif differ diff --git a/Website/images/Flags/si-LK.gif b/Website/images/Flags/si-LK.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/si-LK.gif differ diff --git a/Website/images/Flags/sk-SK.gif b/Website/images/Flags/sk-SK.gif new file mode 100644 index 00000000000..e98c842ee1f Binary files /dev/null and b/Website/images/Flags/sk-SK.gif differ diff --git a/Website/images/Flags/sl-SI.gif b/Website/images/Flags/sl-SI.gif new file mode 100644 index 00000000000..72c21fff665 Binary files /dev/null and b/Website/images/Flags/sl-SI.gif differ diff --git a/Website/images/Flags/sma-NO.gif b/Website/images/Flags/sma-NO.gif new file mode 100644 index 00000000000..2096e61cc92 Binary files /dev/null and b/Website/images/Flags/sma-NO.gif differ diff --git a/Website/images/Flags/sma-SE.gif b/Website/images/Flags/sma-SE.gif new file mode 100644 index 00000000000..136670fd849 Binary files /dev/null and b/Website/images/Flags/sma-SE.gif differ diff --git a/Website/images/Flags/smj-NO.gif b/Website/images/Flags/smj-NO.gif new file mode 100644 index 00000000000..2096e61cc92 Binary files /dev/null and b/Website/images/Flags/smj-NO.gif differ diff --git a/Website/images/Flags/smj-SE.gif b/Website/images/Flags/smj-SE.gif new file mode 100644 index 00000000000..136670fd849 Binary files /dev/null and b/Website/images/Flags/smj-SE.gif differ diff --git a/Website/images/Flags/smn-FI.gif b/Website/images/Flags/smn-FI.gif new file mode 100644 index 00000000000..b31f1155b35 Binary files /dev/null and b/Website/images/Flags/smn-FI.gif differ diff --git a/Website/images/Flags/sms-FI.gif b/Website/images/Flags/sms-FI.gif new file mode 100644 index 00000000000..b31f1155b35 Binary files /dev/null and b/Website/images/Flags/sms-FI.gif differ diff --git a/Website/images/Flags/sq-AL.gif b/Website/images/Flags/sq-AL.gif new file mode 100644 index 00000000000..d31096cf312 Binary files /dev/null and b/Website/images/Flags/sq-AL.gif differ diff --git a/Website/images/Flags/sr-Cyrl-BA.gif b/Website/images/Flags/sr-Cyrl-BA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Cyrl-BA.gif differ diff --git a/Website/images/Flags/sr-Cyrl-CS.gif b/Website/images/Flags/sr-Cyrl-CS.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Cyrl-CS.gif differ diff --git a/Website/images/Flags/sr-Cyrl-ME.gif b/Website/images/Flags/sr-Cyrl-ME.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Cyrl-ME.gif differ diff --git a/Website/images/Flags/sr-Cyrl-RS.gif b/Website/images/Flags/sr-Cyrl-RS.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Cyrl-RS.gif differ diff --git a/Website/images/Flags/sr-Latn-BA.gif b/Website/images/Flags/sr-Latn-BA.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Latn-BA.gif differ diff --git a/Website/images/Flags/sr-Latn-CS.gif b/Website/images/Flags/sr-Latn-CS.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Latn-CS.gif differ diff --git a/Website/images/Flags/sr-Latn-ME.gif b/Website/images/Flags/sr-Latn-ME.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Latn-ME.gif differ diff --git a/Website/images/Flags/sr-Latn-RS.gif b/Website/images/Flags/sr-Latn-RS.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/sr-Latn-RS.gif differ diff --git a/Website/images/Flags/sv-FI.gif b/Website/images/Flags/sv-FI.gif new file mode 100644 index 00000000000..b31f1155b35 Binary files /dev/null and b/Website/images/Flags/sv-FI.gif differ diff --git a/Website/images/Flags/sv-SE.gif b/Website/images/Flags/sv-SE.gif new file mode 100644 index 00000000000..136670fd849 Binary files /dev/null and b/Website/images/Flags/sv-SE.gif differ diff --git a/Website/images/Flags/sw-KE.gif b/Website/images/Flags/sw-KE.gif new file mode 100644 index 00000000000..b5bca27ec56 Binary files /dev/null and b/Website/images/Flags/sw-KE.gif differ diff --git a/Website/images/Flags/syr-SY.gif b/Website/images/Flags/syr-SY.gif new file mode 100644 index 00000000000..0bc3d95e267 Binary files /dev/null and b/Website/images/Flags/syr-SY.gif differ diff --git a/Website/images/Flags/ta-IN.gif b/Website/images/Flags/ta-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/ta-IN.gif differ diff --git a/Website/images/Flags/te-IN.gif b/Website/images/Flags/te-IN.gif new file mode 100644 index 00000000000..74e558aaa6f Binary files /dev/null and b/Website/images/Flags/te-IN.gif differ diff --git a/Website/images/Flags/tg-Cyrl-TJ.gif b/Website/images/Flags/tg-Cyrl-TJ.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/tg-Cyrl-TJ.gif differ diff --git a/Website/images/Flags/th-TH.gif b/Website/images/Flags/th-TH.gif new file mode 100644 index 00000000000..19e26b7bdfb Binary files /dev/null and b/Website/images/Flags/th-TH.gif differ diff --git a/Website/images/Flags/tk-TM.gif b/Website/images/Flags/tk-TM.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/tk-TM.gif differ diff --git a/Website/images/Flags/tn-ZA.gif b/Website/images/Flags/tn-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/tn-ZA.gif differ diff --git a/Website/images/Flags/tr-TR.gif b/Website/images/Flags/tr-TR.gif new file mode 100644 index 00000000000..06dcdbb3ed7 Binary files /dev/null and b/Website/images/Flags/tr-TR.gif differ diff --git a/Website/images/Flags/tt-RU.gif b/Website/images/Flags/tt-RU.gif new file mode 100644 index 00000000000..15bad9c1ead Binary files /dev/null and b/Website/images/Flags/tt-RU.gif differ diff --git a/Website/images/Flags/tzm-Latn-DZ.gif b/Website/images/Flags/tzm-Latn-DZ.gif new file mode 100644 index 00000000000..5e423573e34 Binary files /dev/null and b/Website/images/Flags/tzm-Latn-DZ.gif differ diff --git a/Website/images/Flags/ug-CN.gif b/Website/images/Flags/ug-CN.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/ug-CN.gif differ diff --git a/Website/images/Flags/uk-UA.gif b/Website/images/Flags/uk-UA.gif new file mode 100644 index 00000000000..c053553c4eb Binary files /dev/null and b/Website/images/Flags/uk-UA.gif differ diff --git a/Website/images/Flags/ur-PK.gif b/Website/images/Flags/ur-PK.gif new file mode 100644 index 00000000000..45f9d67ee08 Binary files /dev/null and b/Website/images/Flags/ur-PK.gif differ diff --git a/Website/images/Flags/uz-Cyrl-UZ.gif b/Website/images/Flags/uz-Cyrl-UZ.gif new file mode 100644 index 00000000000..1e339a5094c Binary files /dev/null and b/Website/images/Flags/uz-Cyrl-UZ.gif differ diff --git a/Website/images/Flags/uz-Latn-UZ.gif b/Website/images/Flags/uz-Latn-UZ.gif new file mode 100644 index 00000000000..1e339a5094c Binary files /dev/null and b/Website/images/Flags/uz-Latn-UZ.gif differ diff --git a/Website/images/Flags/uz-UZ-Cyrl.gif b/Website/images/Flags/uz-UZ-Cyrl.gif new file mode 100644 index 00000000000..1e339a5094c Binary files /dev/null and b/Website/images/Flags/uz-UZ-Cyrl.gif differ diff --git a/Website/images/Flags/uz-UZ-Latn.gif b/Website/images/Flags/uz-UZ-Latn.gif new file mode 100644 index 00000000000..1e339a5094c Binary files /dev/null and b/Website/images/Flags/uz-UZ-Latn.gif differ diff --git a/Website/images/Flags/vi-VN.gif b/Website/images/Flags/vi-VN.gif new file mode 100644 index 00000000000..e1bd9292c07 Binary files /dev/null and b/Website/images/Flags/vi-VN.gif differ diff --git a/Website/images/Flags/wo-SN.gif b/Website/images/Flags/wo-SN.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/wo-SN.gif differ diff --git a/Website/images/Flags/xh-ZA.gif b/Website/images/Flags/xh-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/xh-ZA.gif differ diff --git a/Website/images/Flags/yo-NG.gif b/Website/images/Flags/yo-NG.gif new file mode 100644 index 00000000000..5eb2ac0f389 Binary files /dev/null and b/Website/images/Flags/yo-NG.gif differ diff --git a/Website/images/Flags/zh-CHS.gif b/Website/images/Flags/zh-CHS.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/zh-CHS.gif differ diff --git a/Website/images/Flags/zh-CHT.gif b/Website/images/Flags/zh-CHT.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/zh-CHT.gif differ diff --git a/Website/images/Flags/zh-CN.gif b/Website/images/Flags/zh-CN.gif new file mode 100644 index 00000000000..eca94ba130b Binary files /dev/null and b/Website/images/Flags/zh-CN.gif differ diff --git a/Website/images/Flags/zh-HK.gif b/Website/images/Flags/zh-HK.gif new file mode 100644 index 00000000000..8e05f68ed32 Binary files /dev/null and b/Website/images/Flags/zh-HK.gif differ diff --git a/Website/images/Flags/zh-MO.gif b/Website/images/Flags/zh-MO.gif new file mode 100644 index 00000000000..d8538f91df9 Binary files /dev/null and b/Website/images/Flags/zh-MO.gif differ diff --git a/Website/images/Flags/zh-SG.gif b/Website/images/Flags/zh-SG.gif new file mode 100644 index 00000000000..5562dac2e4d Binary files /dev/null and b/Website/images/Flags/zh-SG.gif differ diff --git a/Website/images/Flags/zh-TW.gif b/Website/images/Flags/zh-TW.gif new file mode 100644 index 00000000000..1a089b96659 Binary files /dev/null and b/Website/images/Flags/zh-TW.gif differ diff --git a/Website/images/Flags/zu-ZA.gif b/Website/images/Flags/zu-ZA.gif new file mode 100644 index 00000000000..1f5363b07f8 Binary files /dev/null and b/Website/images/Flags/zu-ZA.gif differ diff --git a/Website/images/Forge.png b/Website/images/Forge.png new file mode 100644 index 00000000000..bad6a82e7d9 Binary files /dev/null and b/Website/images/Forge.png differ diff --git a/Website/images/InstallWizardBg.png b/Website/images/InstallWizardBg.png new file mode 100644 index 00000000000..3aea30b30d3 Binary files /dev/null and b/Website/images/InstallWizardBg.png differ diff --git a/Website/images/Logos.jpg b/Website/images/Logos.jpg new file mode 100644 index 00000000000..671c2f54bdd Binary files /dev/null and b/Website/images/Logos.jpg differ diff --git a/Website/images/Search/SearchButton.png b/Website/images/Search/SearchButton.png new file mode 100644 index 00000000000..ee5c39d0c56 Binary files /dev/null and b/Website/images/Search/SearchButton.png differ diff --git a/Website/images/Search/clearText.png b/Website/images/Search/clearText.png new file mode 100644 index 00000000000..7d0a38f918b Binary files /dev/null and b/Website/images/Search/clearText.png differ diff --git a/Website/images/Search/dotnetnuke-icon.gif b/Website/images/Search/dotnetnuke-icon.gif new file mode 100644 index 00000000000..45a79ec7de8 Binary files /dev/null and b/Website/images/Search/dotnetnuke-icon.gif differ diff --git a/Website/images/Search/google-icon.gif b/Website/images/Search/google-icon.gif new file mode 100644 index 00000000000..e6f4ac295fb Binary files /dev/null and b/Website/images/Search/google-icon.gif differ diff --git a/Website/images/SearchCrawler_16px.gif b/Website/images/SearchCrawler_16px.gif new file mode 100644 index 00000000000..059ee28ab94 Binary files /dev/null and b/Website/images/SearchCrawler_16px.gif differ diff --git a/Website/images/SearchCrawler_32px.gif b/Website/images/SearchCrawler_32px.gif new file mode 100644 index 00000000000..00540d11f85 Binary files /dev/null and b/Website/images/SearchCrawler_32px.gif differ diff --git a/Website/images/Store.png b/Website/images/Store.png new file mode 100644 index 00000000000..c8a84250e4a Binary files /dev/null and b/Website/images/Store.png differ diff --git a/Website/images/System-Box-Empty-icon.png b/Website/images/System-Box-Empty-icon.png new file mode 100644 index 00000000000..8ae4dfe26e3 Binary files /dev/null and b/Website/images/System-Box-Empty-icon.png differ diff --git a/Website/images/TimePicker.png b/Website/images/TimePicker.png new file mode 100644 index 00000000000..80d85b5e251 Binary files /dev/null and b/Website/images/TimePicker.png differ diff --git a/Website/images/about.gif b/Website/images/about.gif new file mode 100644 index 00000000000..1262e3656d6 Binary files /dev/null and b/Website/images/about.gif differ diff --git a/Website/images/action.gif b/Website/images/action.gif new file mode 100644 index 00000000000..81da5e6f6fa Binary files /dev/null and b/Website/images/action.gif differ diff --git a/Website/images/action_bottom.gif b/Website/images/action_bottom.gif new file mode 100644 index 00000000000..fc052ee0ee6 Binary files /dev/null and b/Website/images/action_bottom.gif differ diff --git a/Website/images/action_delete.gif b/Website/images/action_delete.gif new file mode 100644 index 00000000000..0952d5d4595 Binary files /dev/null and b/Website/images/action_delete.gif differ diff --git a/Website/images/action_down.gif b/Website/images/action_down.gif new file mode 100644 index 00000000000..c9088c81935 Binary files /dev/null and b/Website/images/action_down.gif differ diff --git a/Website/images/action_export.gif b/Website/images/action_export.gif new file mode 100644 index 00000000000..8402465b9ed Binary files /dev/null and b/Website/images/action_export.gif differ diff --git a/Website/images/action_help.gif b/Website/images/action_help.gif new file mode 100644 index 00000000000..1262e3656d6 Binary files /dev/null and b/Website/images/action_help.gif differ diff --git a/Website/images/action_import.gif b/Website/images/action_import.gif new file mode 100644 index 00000000000..cc08b836717 Binary files /dev/null and b/Website/images/action_import.gif differ diff --git a/Website/images/action_move.gif b/Website/images/action_move.gif new file mode 100644 index 00000000000..72e13471d1c Binary files /dev/null and b/Website/images/action_move.gif differ diff --git a/Website/images/action_print.gif b/Website/images/action_print.gif new file mode 100644 index 00000000000..03c55865b7b Binary files /dev/null and b/Website/images/action_print.gif differ diff --git a/Website/images/action_refresh.gif b/Website/images/action_refresh.gif new file mode 100644 index 00000000000..6d7e5bb4ade Binary files /dev/null and b/Website/images/action_refresh.gif differ diff --git a/Website/images/action_right.gif b/Website/images/action_right.gif new file mode 100644 index 00000000000..0d69e2d4a9d Binary files /dev/null and b/Website/images/action_right.gif differ diff --git a/Website/images/action_rss.gif b/Website/images/action_rss.gif new file mode 100644 index 00000000000..b0e4adf1d51 Binary files /dev/null and b/Website/images/action_rss.gif differ diff --git a/Website/images/action_settings.gif b/Website/images/action_settings.gif new file mode 100644 index 00000000000..c0a2e5c6d66 Binary files /dev/null and b/Website/images/action_settings.gif differ diff --git a/Website/images/action_source.gif b/Website/images/action_source.gif new file mode 100644 index 00000000000..ffdb29dc6ee Binary files /dev/null and b/Website/images/action_source.gif differ diff --git a/Website/images/action_top.gif b/Website/images/action_top.gif new file mode 100644 index 00000000000..c9995f14f1e Binary files /dev/null and b/Website/images/action_top.gif differ diff --git a/Website/images/action_up.gif b/Website/images/action_up.gif new file mode 100644 index 00000000000..30c7a737610 Binary files /dev/null and b/Website/images/action_up.gif differ diff --git a/Website/images/add.gif b/Website/images/add.gif new file mode 100644 index 00000000000..18f97ba4c17 Binary files /dev/null and b/Website/images/add.gif differ diff --git a/Website/images/appGallery_License.gif b/Website/images/appGallery_License.gif new file mode 100644 index 00000000000..b114259fb32 Binary files /dev/null and b/Website/images/appGallery_License.gif differ diff --git a/Website/images/appGallery_cart.gif b/Website/images/appGallery_cart.gif new file mode 100644 index 00000000000..2cac2e30bb5 Binary files /dev/null and b/Website/images/appGallery_cart.gif differ diff --git a/Website/images/appGallery_deploy.gif b/Website/images/appGallery_deploy.gif new file mode 100644 index 00000000000..4e6963a2485 Binary files /dev/null and b/Website/images/appGallery_deploy.gif differ diff --git a/Website/images/appGallery_details.gif b/Website/images/appGallery_details.gif new file mode 100644 index 00000000000..c13ee6d4010 Binary files /dev/null and b/Website/images/appGallery_details.gif differ diff --git a/Website/images/appGallery_module.gif b/Website/images/appGallery_module.gif new file mode 100644 index 00000000000..be8ed083c82 Binary files /dev/null and b/Website/images/appGallery_module.gif differ diff --git a/Website/images/appGallery_other.gif b/Website/images/appGallery_other.gif new file mode 100644 index 00000000000..be8ed083c82 Binary files /dev/null and b/Website/images/appGallery_other.gif differ diff --git a/Website/images/appGallery_skin.gif b/Website/images/appGallery_skin.gif new file mode 100644 index 00000000000..6aed05b4795 Binary files /dev/null and b/Website/images/appGallery_skin.gif differ diff --git a/Website/images/arrow-left.png b/Website/images/arrow-left.png new file mode 100644 index 00000000000..369c8d26950 Binary files /dev/null and b/Website/images/arrow-left.png differ diff --git a/Website/images/arrow-right.png b/Website/images/arrow-right.png new file mode 100644 index 00000000000..4f61edb737b Binary files /dev/null and b/Website/images/arrow-right.png differ diff --git a/Website/images/banner.gif b/Website/images/banner.gif new file mode 100644 index 00000000000..736a8468d62 Binary files /dev/null and b/Website/images/banner.gif differ diff --git a/Website/images/begin.gif b/Website/images/begin.gif new file mode 100644 index 00000000000..85fea6600ec Binary files /dev/null and b/Website/images/begin.gif differ diff --git a/Website/images/bevel.gif b/Website/images/bevel.gif new file mode 100644 index 00000000000..6736456f91d Binary files /dev/null and b/Website/images/bevel.gif differ diff --git a/Website/images/bevel_blue.gif b/Website/images/bevel_blue.gif new file mode 100644 index 00000000000..30fabca3336 Binary files /dev/null and b/Website/images/bevel_blue.gif differ diff --git a/Website/images/bottom-left.gif b/Website/images/bottom-left.gif new file mode 100644 index 00000000000..12398927f01 Binary files /dev/null and b/Website/images/bottom-left.gif differ diff --git a/Website/images/bottom-right.gif b/Website/images/bottom-right.gif new file mode 100644 index 00000000000..2750f689fcf Binary files /dev/null and b/Website/images/bottom-right.gif differ diff --git a/Website/images/bottom-tile.gif b/Website/images/bottom-tile.gif new file mode 100644 index 00000000000..a8b1f83ee21 Binary files /dev/null and b/Website/images/bottom-tile.gif differ diff --git a/Website/images/bottom.gif b/Website/images/bottom.gif new file mode 100644 index 00000000000..fc052ee0ee6 Binary files /dev/null and b/Website/images/bottom.gif differ diff --git a/Website/images/breadcrumb.gif b/Website/images/breadcrumb.gif new file mode 100644 index 00000000000..1c0ce5c7ab2 Binary files /dev/null and b/Website/images/breadcrumb.gif differ diff --git a/Website/images/calendar.png b/Website/images/calendar.png new file mode 100644 index 00000000000..fbf52933de7 Binary files /dev/null and b/Website/images/calendar.png differ diff --git a/Website/images/calendaricons.png b/Website/images/calendaricons.png new file mode 100644 index 00000000000..bb593fc0290 Binary files /dev/null and b/Website/images/calendaricons.png differ diff --git a/Website/images/cancel.gif b/Website/images/cancel.gif new file mode 100644 index 00000000000..abbe878d394 Binary files /dev/null and b/Website/images/cancel.gif differ diff --git a/Website/images/cancel2.gif b/Website/images/cancel2.gif new file mode 100644 index 00000000000..a3577f05870 Binary files /dev/null and b/Website/images/cancel2.gif differ diff --git a/Website/images/captcha.jpg b/Website/images/captcha.jpg new file mode 100644 index 00000000000..5ada559e12a Binary files /dev/null and b/Website/images/captcha.jpg differ diff --git a/Website/images/cart.gif b/Website/images/cart.gif new file mode 100644 index 00000000000..3bbfcc09e9c Binary files /dev/null and b/Website/images/cart.gif differ diff --git a/Website/images/category.gif b/Website/images/category.gif new file mode 100644 index 00000000000..8788aeb159c Binary files /dev/null and b/Website/images/category.gif differ diff --git a/Website/images/checkbox.png b/Website/images/checkbox.png new file mode 100644 index 00000000000..ef72489103a Binary files /dev/null and b/Website/images/checkbox.png differ diff --git a/Website/images/checked-disabled.gif b/Website/images/checked-disabled.gif new file mode 100644 index 00000000000..35174cd1adf Binary files /dev/null and b/Website/images/checked-disabled.gif differ diff --git a/Website/images/checked.gif b/Website/images/checked.gif new file mode 100644 index 00000000000..f39345d50bb Binary files /dev/null and b/Website/images/checked.gif differ diff --git a/Website/images/close-icn.png b/Website/images/close-icn.png new file mode 100644 index 00000000000..afdfd61c1e3 Binary files /dev/null and b/Website/images/close-icn.png differ diff --git a/Website/images/closeBtn.png b/Website/images/closeBtn.png new file mode 100644 index 00000000000..86b26a9870d Binary files /dev/null and b/Website/images/closeBtn.png differ diff --git a/Website/images/collapse.gif b/Website/images/collapse.gif new file mode 100644 index 00000000000..5bcbb041140 Binary files /dev/null and b/Website/images/collapse.gif differ diff --git a/Website/images/copy.gif b/Website/images/copy.gif new file mode 100644 index 00000000000..7163f43403f Binary files /dev/null and b/Website/images/copy.gif differ diff --git a/Website/images/darkCheckbox.png b/Website/images/darkCheckbox.png new file mode 100644 index 00000000000..e7bcfefd6b6 Binary files /dev/null and b/Website/images/darkCheckbox.png differ diff --git a/Website/images/datePicker.png b/Website/images/datePicker.png new file mode 100644 index 00000000000..0c27501620f Binary files /dev/null and b/Website/images/datePicker.png differ diff --git a/Website/images/datePickerArrows.png b/Website/images/datePickerArrows.png new file mode 100644 index 00000000000..a5ccef93a8a Binary files /dev/null and b/Website/images/datePickerArrows.png differ diff --git a/Website/images/dbldn.gif b/Website/images/dbldn.gif new file mode 100644 index 00000000000..ee3da741616 Binary files /dev/null and b/Website/images/dbldn.gif differ diff --git a/Website/images/dblup.gif b/Website/images/dblup.gif new file mode 100644 index 00000000000..8155e6f10bd Binary files /dev/null and b/Website/images/dblup.gif differ diff --git a/Website/images/delete.gif b/Website/images/delete.gif new file mode 100644 index 00000000000..7b56acaa504 Binary files /dev/null and b/Website/images/delete.gif differ diff --git a/Website/images/deny.gif b/Website/images/deny.gif new file mode 100644 index 00000000000..f1ea3fcd784 Binary files /dev/null and b/Website/images/deny.gif differ diff --git a/Website/images/dn.gif b/Website/images/dn.gif new file mode 100644 index 00000000000..c9088c81935 Binary files /dev/null and b/Website/images/dn.gif differ diff --git a/Website/images/dnlt.gif b/Website/images/dnlt.gif new file mode 100644 index 00000000000..f33fa61e812 Binary files /dev/null and b/Website/images/dnlt.gif differ diff --git a/Website/images/dnnActiveTagClose.png b/Website/images/dnnActiveTagClose.png new file mode 100644 index 00000000000..e6a4c2f6739 Binary files /dev/null and b/Website/images/dnnActiveTagClose.png differ diff --git a/Website/images/dnnSpinnerDownArrow.png b/Website/images/dnnSpinnerDownArrow.png new file mode 100644 index 00000000000..2bd6551b8ef Binary files /dev/null and b/Website/images/dnnSpinnerDownArrow.png differ diff --git a/Website/images/dnnSpinnerDownArrowWhite.png b/Website/images/dnnSpinnerDownArrowWhite.png new file mode 100644 index 00000000000..3e15a7ac881 Binary files /dev/null and b/Website/images/dnnSpinnerDownArrowWhite.png differ diff --git a/Website/images/dnnSpinnerUpArrow.png b/Website/images/dnnSpinnerUpArrow.png new file mode 100644 index 00000000000..eb1f61c73c1 Binary files /dev/null and b/Website/images/dnnSpinnerUpArrow.png differ diff --git a/Website/images/dnnTagClose.png b/Website/images/dnnTagClose.png new file mode 100644 index 00000000000..ea39e3778d1 Binary files /dev/null and b/Website/images/dnnTagClose.png differ diff --git a/Website/images/dnnTertiaryButtonBG.png b/Website/images/dnnTertiaryButtonBG.png new file mode 100644 index 00000000000..3354c47eaad Binary files /dev/null and b/Website/images/dnnTertiaryButtonBG.png differ diff --git a/Website/images/dnnanim.gif b/Website/images/dnnanim.gif new file mode 100644 index 00000000000..5e62d01af9e Binary files /dev/null and b/Website/images/dnnanim.gif differ diff --git a/Website/images/dnrt.gif b/Website/images/dnrt.gif new file mode 100644 index 00000000000..e9244bc29e9 Binary files /dev/null and b/Website/images/dnrt.gif differ diff --git a/Website/images/down-icn.png b/Website/images/down-icn.png new file mode 100644 index 00000000000..6548aa0e7c4 Binary files /dev/null and b/Website/images/down-icn.png differ diff --git a/Website/images/edit.gif b/Website/images/edit.gif new file mode 100644 index 00000000000..88f613c8e0b Binary files /dev/null and b/Website/images/edit.gif differ diff --git a/Website/images/edit_pen.gif b/Website/images/edit_pen.gif new file mode 100644 index 00000000000..2a7b04504fa Binary files /dev/null and b/Website/images/edit_pen.gif differ diff --git a/Website/images/eip_edit.png b/Website/images/eip_edit.png new file mode 100644 index 00000000000..842032f9ffd Binary files /dev/null and b/Website/images/eip_edit.png differ diff --git a/Website/images/eip_save.png b/Website/images/eip_save.png new file mode 100644 index 00000000000..b7ada0f6c04 Binary files /dev/null and b/Website/images/eip_save.png differ diff --git a/Website/images/eip_title_cancel.png b/Website/images/eip_title_cancel.png new file mode 100644 index 00000000000..f81c7a21754 Binary files /dev/null and b/Website/images/eip_title_cancel.png differ diff --git a/Website/images/eip_title_save.png b/Website/images/eip_title_save.png new file mode 100644 index 00000000000..d9ad55f9847 Binary files /dev/null and b/Website/images/eip_title_save.png differ diff --git a/Website/images/eip_toolbar.png b/Website/images/eip_toolbar.png new file mode 100644 index 00000000000..383018127f8 Binary files /dev/null and b/Website/images/eip_toolbar.png differ diff --git a/Website/images/empty.png b/Website/images/empty.png new file mode 100644 index 00000000000..22e105dd069 Binary files /dev/null and b/Website/images/empty.png differ diff --git a/Website/images/end.gif b/Website/images/end.gif new file mode 100644 index 00000000000..e4cecec9c13 Binary files /dev/null and b/Website/images/end.gif differ diff --git a/Website/images/epi_save.gif b/Website/images/epi_save.gif new file mode 100644 index 00000000000..7e98ed50972 Binary files /dev/null and b/Website/images/epi_save.gif differ diff --git a/Website/images/error-icn.png b/Website/images/error-icn.png new file mode 100644 index 00000000000..c2299456b10 Binary files /dev/null and b/Website/images/error-icn.png differ diff --git a/Website/images/error-pointer.png b/Website/images/error-pointer.png new file mode 100644 index 00000000000..975a1388bbc Binary files /dev/null and b/Website/images/error-pointer.png differ diff --git a/Website/images/error_tooltip_ie.png b/Website/images/error_tooltip_ie.png new file mode 100644 index 00000000000..82cc6c15681 Binary files /dev/null and b/Website/images/error_tooltip_ie.png differ diff --git a/Website/images/errorbg.gif b/Website/images/errorbg.gif new file mode 100644 index 00000000000..f6b57126c9f Binary files /dev/null and b/Website/images/errorbg.gif differ diff --git a/Website/images/expand.gif b/Website/images/expand.gif new file mode 100644 index 00000000000..7f951173433 Binary files /dev/null and b/Website/images/expand.gif differ diff --git a/Website/images/ffwd.gif b/Website/images/ffwd.gif new file mode 100644 index 00000000000..3c1a0d1e59f Binary files /dev/null and b/Website/images/ffwd.gif differ diff --git a/Website/images/file.gif b/Website/images/file.gif new file mode 100644 index 00000000000..f768081a235 Binary files /dev/null and b/Website/images/file.gif differ diff --git a/Website/images/finishflag.png b/Website/images/finishflag.png new file mode 100644 index 00000000000..0bbe4c24de6 Binary files /dev/null and b/Website/images/finishflag.png differ diff --git a/Website/images/folder.gif b/Website/images/folder.gif new file mode 100644 index 00000000000..89c64cd2812 Binary files /dev/null and b/Website/images/folder.gif differ diff --git a/Website/images/folderblank.gif b/Website/images/folderblank.gif new file mode 100644 index 00000000000..85df9a36ff9 Binary files /dev/null and b/Website/images/folderblank.gif differ diff --git a/Website/images/folderclosed.gif b/Website/images/folderclosed.gif new file mode 100644 index 00000000000..89c64cd2812 Binary files /dev/null and b/Website/images/folderclosed.gif differ diff --git a/Website/images/folderminus.gif b/Website/images/folderminus.gif new file mode 100644 index 00000000000..11ae43a5ae0 Binary files /dev/null and b/Website/images/folderminus.gif differ diff --git a/Website/images/folderopen.gif b/Website/images/folderopen.gif new file mode 100644 index 00000000000..8788aeb159c Binary files /dev/null and b/Website/images/folderopen.gif differ diff --git a/Website/images/folderplus.gif b/Website/images/folderplus.gif new file mode 100644 index 00000000000..b87f0031545 Binary files /dev/null and b/Website/images/folderplus.gif differ diff --git a/Website/images/folderup.gif b/Website/images/folderup.gif new file mode 100644 index 00000000000..1c893931fa7 Binary files /dev/null and b/Website/images/folderup.gif differ diff --git a/Website/images/frev.gif b/Website/images/frev.gif new file mode 100644 index 00000000000..9b8b811077e Binary files /dev/null and b/Website/images/frev.gif differ diff --git a/Website/images/frew.gif b/Website/images/frew.gif new file mode 100644 index 00000000000..0859a6dd7b8 Binary files /dev/null and b/Website/images/frew.gif differ diff --git a/Website/images/fwd.gif b/Website/images/fwd.gif new file mode 100644 index 00000000000..9336c340651 Binary files /dev/null and b/Website/images/fwd.gif differ diff --git a/Website/images/grant.gif b/Website/images/grant.gif new file mode 100644 index 00000000000..b4d6e1b050a Binary files /dev/null and b/Website/images/grant.gif differ diff --git a/Website/images/green-ok.gif b/Website/images/green-ok.gif new file mode 100644 index 00000000000..475bbdb7b8f Binary files /dev/null and b/Website/images/green-ok.gif differ diff --git a/Website/images/help-icn.png b/Website/images/help-icn.png new file mode 100644 index 00000000000..e71f1a56e26 Binary files /dev/null and b/Website/images/help-icn.png differ diff --git a/Website/images/help.gif b/Website/images/help.gif new file mode 100644 index 00000000000..1262e3656d6 Binary files /dev/null and b/Website/images/help.gif differ diff --git a/Website/images/helpI-icn-grey.png b/Website/images/helpI-icn-grey.png new file mode 100644 index 00000000000..72be03de6ff Binary files /dev/null and b/Website/images/helpI-icn-grey.png differ diff --git a/Website/images/icon-FAQ-32px.png b/Website/images/icon-FAQ-32px.png new file mode 100644 index 00000000000..768a1464bd4 Binary files /dev/null and b/Website/images/icon-FAQ-32px.png differ diff --git a/Website/images/icon-announcements-32px.png b/Website/images/icon-announcements-32px.png new file mode 100644 index 00000000000..cb0b6b530e1 Binary files /dev/null and b/Website/images/icon-announcements-32px.png differ diff --git a/Website/images/icon-events-32px.png b/Website/images/icon-events-32px.png new file mode 100644 index 00000000000..21da41a63b6 Binary files /dev/null and b/Website/images/icon-events-32px.png differ diff --git a/Website/images/icon-feedback-32px.png b/Website/images/icon-feedback-32px.png new file mode 100644 index 00000000000..abdce46c6e4 Binary files /dev/null and b/Website/images/icon-feedback-32px.png differ diff --git a/Website/images/icon-fnl-32px.png b/Website/images/icon-fnl-32px.png new file mode 100644 index 00000000000..6fd02bb1e03 Binary files /dev/null and b/Website/images/icon-fnl-32px.png differ diff --git a/Website/images/icon-iframe-32px.png b/Website/images/icon-iframe-32px.png new file mode 100644 index 00000000000..ad514369dc7 Binary files /dev/null and b/Website/images/icon-iframe-32px.png differ diff --git a/Website/images/icon-links-32px.png b/Website/images/icon-links-32px.png new file mode 100644 index 00000000000..3e7cb8debcd Binary files /dev/null and b/Website/images/icon-links-32px.png differ diff --git a/Website/images/icon-media-32px.png b/Website/images/icon-media-32px.png new file mode 100644 index 00000000000..23b78271b19 Binary files /dev/null and b/Website/images/icon-media-32px.png differ diff --git a/Website/images/icon_Vendors_16px.gif b/Website/images/icon_Vendors_16px.gif new file mode 100644 index 00000000000..a86a6bebed3 Binary files /dev/null and b/Website/images/icon_Vendors_16px.gif differ diff --git a/Website/images/icon_Vendors_32px.gif b/Website/images/icon_Vendors_32px.gif new file mode 100644 index 00000000000..8318ab4cad4 Binary files /dev/null and b/Website/images/icon_Vendors_32px.gif differ diff --git a/Website/images/icon_activatelicense_16px.gif b/Website/images/icon_activatelicense_16px.gif new file mode 100644 index 00000000000..9c1e9761dc8 Binary files /dev/null and b/Website/images/icon_activatelicense_16px.gif differ diff --git a/Website/images/icon_activatelicense_32px.gif b/Website/images/icon_activatelicense_32px.gif new file mode 100644 index 00000000000..61ced53a1f5 Binary files /dev/null and b/Website/images/icon_activatelicense_32px.gif differ diff --git a/Website/images/icon_analytics_16px.gif b/Website/images/icon_analytics_16px.gif new file mode 100644 index 00000000000..0324641e55c Binary files /dev/null and b/Website/images/icon_analytics_16px.gif differ diff --git a/Website/images/icon_analytics_32px.gif b/Website/images/icon_analytics_32px.gif new file mode 100644 index 00000000000..89122c132d2 Binary files /dev/null and b/Website/images/icon_analytics_32px.gif differ diff --git a/Website/images/icon_appintegrity_16px.gif b/Website/images/icon_appintegrity_16px.gif new file mode 100644 index 00000000000..30e40cd659a Binary files /dev/null and b/Website/images/icon_appintegrity_16px.gif differ diff --git a/Website/images/icon_appintegrity_32px.gif b/Website/images/icon_appintegrity_32px.gif new file mode 100644 index 00000000000..ade721e8649 Binary files /dev/null and b/Website/images/icon_appintegrity_32px.gif differ diff --git a/Website/images/icon_authentication.png b/Website/images/icon_authentication.png new file mode 100644 index 00000000000..aeff5fae34b Binary files /dev/null and b/Website/images/icon_authentication.png differ diff --git a/Website/images/icon_authentication_16px.gif b/Website/images/icon_authentication_16px.gif new file mode 100644 index 00000000000..38ff573cbaf Binary files /dev/null and b/Website/images/icon_authentication_16px.gif differ diff --git a/Website/images/icon_authentication_32px.gif b/Website/images/icon_authentication_32px.gif new file mode 100644 index 00000000000..1df78acf29d Binary files /dev/null and b/Website/images/icon_authentication_32px.gif differ diff --git a/Website/images/icon_bulkmail_16px.gif b/Website/images/icon_bulkmail_16px.gif new file mode 100644 index 00000000000..9e1b61d6463 Binary files /dev/null and b/Website/images/icon_bulkmail_16px.gif differ diff --git a/Website/images/icon_bulkmail_32px.gif b/Website/images/icon_bulkmail_32px.gif new file mode 100644 index 00000000000..956b4cb33f0 Binary files /dev/null and b/Website/images/icon_bulkmail_32px.gif differ diff --git a/Website/images/icon_configuration_16px.png b/Website/images/icon_configuration_16px.png new file mode 100644 index 00000000000..597b90f6dfa Binary files /dev/null and b/Website/images/icon_configuration_16px.png differ diff --git a/Website/images/icon_configuration_32px.png b/Website/images/icon_configuration_32px.png new file mode 100644 index 00000000000..f38bc9ca1df Binary files /dev/null and b/Website/images/icon_configuration_32px.png differ diff --git a/Website/images/icon_container.gif b/Website/images/icon_container.gif new file mode 100644 index 00000000000..4ebf63a1688 Binary files /dev/null and b/Website/images/icon_container.gif differ diff --git a/Website/images/icon_dashboard.png b/Website/images/icon_dashboard.png new file mode 100644 index 00000000000..b74757e87bc Binary files /dev/null and b/Website/images/icon_dashboard.png differ diff --git a/Website/images/icon_dashboard_16px.gif b/Website/images/icon_dashboard_16px.gif new file mode 100644 index 00000000000..96f71623457 Binary files /dev/null and b/Website/images/icon_dashboard_16px.gif differ diff --git a/Website/images/icon_dashboard_32px.gif b/Website/images/icon_dashboard_32px.gif new file mode 100644 index 00000000000..ba68005dc2c Binary files /dev/null and b/Website/images/icon_dashboard_32px.gif differ diff --git a/Website/images/icon_exceptionviewer_16px.gif b/Website/images/icon_exceptionviewer_16px.gif new file mode 100644 index 00000000000..1b9c92185e5 Binary files /dev/null and b/Website/images/icon_exceptionviewer_16px.gif differ diff --git a/Website/images/icon_extensions.gif b/Website/images/icon_extensions.gif new file mode 100644 index 00000000000..be8ed083c82 Binary files /dev/null and b/Website/images/icon_extensions.gif differ diff --git a/Website/images/icon_extensions_16px.png b/Website/images/icon_extensions_16px.png new file mode 100644 index 00000000000..3edfbf740c7 Binary files /dev/null and b/Website/images/icon_extensions_16px.png differ diff --git a/Website/images/icon_extensions_32px.png b/Website/images/icon_extensions_32px.png new file mode 100644 index 00000000000..6559ea980af Binary files /dev/null and b/Website/images/icon_extensions_32px.png differ diff --git a/Website/images/icon_filemanager_16px.gif b/Website/images/icon_filemanager_16px.gif new file mode 100644 index 00000000000..cd58d00462b Binary files /dev/null and b/Website/images/icon_filemanager_16px.gif differ diff --git a/Website/images/icon_filemanager_32px.gif b/Website/images/icon_filemanager_32px.gif new file mode 100644 index 00000000000..653f92846db Binary files /dev/null and b/Website/images/icon_filemanager_32px.gif differ diff --git a/Website/images/icon_health_16px.gif b/Website/images/icon_health_16px.gif new file mode 100644 index 00000000000..abf7c56f63a Binary files /dev/null and b/Website/images/icon_health_16px.gif differ diff --git a/Website/images/icon_health_32px.gif b/Website/images/icon_health_32px.gif new file mode 100644 index 00000000000..7d92b63f0ad Binary files /dev/null and b/Website/images/icon_health_32px.gif differ diff --git a/Website/images/icon_help_32px.gif b/Website/images/icon_help_32px.gif new file mode 100644 index 00000000000..30ea938d904 Binary files /dev/null and b/Website/images/icon_help_32px.gif differ diff --git a/Website/images/icon_host_16px.gif b/Website/images/icon_host_16px.gif new file mode 100644 index 00000000000..c176805c5dc Binary files /dev/null and b/Website/images/icon_host_16px.gif differ diff --git a/Website/images/icon_host_32px.gif b/Website/images/icon_host_32px.gif new file mode 100644 index 00000000000..248a904f14e Binary files /dev/null and b/Website/images/icon_host_32px.gif differ diff --git a/Website/images/icon_hostsettings_16px.gif b/Website/images/icon_hostsettings_16px.gif new file mode 100644 index 00000000000..35d63393177 Binary files /dev/null and b/Website/images/icon_hostsettings_16px.gif differ diff --git a/Website/images/icon_hostsettings_32px.gif b/Website/images/icon_hostsettings_32px.gif new file mode 100644 index 00000000000..9a192a85dfd Binary files /dev/null and b/Website/images/icon_hostsettings_32px.gif differ diff --git a/Website/images/icon_hostusers_16px.gif b/Website/images/icon_hostusers_16px.gif new file mode 100644 index 00000000000..3756e12edb9 Binary files /dev/null and b/Website/images/icon_hostusers_16px.gif differ diff --git a/Website/images/icon_hostusers_32px.gif b/Website/images/icon_hostusers_32px.gif new file mode 100644 index 00000000000..e25a47b9f6a Binary files /dev/null and b/Website/images/icon_hostusers_32px.gif differ diff --git a/Website/images/icon_kb_16px.gif b/Website/images/icon_kb_16px.gif new file mode 100644 index 00000000000..09fc3822b2a Binary files /dev/null and b/Website/images/icon_kb_16px.gif differ diff --git a/Website/images/icon_kb_32px.gif b/Website/images/icon_kb_32px.gif new file mode 100644 index 00000000000..30f37e13280 Binary files /dev/null and b/Website/images/icon_kb_32px.gif differ diff --git a/Website/images/icon_languagePack.gif b/Website/images/icon_languagePack.gif new file mode 100644 index 00000000000..c2e61724bc1 Binary files /dev/null and b/Website/images/icon_languagePack.gif differ diff --git a/Website/images/icon_language_16px.gif b/Website/images/icon_language_16px.gif new file mode 100644 index 00000000000..ba6719a0565 Binary files /dev/null and b/Website/images/icon_language_16px.gif differ diff --git a/Website/images/icon_language_32px.gif b/Website/images/icon_language_32px.gif new file mode 100644 index 00000000000..d4ed905563c Binary files /dev/null and b/Website/images/icon_language_32px.gif differ diff --git a/Website/images/icon_library.png b/Website/images/icon_library.png new file mode 100644 index 00000000000..c642cf46d81 Binary files /dev/null and b/Website/images/icon_library.png differ diff --git a/Website/images/icon_licensemgmt_16px.gif b/Website/images/icon_licensemgmt_16px.gif new file mode 100644 index 00000000000..1ecf8600b99 Binary files /dev/null and b/Website/images/icon_licensemgmt_16px.gif differ diff --git a/Website/images/icon_licensemgmt_32px.gif b/Website/images/icon_licensemgmt_32px.gif new file mode 100644 index 00000000000..c1120dbe4b4 Binary files /dev/null and b/Website/images/icon_licensemgmt_32px.gif differ diff --git a/Website/images/icon_lists_16px.gif b/Website/images/icon_lists_16px.gif new file mode 100644 index 00000000000..d5f88c7c79c Binary files /dev/null and b/Website/images/icon_lists_16px.gif differ diff --git a/Website/images/icon_lists_32px.gif b/Website/images/icon_lists_32px.gif new file mode 100644 index 00000000000..a55b18a45ef Binary files /dev/null and b/Website/images/icon_lists_32px.gif differ diff --git a/Website/images/icon_marketplace_16px.gif b/Website/images/icon_marketplace_16px.gif new file mode 100644 index 00000000000..b6bf9583a7b Binary files /dev/null and b/Website/images/icon_marketplace_16px.gif differ diff --git a/Website/images/icon_marketplace_32px.gif b/Website/images/icon_marketplace_32px.gif new file mode 100644 index 00000000000..2cac2e30bb5 Binary files /dev/null and b/Website/images/icon_marketplace_32px.gif differ diff --git a/Website/images/icon_moduledefinitions_16px.gif b/Website/images/icon_moduledefinitions_16px.gif new file mode 100644 index 00000000000..16b811854ec Binary files /dev/null and b/Website/images/icon_moduledefinitions_16px.gif differ diff --git a/Website/images/icon_moduledefinitions_32px.gif b/Website/images/icon_moduledefinitions_32px.gif new file mode 100644 index 00000000000..f039bf91d45 Binary files /dev/null and b/Website/images/icon_moduledefinitions_32px.gif differ diff --git a/Website/images/icon_modules.png b/Website/images/icon_modules.png new file mode 100644 index 00000000000..14ba936ac03 Binary files /dev/null and b/Website/images/icon_modules.png differ diff --git a/Website/images/icon_mytickets_16px.gif b/Website/images/icon_mytickets_16px.gif new file mode 100644 index 00000000000..ea19eab48b6 Binary files /dev/null and b/Website/images/icon_mytickets_16px.gif differ diff --git a/Website/images/icon_mytickets_32px.gif b/Website/images/icon_mytickets_32px.gif new file mode 100644 index 00000000000..332af038743 Binary files /dev/null and b/Website/images/icon_mytickets_32px.gif differ diff --git a/Website/images/icon_profeatures_16px.gif b/Website/images/icon_profeatures_16px.gif new file mode 100644 index 00000000000..b1a39bb403d Binary files /dev/null and b/Website/images/icon_profeatures_16px.gif differ diff --git a/Website/images/icon_profile_16px.gif b/Website/images/icon_profile_16px.gif new file mode 100644 index 00000000000..9a5d911ea8d Binary files /dev/null and b/Website/images/icon_profile_16px.gif differ diff --git a/Website/images/icon_profile_32px.gif b/Website/images/icon_profile_32px.gif new file mode 100644 index 00000000000..46e92384fbe Binary files /dev/null and b/Website/images/icon_profile_32px.gif differ diff --git a/Website/images/icon_provider.gif b/Website/images/icon_provider.gif new file mode 100644 index 00000000000..1930b33824d Binary files /dev/null and b/Website/images/icon_provider.gif differ diff --git a/Website/images/icon_publishlanguage_16.gif b/Website/images/icon_publishlanguage_16.gif new file mode 100644 index 00000000000..77543e19a8b Binary files /dev/null and b/Website/images/icon_publishlanguage_16.gif differ diff --git a/Website/images/icon_recyclebin_16px.gif b/Website/images/icon_recyclebin_16px.gif new file mode 100644 index 00000000000..bf3bfac6e88 Binary files /dev/null and b/Website/images/icon_recyclebin_16px.gif differ diff --git a/Website/images/icon_recyclebin_32px.gif b/Website/images/icon_recyclebin_32px.gif new file mode 100644 index 00000000000..e4acc3d9a91 Binary files /dev/null and b/Website/images/icon_recyclebin_32px.gif differ diff --git a/Website/images/icon_scheduler_16px.gif b/Website/images/icon_scheduler_16px.gif new file mode 100644 index 00000000000..cc8f0a8c2e9 Binary files /dev/null and b/Website/images/icon_scheduler_16px.gif differ diff --git a/Website/images/icon_scheduler_32px.gif b/Website/images/icon_scheduler_32px.gif new file mode 100644 index 00000000000..4434f4b3f27 Binary files /dev/null and b/Website/images/icon_scheduler_32px.gif differ diff --git a/Website/images/icon_search_16px.gif b/Website/images/icon_search_16px.gif new file mode 100644 index 00000000000..059ee28ab94 Binary files /dev/null and b/Website/images/icon_search_16px.gif differ diff --git a/Website/images/icon_search_32px.gif b/Website/images/icon_search_32px.gif new file mode 100644 index 00000000000..00540d11f85 Binary files /dev/null and b/Website/images/icon_search_32px.gif differ diff --git a/Website/images/icon_securityroles_16px.gif b/Website/images/icon_securityroles_16px.gif new file mode 100644 index 00000000000..46ed7d8d27a Binary files /dev/null and b/Website/images/icon_securityroles_16px.gif differ diff --git a/Website/images/icon_securityroles_32px.gif b/Website/images/icon_securityroles_32px.gif new file mode 100644 index 00000000000..119c86dbda9 Binary files /dev/null and b/Website/images/icon_securityroles_32px.gif differ diff --git a/Website/images/icon_siteMap_16px.gif b/Website/images/icon_siteMap_16px.gif new file mode 100644 index 00000000000..e444478a528 Binary files /dev/null and b/Website/images/icon_siteMap_16px.gif differ diff --git a/Website/images/icon_siteMap_32px.gif b/Website/images/icon_siteMap_32px.gif new file mode 100644 index 00000000000..2b2b9d05bde Binary files /dev/null and b/Website/images/icon_siteMap_32px.gif differ diff --git a/Website/images/icon_site_16px.gif b/Website/images/icon_site_16px.gif new file mode 100644 index 00000000000..c176805c5dc Binary files /dev/null and b/Website/images/icon_site_16px.gif differ diff --git a/Website/images/icon_site_32px.gif b/Website/images/icon_site_32px.gif new file mode 100644 index 00000000000..248a904f14e Binary files /dev/null and b/Website/images/icon_site_32px.gif differ diff --git a/Website/images/icon_sitelog_16px.gif b/Website/images/icon_sitelog_16px.gif new file mode 100644 index 00000000000..275710c0252 Binary files /dev/null and b/Website/images/icon_sitelog_16px.gif differ diff --git a/Website/images/icon_sitelog_32px.gif b/Website/images/icon_sitelog_32px.gif new file mode 100644 index 00000000000..05100b5850f Binary files /dev/null and b/Website/images/icon_sitelog_32px.gif differ diff --git a/Website/images/icon_sitesettings_16px.gif b/Website/images/icon_sitesettings_16px.gif new file mode 100644 index 00000000000..4a809d2e87d Binary files /dev/null and b/Website/images/icon_sitesettings_16px.gif differ diff --git a/Website/images/icon_sitesettings_32px.gif b/Website/images/icon_sitesettings_32px.gif new file mode 100644 index 00000000000..c02bef146ca Binary files /dev/null and b/Website/images/icon_sitesettings_32px.gif differ diff --git a/Website/images/icon_skin.gif b/Website/images/icon_skin.gif new file mode 100644 index 00000000000..6aed05b4795 Binary files /dev/null and b/Website/images/icon_skin.gif differ diff --git a/Website/images/icon_skins.png b/Website/images/icon_skins.png new file mode 100644 index 00000000000..1efe718cdf1 Binary files /dev/null and b/Website/images/icon_skins.png differ diff --git a/Website/images/icon_skins_16px.gif b/Website/images/icon_skins_16px.gif new file mode 100644 index 00000000000..687f78349a6 Binary files /dev/null and b/Website/images/icon_skins_16px.gif differ diff --git a/Website/images/icon_skins_32px.gif b/Website/images/icon_skins_32px.gif new file mode 100644 index 00000000000..ecba74b0751 Binary files /dev/null and b/Website/images/icon_skins_32px.gif differ diff --git a/Website/images/icon_software_16px.gif b/Website/images/icon_software_16px.gif new file mode 100644 index 00000000000..6b1a99e18f9 Binary files /dev/null and b/Website/images/icon_software_16px.gif differ diff --git a/Website/images/icon_software_32px.gif b/Website/images/icon_software_32px.gif new file mode 100644 index 00000000000..4dba437919e Binary files /dev/null and b/Website/images/icon_software_32px.gif differ diff --git a/Website/images/icon_solutions_16px.gif b/Website/images/icon_solutions_16px.gif new file mode 100644 index 00000000000..c630ae6af76 Binary files /dev/null and b/Website/images/icon_solutions_16px.gif differ diff --git a/Website/images/icon_solutions_32px.gif b/Website/images/icon_solutions_32px.gif new file mode 100644 index 00000000000..04dcf63c8bf Binary files /dev/null and b/Website/images/icon_solutions_32px.gif differ diff --git a/Website/images/icon_source_32px.gif b/Website/images/icon_source_32px.gif new file mode 100644 index 00000000000..a7b2469ba2a Binary files /dev/null and b/Website/images/icon_source_32px.gif differ diff --git a/Website/images/icon_specialoffers_16px.gif b/Website/images/icon_specialoffers_16px.gif new file mode 100644 index 00000000000..aedfe4bdb53 Binary files /dev/null and b/Website/images/icon_specialoffers_16px.gif differ diff --git a/Website/images/icon_specialoffers_32px.gif b/Website/images/icon_specialoffers_32px.gif new file mode 100644 index 00000000000..2847f5b20a5 Binary files /dev/null and b/Website/images/icon_specialoffers_32px.gif differ diff --git a/Website/images/icon_sql_16px.gif b/Website/images/icon_sql_16px.gif new file mode 100644 index 00000000000..cbcc8324320 Binary files /dev/null and b/Website/images/icon_sql_16px.gif differ diff --git a/Website/images/icon_sql_32px.gif b/Website/images/icon_sql_32px.gif new file mode 100644 index 00000000000..ae8bd0f5a30 Binary files /dev/null and b/Website/images/icon_sql_32px.gif differ diff --git a/Website/images/icon_support_16px.gif b/Website/images/icon_support_16px.gif new file mode 100644 index 00000000000..47160cc5de8 Binary files /dev/null and b/Website/images/icon_support_16px.gif differ diff --git a/Website/images/icon_support_32px.gif b/Website/images/icon_support_32px.gif new file mode 100644 index 00000000000..b0ae757bb8c Binary files /dev/null and b/Website/images/icon_support_32px.gif differ diff --git a/Website/images/icon_survey_32px.gif b/Website/images/icon_survey_32px.gif new file mode 100644 index 00000000000..6e38bfdff23 Binary files /dev/null and b/Website/images/icon_survey_32px.gif differ diff --git a/Website/images/icon_tabs_16px.gif b/Website/images/icon_tabs_16px.gif new file mode 100644 index 00000000000..5929637d280 Binary files /dev/null and b/Website/images/icon_tabs_16px.gif differ diff --git a/Website/images/icon_tabs_32px.gif b/Website/images/icon_tabs_32px.gif new file mode 100644 index 00000000000..4c65dd2176d Binary files /dev/null and b/Website/images/icon_tabs_32px.gif differ diff --git a/Website/images/icon_tag_16px.gif b/Website/images/icon_tag_16px.gif new file mode 100644 index 00000000000..b578decc1a5 Binary files /dev/null and b/Website/images/icon_tag_16px.gif differ diff --git a/Website/images/icon_tag_32px.gif b/Website/images/icon_tag_32px.gif new file mode 100644 index 00000000000..c49172944f2 Binary files /dev/null and b/Website/images/icon_tag_32px.gif differ diff --git a/Website/images/icon_unknown_16px.gif b/Website/images/icon_unknown_16px.gif new file mode 100644 index 00000000000..446926d0258 Binary files /dev/null and b/Website/images/icon_unknown_16px.gif differ diff --git a/Website/images/icon_unknown_32px.gif b/Website/images/icon_unknown_32px.gif new file mode 100644 index 00000000000..8c47a00ee9f Binary files /dev/null and b/Website/images/icon_unknown_32px.gif differ diff --git a/Website/images/icon_usersSwitcher_16px.gif b/Website/images/icon_usersSwitcher_16px.gif new file mode 100644 index 00000000000..195f2ef40a3 Binary files /dev/null and b/Website/images/icon_usersSwitcher_16px.gif differ diff --git a/Website/images/icon_usersSwitcher_32px.gif b/Website/images/icon_usersSwitcher_32px.gif new file mode 100644 index 00000000000..91f79945b83 Binary files /dev/null and b/Website/images/icon_usersSwitcher_32px.gif differ diff --git a/Website/images/icon_users_16px.gif b/Website/images/icon_users_16px.gif new file mode 100644 index 00000000000..195f2ef40a3 Binary files /dev/null and b/Website/images/icon_users_16px.gif differ diff --git a/Website/images/icon_users_32px.gif b/Website/images/icon_users_32px.gif new file mode 100644 index 00000000000..91f79945b83 Binary files /dev/null and b/Website/images/icon_users_32px.gif differ diff --git a/Website/images/icon_viewScheduleHistory_16px.gif b/Website/images/icon_viewScheduleHistory_16px.gif new file mode 100644 index 00000000000..d3150057b9f Binary files /dev/null and b/Website/images/icon_viewScheduleHistory_16px.gif differ diff --git a/Website/images/icon_viewstats_16px.gif b/Website/images/icon_viewstats_16px.gif new file mode 100644 index 00000000000..3d56b9d9054 Binary files /dev/null and b/Website/images/icon_viewstats_16px.gif differ diff --git a/Website/images/icon_viewstats_32px.gif b/Website/images/icon_viewstats_32px.gif new file mode 100644 index 00000000000..980d1f86414 Binary files /dev/null and b/Website/images/icon_viewstats_32px.gif differ diff --git a/Website/images/icon_wait.gif b/Website/images/icon_wait.gif new file mode 100644 index 00000000000..3288d1035d7 Binary files /dev/null and b/Website/images/icon_wait.gif differ diff --git a/Website/images/icon_webservers_16px.gif b/Website/images/icon_webservers_16px.gif new file mode 100644 index 00000000000..5c0840e97c4 Binary files /dev/null and b/Website/images/icon_webservers_16px.gif differ diff --git a/Website/images/icon_webservers_32px.gif b/Website/images/icon_webservers_32px.gif new file mode 100644 index 00000000000..659bc9ec252 Binary files /dev/null and b/Website/images/icon_webservers_32px.gif differ diff --git a/Website/images/icon_whatsnew_16px.gif b/Website/images/icon_whatsnew_16px.gif new file mode 100644 index 00000000000..1d84468e401 Binary files /dev/null and b/Website/images/icon_whatsnew_16px.gif differ diff --git a/Website/images/icon_whatsnew_32px.gif b/Website/images/icon_whatsnew_32px.gif new file mode 100644 index 00000000000..a33974a93c4 Binary files /dev/null and b/Website/images/icon_whatsnew_32px.gif differ diff --git a/Website/images/icon_widget.png b/Website/images/icon_widget.png new file mode 100644 index 00000000000..cd3bcac4320 Binary files /dev/null and b/Website/images/icon_widget.png differ diff --git a/Website/images/icon_wizard_16px.gif b/Website/images/icon_wizard_16px.gif new file mode 100644 index 00000000000..66f54a22a31 Binary files /dev/null and b/Website/images/icon_wizard_16px.gif differ diff --git a/Website/images/icon_wizard_32px.gif b/Website/images/icon_wizard_32px.gif new file mode 100644 index 00000000000..540b9b3bc34 Binary files /dev/null and b/Website/images/icon_wizard_32px.gif differ diff --git a/Website/images/installer-feedback-states-sprite.png b/Website/images/installer-feedback-states-sprite.png new file mode 100644 index 00000000000..962e15d0ff6 Binary files /dev/null and b/Website/images/installer-feedback-states-sprite.png differ diff --git a/Website/images/left-tile.gif b/Website/images/left-tile.gif new file mode 100644 index 00000000000..49ef49a655a Binary files /dev/null and b/Website/images/left-tile.gif differ diff --git a/Website/images/loading.gif b/Website/images/loading.gif new file mode 100644 index 00000000000..5f524de11fe Binary files /dev/null and b/Website/images/loading.gif differ diff --git a/Website/images/lock.gif b/Website/images/lock.gif new file mode 100644 index 00000000000..4fdff2f298e Binary files /dev/null and b/Website/images/lock.gif differ diff --git a/Website/images/login.gif b/Website/images/login.gif new file mode 100644 index 00000000000..7350605114d Binary files /dev/null and b/Website/images/login.gif differ diff --git a/Website/images/lt.gif b/Website/images/lt.gif new file mode 100644 index 00000000000..04ec6c89d8c Binary files /dev/null and b/Website/images/lt.gif differ diff --git a/Website/images/manage-icn.png b/Website/images/manage-icn.png new file mode 100644 index 00000000000..c4d50b4effa Binary files /dev/null and b/Website/images/manage-icn.png differ diff --git a/Website/images/max.gif b/Website/images/max.gif new file mode 100644 index 00000000000..fc71695c9af Binary files /dev/null and b/Website/images/max.gif differ diff --git a/Website/images/menu_down.gif b/Website/images/menu_down.gif new file mode 100644 index 00000000000..f851c57e57d Binary files /dev/null and b/Website/images/menu_down.gif differ diff --git a/Website/images/menu_right.gif b/Website/images/menu_right.gif new file mode 100644 index 00000000000..1c0ce5c7ab2 Binary files /dev/null and b/Website/images/menu_right.gif differ diff --git a/Website/images/min.gif b/Website/images/min.gif new file mode 100644 index 00000000000..d7d86cf91b5 Binary files /dev/null and b/Website/images/min.gif differ diff --git a/Website/images/minus.gif b/Website/images/minus.gif new file mode 100644 index 00000000000..d7d86cf91b5 Binary files /dev/null and b/Website/images/minus.gif differ diff --git a/Website/images/minus2.gif b/Website/images/minus2.gif new file mode 100644 index 00000000000..3c8f087a2e1 Binary files /dev/null and b/Website/images/minus2.gif differ diff --git a/Website/images/modal-max-min-icn.png b/Website/images/modal-max-min-icn.png new file mode 100644 index 00000000000..366e1db42ef Binary files /dev/null and b/Website/images/modal-max-min-icn.png differ diff --git a/Website/images/modal-resize-icn.png b/Website/images/modal-resize-icn.png new file mode 100644 index 00000000000..da6a5d0f534 Binary files /dev/null and b/Website/images/modal-resize-icn.png differ diff --git a/Website/images/modulebind.gif b/Website/images/modulebind.gif new file mode 100644 index 00000000000..d21ef44b28b Binary files /dev/null and b/Website/images/modulebind.gif differ diff --git a/Website/images/moduleunbind.gif b/Website/images/moduleunbind.gif new file mode 100644 index 00000000000..d3346ad7193 Binary files /dev/null and b/Website/images/moduleunbind.gif differ diff --git a/Website/images/move.gif b/Website/images/move.gif new file mode 100644 index 00000000000..ea0f232bbae Binary files /dev/null and b/Website/images/move.gif differ diff --git a/Website/images/no_avatar.gif b/Website/images/no_avatar.gif new file mode 100644 index 00000000000..5f36070a252 Binary files /dev/null and b/Website/images/no_avatar.gif differ diff --git a/Website/images/node.gif b/Website/images/node.gif new file mode 100644 index 00000000000..05d2e080fea Binary files /dev/null and b/Website/images/node.gif differ diff --git a/Website/images/overlay_bg_ie.png b/Website/images/overlay_bg_ie.png new file mode 100644 index 00000000000..f17dc9d4e28 Binary files /dev/null and b/Website/images/overlay_bg_ie.png differ diff --git a/Website/images/pagination.png b/Website/images/pagination.png new file mode 100644 index 00000000000..975edfded24 Binary files /dev/null and b/Website/images/pagination.png differ diff --git a/Website/images/password.gif b/Website/images/password.gif new file mode 100644 index 00000000000..aa09cb73a50 Binary files /dev/null and b/Website/images/password.gif differ diff --git a/Website/images/pause.gif b/Website/images/pause.gif new file mode 100644 index 00000000000..0c8c520f10d Binary files /dev/null and b/Website/images/pause.gif differ diff --git a/Website/images/pin-icn-16x16.png b/Website/images/pin-icn-16x16.png new file mode 100644 index 00000000000..d4545dc0282 Binary files /dev/null and b/Website/images/pin-icn-16x16.png differ diff --git a/Website/images/pin-icn.png b/Website/images/pin-icn.png new file mode 100644 index 00000000000..b631b3b60ad Binary files /dev/null and b/Website/images/pin-icn.png differ diff --git a/Website/images/plainbutton.gif b/Website/images/plainbutton.gif new file mode 100644 index 00000000000..9efa54d85bf Binary files /dev/null and b/Website/images/plainbutton.gif differ diff --git a/Website/images/plus.gif b/Website/images/plus.gif new file mode 100644 index 00000000000..fc71695c9af Binary files /dev/null and b/Website/images/plus.gif differ diff --git a/Website/images/plus2.gif b/Website/images/plus2.gif new file mode 100644 index 00000000000..52c1a62dcea Binary files /dev/null and b/Website/images/plus2.gif differ diff --git a/Website/images/populatelanguage.gif b/Website/images/populatelanguage.gif new file mode 100644 index 00000000000..77543e19a8b Binary files /dev/null and b/Website/images/populatelanguage.gif differ diff --git a/Website/images/print.gif b/Website/images/print.gif new file mode 100644 index 00000000000..534ee0ea51a Binary files /dev/null and b/Website/images/print.gif differ diff --git a/Website/images/privatemodule.gif b/Website/images/privatemodule.gif new file mode 100644 index 00000000000..1948497bdf6 Binary files /dev/null and b/Website/images/privatemodule.gif differ diff --git a/Website/images/progress.gif b/Website/images/progress.gif new file mode 100644 index 00000000000..e71258eab08 Binary files /dev/null and b/Website/images/progress.gif differ diff --git a/Website/images/progressbar.gif b/Website/images/progressbar.gif new file mode 100644 index 00000000000..e38b1818c5d Binary files /dev/null and b/Website/images/progressbar.gif differ diff --git a/Website/images/radiobutton.png b/Website/images/radiobutton.png new file mode 100644 index 00000000000..6ee4a007365 Binary files /dev/null and b/Website/images/radiobutton.png differ diff --git a/Website/images/ratingminus.gif b/Website/images/ratingminus.gif new file mode 100644 index 00000000000..7a86ee03432 Binary files /dev/null and b/Website/images/ratingminus.gif differ diff --git a/Website/images/ratingplus.gif b/Website/images/ratingplus.gif new file mode 100644 index 00000000000..19f071fe280 Binary files /dev/null and b/Website/images/ratingplus.gif differ diff --git a/Website/images/ratingzero.gif b/Website/images/ratingzero.gif new file mode 100644 index 00000000000..5d984bedc76 Binary files /dev/null and b/Website/images/ratingzero.gif differ diff --git a/Website/images/rec.gif b/Website/images/rec.gif new file mode 100644 index 00000000000..2a3c6faba3f Binary files /dev/null and b/Website/images/rec.gif differ diff --git a/Website/images/red-error.gif b/Website/images/red-error.gif new file mode 100644 index 00000000000..81dcf4c3575 Binary files /dev/null and b/Website/images/red-error.gif differ diff --git a/Website/images/red-error_16px.gif b/Website/images/red-error_16px.gif new file mode 100644 index 00000000000..261dc42e0ca Binary files /dev/null and b/Website/images/red-error_16px.gif differ diff --git a/Website/images/red.gif b/Website/images/red.gif new file mode 100644 index 00000000000..ed2e1ffcabf Binary files /dev/null and b/Website/images/red.gif differ diff --git a/Website/images/refresh.gif b/Website/images/refresh.gif new file mode 100644 index 00000000000..6d7e5bb4ade Binary files /dev/null and b/Website/images/refresh.gif differ diff --git a/Website/images/register.gif b/Website/images/register.gif new file mode 100644 index 00000000000..8954d853971 Binary files /dev/null and b/Website/images/register.gif differ diff --git a/Website/images/required.gif b/Website/images/required.gif new file mode 100644 index 00000000000..0be67e93b6f Binary files /dev/null and b/Website/images/required.gif differ diff --git a/Website/images/reset.gif b/Website/images/reset.gif new file mode 100644 index 00000000000..0a61fe3e917 Binary files /dev/null and b/Website/images/reset.gif differ diff --git a/Website/images/resizeBtn.png b/Website/images/resizeBtn.png new file mode 100644 index 00000000000..69ffe9cc847 Binary files /dev/null and b/Website/images/resizeBtn.png differ diff --git a/Website/images/restore.gif b/Website/images/restore.gif new file mode 100644 index 00000000000..50f6ef97fc6 Binary files /dev/null and b/Website/images/restore.gif differ diff --git a/Website/images/rev.gif b/Website/images/rev.gif new file mode 100644 index 00000000000..6a8ca1cc49f Binary files /dev/null and b/Website/images/rev.gif differ diff --git a/Website/images/rew.gif b/Website/images/rew.gif new file mode 100644 index 00000000000..40c023264e0 Binary files /dev/null and b/Website/images/rew.gif differ diff --git a/Website/images/right-tile.gif b/Website/images/right-tile.gif new file mode 100644 index 00000000000..0276bb58db9 Binary files /dev/null and b/Website/images/right-tile.gif differ diff --git a/Website/images/rss.gif b/Website/images/rss.gif new file mode 100644 index 00000000000..b0e4adf1d51 Binary files /dev/null and b/Website/images/rss.gif differ diff --git a/Website/images/rt.gif b/Website/images/rt.gif new file mode 100644 index 00000000000..cc08b836717 Binary files /dev/null and b/Website/images/rt.gif differ diff --git a/Website/images/sample-group-profile.jpg b/Website/images/sample-group-profile.jpg new file mode 100644 index 00000000000..2be9d8b2222 Binary files /dev/null and b/Website/images/sample-group-profile.jpg differ diff --git a/Website/images/save.gif b/Website/images/save.gif new file mode 100644 index 00000000000..7e98ed50972 Binary files /dev/null and b/Website/images/save.gif differ diff --git a/Website/images/search.gif b/Website/images/search.gif new file mode 100644 index 00000000000..f2a895c6d56 Binary files /dev/null and b/Website/images/search.gif differ diff --git a/Website/images/search_go.gif b/Website/images/search_go.gif new file mode 100644 index 00000000000..c8147ea92be Binary files /dev/null and b/Website/images/search_go.gif differ diff --git a/Website/images/settings.gif b/Website/images/settings.gif new file mode 100644 index 00000000000..e8ebad58e8f Binary files /dev/null and b/Website/images/settings.gif differ diff --git a/Website/images/shared.gif b/Website/images/shared.gif new file mode 100644 index 00000000000..452e29f22c7 Binary files /dev/null and b/Website/images/shared.gif differ diff --git a/Website/images/sharedmodule.gif b/Website/images/sharedmodule.gif new file mode 100644 index 00000000000..620f81259b0 Binary files /dev/null and b/Website/images/sharedmodule.gif differ diff --git a/Website/images/sharepoint_48X48.png b/Website/images/sharepoint_48X48.png new file mode 100644 index 00000000000..2475c9448be Binary files /dev/null and b/Website/images/sharepoint_48X48.png differ diff --git a/Website/images/sort-dark-sprite.png b/Website/images/sort-dark-sprite.png new file mode 100644 index 00000000000..015525522f0 Binary files /dev/null and b/Website/images/sort-dark-sprite.png differ diff --git a/Website/images/sort-sprite.png b/Website/images/sort-sprite.png new file mode 100644 index 00000000000..f6df82f8cf8 Binary files /dev/null and b/Website/images/sort-sprite.png differ diff --git a/Website/images/sortascending.gif b/Website/images/sortascending.gif new file mode 100644 index 00000000000..1fb09491989 Binary files /dev/null and b/Website/images/sortascending.gif differ diff --git a/Website/images/sortdescending.gif b/Website/images/sortdescending.gif new file mode 100644 index 00000000000..80dc21efb2f Binary files /dev/null and b/Website/images/sortdescending.gif differ diff --git a/Website/images/spacer.gif b/Website/images/spacer.gif new file mode 100644 index 00000000000..85d40aa848b Binary files /dev/null and b/Website/images/spacer.gif differ diff --git a/Website/images/stop.gif b/Website/images/stop.gif new file mode 100644 index 00000000000..f8a5a1a56c9 Binary files /dev/null and b/Website/images/stop.gif differ diff --git a/Website/images/success-icn.png b/Website/images/success-icn.png new file mode 100644 index 00000000000..b22018c533b Binary files /dev/null and b/Website/images/success-icn.png differ diff --git a/Website/images/synchronize.gif b/Website/images/synchronize.gif new file mode 100644 index 00000000000..2ef0c2d26ad Binary files /dev/null and b/Website/images/synchronize.gif differ diff --git a/Website/images/tabimage.gif b/Website/images/tabimage.gif new file mode 100644 index 00000000000..36260c3c09c Binary files /dev/null and b/Website/images/tabimage.gif differ diff --git a/Website/images/tabimage_blue.gif b/Website/images/tabimage_blue.gif new file mode 100644 index 00000000000..a5fe9ef1718 Binary files /dev/null and b/Website/images/tabimage_blue.gif differ diff --git a/Website/images/table-sort-sprite.png b/Website/images/table-sort-sprite.png new file mode 100644 index 00000000000..bee6ba817dc Binary files /dev/null and b/Website/images/table-sort-sprite.png differ diff --git a/Website/images/tableft.gif b/Website/images/tableft.gif new file mode 100644 index 00000000000..ed037b7917b Binary files /dev/null and b/Website/images/tableft.gif differ diff --git a/Website/images/tablogin_blue.gif b/Website/images/tablogin_blue.gif new file mode 100644 index 00000000000..316976acb43 Binary files /dev/null and b/Website/images/tablogin_blue.gif differ diff --git a/Website/images/tablogin_gray.gif b/Website/images/tablogin_gray.gif new file mode 100644 index 00000000000..d49375779ad Binary files /dev/null and b/Website/images/tablogin_gray.gif differ diff --git a/Website/images/tabright.gif b/Website/images/tabright.gif new file mode 100644 index 00000000000..4381223de4d Binary files /dev/null and b/Website/images/tabright.gif differ diff --git a/Website/images/tag.gif b/Website/images/tag.gif new file mode 100644 index 00000000000..8efd0ec995e Binary files /dev/null and b/Website/images/tag.gif differ diff --git a/Website/images/thumbnail.jpg b/Website/images/thumbnail.jpg new file mode 100644 index 00000000000..a14df422637 Binary files /dev/null and b/Website/images/thumbnail.jpg differ diff --git a/Website/images/thumbnail_black.png b/Website/images/thumbnail_black.png new file mode 100644 index 00000000000..87c49dbc528 Binary files /dev/null and b/Website/images/thumbnail_black.png differ diff --git a/Website/images/top-left.gif b/Website/images/top-left.gif new file mode 100644 index 00000000000..318f03797d9 Binary files /dev/null and b/Website/images/top-left.gif differ diff --git a/Website/images/top-right.gif b/Website/images/top-right.gif new file mode 100644 index 00000000000..e4a8f4aaadd Binary files /dev/null and b/Website/images/top-right.gif differ diff --git a/Website/images/top-tile.gif b/Website/images/top-tile.gif new file mode 100644 index 00000000000..930209fbf78 Binary files /dev/null and b/Website/images/top-tile.gif differ diff --git a/Website/images/top.gif b/Website/images/top.gif new file mode 100644 index 00000000000..c9995f14f1e Binary files /dev/null and b/Website/images/top.gif differ diff --git a/Website/images/total.gif b/Website/images/total.gif new file mode 100644 index 00000000000..a632034a835 Binary files /dev/null and b/Website/images/total.gif differ diff --git a/Website/images/translate.gif b/Website/images/translate.gif new file mode 100644 index 00000000000..2d9b209b8cd Binary files /dev/null and b/Website/images/translate.gif differ diff --git a/Website/images/translated.gif b/Website/images/translated.gif new file mode 100644 index 00000000000..b4ac9669275 Binary files /dev/null and b/Website/images/translated.gif differ diff --git a/Website/images/unchecked-disabled.gif b/Website/images/unchecked-disabled.gif new file mode 100644 index 00000000000..a56220d1079 Binary files /dev/null and b/Website/images/unchecked-disabled.gif differ diff --git a/Website/images/unchecked.gif b/Website/images/unchecked.gif new file mode 100644 index 00000000000..bfb4d94d2d1 Binary files /dev/null and b/Website/images/unchecked.gif differ diff --git a/Website/images/untranslate.gif b/Website/images/untranslate.gif new file mode 100644 index 00000000000..511895db2c7 Binary files /dev/null and b/Website/images/untranslate.gif differ diff --git a/Website/images/up-icn.png b/Website/images/up-icn.png new file mode 100644 index 00000000000..d94ca119866 Binary files /dev/null and b/Website/images/up-icn.png differ diff --git a/Website/images/up.gif b/Website/images/up.gif new file mode 100644 index 00000000000..30c7a737610 Binary files /dev/null and b/Website/images/up.gif differ diff --git a/Website/images/uplt.gif b/Website/images/uplt.gif new file mode 100644 index 00000000000..5a136f51bc5 Binary files /dev/null and b/Website/images/uplt.gif differ diff --git a/Website/images/uprt.gif b/Website/images/uprt.gif new file mode 100644 index 00000000000..3d509f8c443 Binary files /dev/null and b/Website/images/uprt.gif differ diff --git a/Website/images/userOnline.gif b/Website/images/userOnline.gif new file mode 100644 index 00000000000..3d3c29125a8 Binary files /dev/null and b/Website/images/userOnline.gif differ diff --git a/Website/images/videoIcon.png b/Website/images/videoIcon.png new file mode 100644 index 00000000000..c12d07f461f Binary files /dev/null and b/Website/images/videoIcon.png differ diff --git a/Website/images/view.gif b/Website/images/view.gif new file mode 100644 index 00000000000..ce6aeacd8ce Binary files /dev/null and b/Website/images/view.gif differ diff --git a/Website/images/visibility.png b/Website/images/visibility.png new file mode 100644 index 00000000000..5ca27b777c8 Binary files /dev/null and b/Website/images/visibility.png differ diff --git a/Website/images/warning-icn.png b/Website/images/warning-icn.png new file mode 100644 index 00000000000..14ce4e8a1b1 Binary files /dev/null and b/Website/images/warning-icn.png differ diff --git a/Website/images/xml.gif b/Website/images/xml.gif new file mode 100644 index 00000000000..7b1d407fe62 Binary files /dev/null and b/Website/images/xml.gif differ diff --git a/Website/images/yellow-warning.gif b/Website/images/yellow-warning.gif new file mode 100644 index 00000000000..466c4a904b3 Binary files /dev/null and b/Website/images/yellow-warning.gif differ diff --git a/Website/images/yellow-warning_16px.gif b/Website/images/yellow-warning_16px.gif new file mode 100644 index 00000000000..b2a45e02937 Binary files /dev/null and b/Website/images/yellow-warning_16px.gif differ diff --git a/Website/js/ClientAPICaps.config b/Website/js/ClientAPICaps.config new file mode 100644 index 00000000000..0141ea1a453 --- /dev/null +++ b/Website/js/ClientAPICaps.config @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Website/js/MicrosoftAjax-License.htm b/Website/js/MicrosoftAjax-License.htm new file mode 100644 index 00000000000..77581edc9eb --- /dev/null +++ b/Website/js/MicrosoftAjax-License.htm @@ -0,0 +1,244 @@ + + + + + + + + + + + + +
    + +

    Microsoft +Permissive License (Ms-PL)

    + +

     

    + +

    This license governs use +of the accompanying software. If you use the software, you accept this license. +If you do not accept the license, do not use the software.

    + +

     

    + +

    1. +Definitions

    + +

    The terms reproduce, +reproduction, derivative works, and distribution have the same meaning +here as under U.S. copyright law.

    + +

    A contribution is the +original software, or any additions or changes to the software.

    + +

    A contributor is any +person that distributes its contribution under this license.

    + +

    Licensed +patents are a contributors patent claims that read directly on its +contribution.

    + +

     

    + +

    2. +Grant of Rights

    + +

    (A) Copyright Grant- +Subject to the terms of this license, including the license conditions and +limitations in section 3, each contributor grants you a non-exclusive, +worldwide, royalty-free copyright license to reproduce its contribution, +prepare derivative works of its contribution, and distribute its contribution +or any derivative works that you create.

    + +

    (B) Patent Grant- Subject +to the terms of this license, including the license conditions and limitations +in section 3, each contributor grants you a non-exclusive, worldwide, +royalty-free license under its licensed patents to make, have made, use, sell, +offer for sale, import, and/or otherwise dispose of its contribution in the +software or derivative works of the contribution in the software.

    + +

     

    + +

    3. +Conditions and Limitations

    + +

    (A) No Trademark License- +This license does not grant you rights to use any contributors name, logo, or +trademarks.

    + +

    (B) If you bring a patent +claim against any contributor over patents that you claim are infringed by the +software, your patent license from such contributor to the software ends +automatically.

    + +

    (C) If you distribute any +portion of the software, you must retain all copyright, patent, trademark, and +attribution notices that are present in the software.

    + +

    (D) If you distribute any +portion of the software in source code form, you may do so only under this +license by including a complete copy of this license with your distribution. If +you distribute any portion of the software in compiled or object code form, you +may only do so under a license that complies with this license.

    + +

    (E) The software is +licensed as-is. You bear the risk of using it. The contributors give no +express warranties, guarantees or conditions. You may have additional consumer +rights under your local laws which this license cannot change. To the extent +permitted under your local laws, the contributors exclude the implied +warranties of merchantability, fitness for a particular purpose and +non-infringement.

    + +

    (F) If you distribute the +software or derivative works with programs you develop, you agree to indemnify, +defend, and hold harmless all contributors from any claims, including +attorneys fees, related to the distribution or use of your programs. For +clarity, you have no such obligations to a contributor for any claims based +solely on the unmodified contributions of that contributor.

    + +

    (G) If you make any +additions or changes to the original software, you may only distribute them +under a new namespace. In addition, you will clearly identify your changes or +additions as your own.

    + +

     

    + +
    + + + + diff --git a/Website/js/MicrosoftAjax.js b/Website/js/MicrosoftAjax.js new file mode 100644 index 00000000000..56c874ab489 --- /dev/null +++ b/Website/js/MicrosoftAjax.js @@ -0,0 +1,831 @@ + +Function.__typeName='Function';Function.__class=true;Function.createCallback=function Function$createCallback(method,context){var e=Function._validateParams(arguments,[{name:"method",type:Function},{name:"context",mayBeNull:true}]);if(e)throw e;return function(){var l=arguments.length;if(l>0){var args=[];for(var i=0;imaxParams){var e=Error.parameterCount();e.popStackFrame();return e;} +return null;} +Function._validateParameter=function Function$_validateParameter(param,expectedParam,paramName){var e;var expectedType=expectedParam.type;var expectedInteger=!!expectedParam.integer;var expectedDomElement=!!expectedParam.domElement;var mayBeNull=!!expectedParam.mayBeNull;e=Function._validateParameterType(param,expectedType,expectedInteger,expectedDomElement,mayBeNull,paramName);if(e){e.popStackFrame();return e;} +var expectedElementType=expectedParam.elementType;var elementMayBeNull=!!expectedParam.elementMayBeNull;if(expectedType===Array&&typeof(param)!=="undefined"&¶m!==null&&(expectedElementType||!elementMayBeNull)){var expectedElementInteger=!!expectedParam.elementInteger;var expectedElementDomElement=!!expectedParam.elementDomElement;for(var i=0;i1)&&(typeof(baseType)==='undefined'))throw Error.argumentUndefined('baseType');if(baseType&&!baseType.__class)throw Error.argument('baseType',Sys.Res.baseNotAClass);this.prototype.constructor=this;this.__typeName=typeName;this.__class=true;if(baseType){this.__baseType=baseType;this.__basePrototypePending=true;} +if(!window.__classes)window.__classes={};window.__classes[typeName.toUpperCase()]=this;if(interfaceTypes){this.__interfaces=[];for(var i=2;idtf.Calendar.TwoDigitYearMax){return year-100;}} +return year;} +Date._getParseRegExp=function Date$_getParseRegExp(dtf,format){if(!dtf._parseRegExp){dtf._parseRegExp={};} +else if(dtf._parseRegExp[format]){return dtf._parseRegExp[format];} +var expFormat=Date._expandFormat(dtf,format);expFormat=expFormat.replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g,"\\\\$1");var regexp=new Sys.StringBuilder("^");var groups=[];var index=0;var quoteCount=0;var tokenRegExp=Date._getTokenRegExp();var match;while((match=tokenRegExp.exec(expFormat))!==null){var preMatch=expFormat.slice(index,match.index);index=tokenRegExp.lastIndex;quoteCount+=Date._appendPreOrPostMatch(preMatch,regexp);if((quoteCount%2)===1){regexp.append(match[0]);continue;} +switch(match[0]){case'dddd':case'ddd':case'MMMM':case'MMM':regexp.append("(\\D+)");break;case'tt':case't':regexp.append("(\\D*)");break;case'yyyy':regexp.append("(\\d{4})");break;case'fff':regexp.append("(\\d{3})");break;case'ff':regexp.append("(\\d{2})");break;case'f':regexp.append("(\\d)");break;case'dd':case'd':case'MM':case'M':case'yy':case'y':case'HH':case'H':case'hh':case'h':case'mm':case'm':case'ss':case's':regexp.append("(\\d\\d?)");break;case'zzz':regexp.append("([+-]?\\d\\d?:\\d{2})");break;case'zz':case'z':regexp.append("([+-]?\\d\\d?)");break;} +Array.add(groups,match[0]);} +Date._appendPreOrPostMatch(expFormat.slice(index),regexp);regexp.append("$");var regexpStr=regexp.toString().replace(/\s+/g,"\\s+");var parseRegExp={'regExp':regexpStr,'groups':groups};dtf._parseRegExp[format]=parseRegExp;return parseRegExp;} +Date._getTokenRegExp=function Date$_getTokenRegExp(){return/dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z/g;} +Date.parseLocale=function Date$parseLocale(value,formats){var e=Function._validateParams(arguments,[{name:"value",type:String},{name:"formats",mayBeNull:true,optional:true,parameterArray:true}]);if(e)throw e;return Date._parse(value,Sys.CultureInfo.CurrentCulture,arguments);} +Date.parseInvariant=function Date$parseInvariant(value,formats){var e=Function._validateParams(arguments,[{name:"value",type:String},{name:"formats",mayBeNull:true,optional:true,parameterArray:true}]);if(e)throw e;return Date._parse(value,Sys.CultureInfo.InvariantCulture,arguments);} +Date._parse=function Date$_parse(value,cultureInfo,args){var custom=false;for(var i=1,il=args.length;i31))return null;break;case'MMMM':month=cultureInfo._getMonthIndex(matchGroup);if((month<0)||(month>11))return null;break;case'MMM':month=cultureInfo._getAbbrMonthIndex(matchGroup);if((month<0)||(month>11))return null;break;case'M':case'MM':var month=Date._parseInt(matchGroup)-1;if((month<0)||(month>11))return null;break;case'y':case'yy':year=Date._expandYear(dtf,Date._parseInt(matchGroup));if((year<0)||(year>9999))return null;break;case'yyyy':year=Date._parseInt(matchGroup);if((year<0)||(year>9999))return null;break;case'h':case'hh':hour=Date._parseInt(matchGroup);if(hour===12)hour=0;if((hour<0)||(hour>11))return null;break;case'H':case'HH':hour=Date._parseInt(matchGroup);if((hour<0)||(hour>23))return null;break;case'm':case'mm':min=Date._parseInt(matchGroup);if((min<0)||(min>59))return null;break;case's':case'ss':sec=Date._parseInt(matchGroup);if((sec<0)||(sec>59))return null;break;case'tt':case't':var upperToken=matchGroup.toUpperCase();pmHour=(upperToken===dtf.PMDesignator.toUpperCase());if(!pmHour&&(upperToken!==dtf.AMDesignator.toUpperCase()))return null;break;case'f':msec=Date._parseInt(matchGroup)*100;if((msec<0)||(msec>999))return null;break;case'ff':msec=Date._parseInt(matchGroup)*10;if((msec<0)||(msec>999))return null;break;case'fff':msec=Date._parseInt(matchGroup);if((msec<0)||(msec>999))return null;break;case'dddd':weekDay=cultureInfo._getDayIndex(matchGroup);if((weekDay<0)||(weekDay>6))return null;break;case'ddd':weekDay=cultureInfo._getAbbrDayIndex(matchGroup);if((weekDay<0)||(weekDay>6))return null;break;case'zzz':var offsets=matchGroup.split(/:/);if(offsets.length!==2)return null;var hourOffset=Date._parseInt(offsets[0]);if((hourOffset<-12)||(hourOffset>13))return null;var minOffset=Date._parseInt(offsets[1]);if((minOffset<0)||(minOffset>59))return null;tzMinOffset=(hourOffset*60)+(matchGroup.startsWith('-')?-minOffset:minOffset);break;case'z':case'zz':var hourOffset=Date._parseInt(matchGroup);if((hourOffset<-12)||(hourOffset>13))return null;tzMinOffset=hourOffset*60;break;}}} +var result=new Date();if(year===null){year=result.getFullYear();} +if(month===null){month=result.getMonth();} +if(date===null){date=result.getDate();} +result.setFullYear(year,month,date);if(result.getDate()!==date)return null;if((weekDay!==null)&&(result.getDay()!==weekDay)){return null;} +if(pmHour&&(hour<12)){hour+=12;} +result.setHours(hour,min,sec,msec);if(tzMinOffset!==null){var adjustedMin=result.getMinutes()-(tzMinOffset+result.getTimezoneOffset());result.setHours(result.getHours()+parseInt(adjustedMin/60),adjustedMin%60);} +return result;}} +Date._parseInt=function Date$_parseInt(value){return parseInt(value.replace(/^[\s0]+(\d+)$/,"$1"));} +Date.prototype.format=function Date$format(format){var e=Function._validateParams(arguments,[{name:"format",type:String}]);if(e)throw e;return this._toFormattedString(format,Sys.CultureInfo.InvariantCulture);} +Date.prototype.localeFormat=function Date$localeFormat(format){var e=Function._validateParams(arguments,[{name:"format",type:String}]);if(e)throw e;return this._toFormattedString(format,Sys.CultureInfo.CurrentCulture);} +Date.prototype._toFormattedString=function Date$_toFormattedString(format,cultureInfo){if(!format||(format.length===0)||(format==='i')){if(cultureInfo&&(cultureInfo.name.length>0)){return this.toLocaleString();} +else{return this.toString();}} +var dtf=cultureInfo.dateTimeFormat;format=Date._expandFormat(dtf,format);var ret=new Sys.StringBuilder();var hour;function addLeadingZero(num){if(num<10){return'0'+num;} +return num.toString();} +function addLeadingZeros(num){if(num<10){return'00'+num;} +if(num<100){return'0'+num;} +return num.toString();} +var quoteCount=0;var tokenRegExp=Date._getTokenRegExp();for(;;){var index=tokenRegExp.lastIndex;var ar=tokenRegExp.exec(format);var preMatch=format.slice(index,ar?ar.index:format.length);quoteCount+=Date._appendPreOrPostMatch(preMatch,ret);if(!ar)break;if((quoteCount%2)===1){ret.append(ar[0]);continue;} +switch(ar[0]){case"dddd":ret.append(dtf.DayNames[this.getDay()]);break;case"ddd":ret.append(dtf.AbbreviatedDayNames[this.getDay()]);break;case"dd":ret.append(addLeadingZero(this.getDate()));break;case"d":ret.append(this.getDate());break;case"MMMM":ret.append(dtf.MonthNames[this.getMonth()]);break;case"MMM":ret.append(dtf.AbbreviatedMonthNames[this.getMonth()]);break;case"MM":ret.append(addLeadingZero(this.getMonth()+1));break;case"M":ret.append(this.getMonth()+1);break;case"yyyy":ret.append(this.getFullYear());break;case"yy":ret.append(addLeadingZero(this.getFullYear()%100));break;case"y":ret.append(this.getFullYear()%100);break;case"hh":hour=this.getHours()%12;if(hour===0)hour=12;ret.append(addLeadingZero(hour));break;case"h":hour=this.getHours()%12;if(hour===0)hour=12;ret.append(hour);break;case"HH":ret.append(addLeadingZero(this.getHours()));break;case"H":ret.append(this.getHours());break;case"mm":ret.append(addLeadingZero(this.getMinutes()));break;case"m":ret.append(this.getMinutes());break;case"ss":ret.append(addLeadingZero(this.getSeconds()));break;case"s":ret.append(this.getSeconds());break;case"tt":ret.append((this.getHours()<12)?dtf.AMDesignator:dtf.PMDesignator);break;case"t":ret.append(((this.getHours()<12)?dtf.AMDesignator:dtf.PMDesignator).charAt(0));break;case"f":ret.append(addLeadingZeros(this.getMilliseconds()).charAt(0));break;case"ff":ret.append(addLeadingZeros(this.getMilliseconds()).substr(0,2));break;case"fff":ret.append(addLeadingZeros(this.getMilliseconds()));break;case"z":hour=this.getTimezoneOffset()/60;ret.append(((hour>=0)?'+':'-')+Math.floor(Math.abs(hour)));break;case"zz":hour=this.getTimezoneOffset()/60;ret.append(((hour>=0)?'+':'-')+addLeadingZero(Math.floor(Math.abs(hour))));break;case"zzz":hour=this.getTimezoneOffset()/60;ret.append(((hour>=0)?'+':'-')+addLeadingZero(Math.floor(Math.abs(hour)))+ +dtf.TimeSeparator+addLeadingZero(Math.abs(this.getTimezoneOffset()%60)));break;}} +return ret.toString();} +Number.__typeName='Number';Number.__class=true;Number.parseLocale=function Number$parseLocale(value){var e=Function._validateParams(arguments,[{name:"value",type:String}]);if(e)throw e;return Number._parse(value,Sys.CultureInfo.CurrentCulture);} +Number.parseInvariant=function Number$parseInvariant(value){var e=Function._validateParams(arguments,[{name:"value",type:String}]);if(e)throw e;return Number._parse(value,Sys.CultureInfo.InvariantCulture);} +Number._parse=function Number$_parse(value,cultureInfo){var valueStr=value.trim();if(valueStr.match(/infinity/i)!==null){return parseFloat(valueStr);} +if(valueStr.match(/^0x[a-f0-9]+$/i)!==null){return parseInt(valueStr);} +var numFormat=cultureInfo.numberFormat;var decSeparator=numFormat.NumberDecimalSeparator;var grpSeparator=numFormat.NumberGroupSeparator;var numberFormatRegex=new RegExp("^[+-]?[\\d\\"+grpSeparator+"]*\\"+decSeparator+"?\\d*([eE][+-]?\\d+)?$");if(!valueStr.match(numberFormatRegex)){return Number.NaN;} +valueStr=valueStr.split(grpSeparator).join("");valueStr=valueStr.replace(decSeparator,".");return parseFloat(valueStr);} +Number.prototype.format=function Number$format(format){var e=Function._validateParams(arguments,[{name:"format",type:String}]);if(e)throw e;return this._toFormattedString(format,Sys.CultureInfo.InvariantCulture);} +Number.prototype.localeFormat=function Number$localeFormat(format){var e=Function._validateParams(arguments,[{name:"format",type:String}]);if(e)throw e;return this._toFormattedString(format,Sys.CultureInfo.CurrentCulture);} +Number.prototype._toFormattedString=function Number$_toFormattedString(format,cultureInfo){if(!format||(format.length===0)||(format==='i')){if(cultureInfo&&(cultureInfo.name.length>0)){return this.toLocaleString();} +else{return this.toString();}} +var _percentPositivePattern=["n %","n%","%n"];var _percentNegativePattern=["-n %","-n%","-%n"];var _numberNegativePattern=["(n)","-n","- n","n-","n -"];var _currencyPositivePattern=["$n","n$","$ n","n $"];var _currencyNegativePattern=["($n)","-$n","$-n","$n-","(n$)","-n$","n-$","n$-","-n $","-$ n","n $-","$ n-","$ -n","n- $","($ n)","(n $)"];function expandNumber(number,precision,groupSizes,sep,decimalChar){var curSize=groupSizes[0];var curGroupIndex=1;var numberString=number.toString();var right="";var exponent="";var decimalSplit=numberString.split('.');if(decimalSplit.length>1){numberString=decimalSplit[0];right=decimalSplit[1];var exponentSplit=right.split(/e/i);if(exponentSplit.length>1){right=exponentSplit[0];exponent="e"+exponentSplit[1];}} +if(precision>0){var rightDifference=right.length-precision;if(rightDifference>0){right=right.slice(0,precision);}else if(rightDifference<0){for(var i=0;i=0){if(curSize===0||curSize>stringIndex){if(ret.length>0) +return numberString.slice(0,stringIndex+1)+sep+ret+right;else +return numberString.slice(0,stringIndex+1)+right;} +if(ret.length>0) +ret=numberString.slice(stringIndex-curSize+1,stringIndex+1)+sep+ret;else +ret=numberString.slice(stringIndex-curSize+1,stringIndex+1);stringIndex-=curSize;if(curGroupIndex1)precision=parseInt(format.slice(1));var pattern;switch(format.charAt(0)){case"d":case"D":pattern='n';if(precision!==-1){var numberStr=""+number;var zerosToAdd=precision-numberStr.length;if(zerosToAdd>0){for(var i=0;i=0);} +Array.dequeue=function Array$dequeue(array){var e=Function._validateParams(arguments,[{name:"array",type:Array,elementMayBeNull:true}]);if(e)throw e;return array.shift();} +Array.forEach=function Array$forEach(array,method,instance){var e=Function._validateParams(arguments,[{name:"array",type:Array,elementMayBeNull:true},{name:"method",type:Function},{name:"instance",mayBeNull:true,optional:true}]);if(e)throw e;for(var i=0,l=array.length;i=0){array.splice(index,1);} +return(index>=0);} +Array.removeAt=function Array$removeAt(array,index){var e=Function._validateParams(arguments,[{name:"array",type:Array,elementMayBeNull:true},{name:"index",mayBeNull:true}]);if(e)throw e;array.splice(index,1);} +String.__typeName='String';String.__class=true;String.prototype.endsWith=function String$endsWith(suffix){var e=Function._validateParams(arguments,[{name:"suffix",type:String}]);if(e)throw e;return(this.substr(this.length-suffix.length)===suffix);} +String.prototype.startsWith=function String$startsWith(prefix){var e=Function._validateParams(arguments,[{name:"prefix",type:String}]);if(e)throw e;return(this.substr(0,prefix.length)===prefix);} +String.prototype.trim=function String$trim(){if(arguments.length!==0)throw Error.parameterCount();return this.replace(/^\s+|\s+$/g,'');} +String.prototype.trimEnd=function String$trimEnd(){if(arguments.length!==0)throw Error.parameterCount();return this.replace(/\s+$/,'');} +String.prototype.trimStart=function String$trimStart(){if(arguments.length!==0)throw Error.parameterCount();return this.replace(/^\s+/,'');} +String.format=function String$format(format,args){var e=Function._validateParams(arguments,[{name:"format",type:String},{name:"args",mayBeNull:true,parameterArray:true}]);if(e)throw e;return String._toFormattedString(false,arguments);} +String.localeFormat=function String$localeFormat(format,args){var e=Function._validateParams(arguments,[{name:"format",type:String},{name:"args",mayBeNull:true,parameterArray:true}]);if(e)throw e;return String._toFormattedString(true,arguments);} +String._toFormattedString=function String$_toFormattedString(useLocale,args){var result='';var format=args[0];for(var i=0;;){var open=format.indexOf('{',i);var close=format.indexOf('}',i);if((open<0)&&(close<0)){result+=format.slice(i);break;} +if((close>0)&&((close-1){Sys.Browser.agent=Sys.Browser.InternetExplorer;Sys.Browser.version=parseFloat(navigator.userAgent.match(/MSIE (\d+\.\d+)/)[1]);Sys.Browser.hasDebuggerStatement=true;} +else if(navigator.userAgent.indexOf(' Firefox/')>-1){Sys.Browser.agent=Sys.Browser.Firefox;Sys.Browser.version=parseFloat(navigator.userAgent.match(/ Firefox\/(\d+\.\d+)/)[1]);Sys.Browser.name='Firefox';Sys.Browser.hasDebuggerStatement=true;} +else if(navigator.userAgent.indexOf(' Safari/')>-1){Sys.Browser.agent=Sys.Browser.Safari;Sys.Browser.version=parseFloat(navigator.userAgent.match(/ Safari\/(\d+\.\d+)/)[1]);Sys.Browser.name='Safari';} +else if(navigator.userAgent.indexOf('Opera/')>-1){Sys.Browser.agent=Sys.Browser.Opera;} +Type.registerNamespace('Sys.UI');Sys._Debug=function Sys$_Debug(){if(arguments.length!==0)throw Error.parameterCount();} +function Sys$_Debug$_appendConsole(text){if((typeof(Debug)!=='undefined')&&Debug.writeln){Debug.writeln(text);} +if(window.console&&window.console.log){window.console.log(text);} +if(window.opera){window.opera.postError(text);} +if(window.debugService){window.debugService.trace(text);}} +function Sys$_Debug$_appendTrace(text){var traceElement=document.getElementById('TraceConsole');if(traceElement&&(traceElement.tagName.toUpperCase()==='TEXTAREA')){traceElement.value+=text+'\n';}} +function Sys$_Debug$assert(condition,message,displayCaller){var e=Function._validateParams(arguments,[{name:"condition",type:Boolean},{name:"message",type:String,mayBeNull:true,optional:true},{name:"displayCaller",type:Boolean,optional:true}]);if(e)throw e;if(!condition){message=(displayCaller&&this.assert.caller)?String.format(Sys.Res.assertFailedCaller,message,this.assert.caller):String.format(Sys.Res.assertFailed,message);if(confirm(String.format(Sys.Res.breakIntoDebugger,message))){this.fail(message);}}} +function Sys$_Debug$clearTrace(){var traceElement=document.getElementById('TraceConsole');if(traceElement&&(traceElement.tagName.toUpperCase()==='TEXTAREA')){traceElement.value='';}} +function Sys$_Debug$fail(message){var e=Function._validateParams(arguments,[{name:"message",type:String,mayBeNull:true}]);if(e)throw e;this._appendConsole(message);if(Sys.Browser.hasDebuggerStatement){eval('debugger');}} +function Sys$_Debug$trace(text){var e=Function._validateParams(arguments,[{name:"text"}]);if(e)throw e;this._appendConsole(text);this._appendTrace(text);} +function Sys$_Debug$traceDump(object,name){var e=Function._validateParams(arguments,[{name:"object",mayBeNull:true},{name:"name",type:String,mayBeNull:true,optional:true}]);if(e)throw e;var text=this._traceDump(object,name,true);} +function Sys$_Debug$_traceDump(object,name,recursive,indentationPadding,loopArray){name=name?name:'traceDump';indentationPadding=indentationPadding?indentationPadding:'';if(object===null){this.trace(indentationPadding+name+': null');return;} +switch(typeof(object)){case'undefined':this.trace(indentationPadding+name+': Undefined');break;case'number':case'string':case'boolean':this.trace(indentationPadding+name+': '+object);break;default:if(Date.isInstanceOfType(object)||RegExp.isInstanceOfType(object)){this.trace(indentationPadding+name+': '+object.toString());break;} +if(!loopArray){loopArray=[];} +else if(Array.contains(loopArray,object)){this.trace(indentationPadding+name+': ...');return;} +Array.add(loopArray,object);if((object==window)||(object===document)||(window.HTMLElement&&(object instanceof HTMLElement))||(typeof(object.nodeName)==='string')){var tag=object.tagName?object.tagName:'DomElement';if(object.id){tag+=' - '+object.id;} +this.trace(indentationPadding+name+' {'+tag+'}');} +else{var typeName=Object.getTypeName(object);this.trace(indentationPadding+name+(typeof(typeName)==='string'?' {'+typeName+'}':''));if((indentationPadding==='')||recursive){indentationPadding+=" ";var i,length,properties,p,v;if(Array.isInstanceOfType(object)){length=object.length;for(i=0;i=0;i--){var part=parts[i].trim();parsed=values[part];if(typeof(parsed)!=='number')throw Error.argument('value',String.format(Sys.Res.enumInvalidValue,value.split(',')[i].trim(),this.__typeName));v|=parsed;} +return v;}} +function Sys$Enum$toString(value){var e=Function._validateParams(arguments,[{name:"value",mayBeNull:true,optional:true}]);if(e)throw e;if((typeof(value)==='undefined')||(value===null))return this.__string;if((typeof(value)!='number')||((value%1)!==0))throw Error.argumentType('value',Object.getType(value),this);var values=this.prototype;var i;if(!this.__flags||(value===0)){for(i in values){if(values[i]===value){return i;}}} +else{var sorted=this.__sortedValues;if(!sorted){sorted=[];for(i in values){sorted[sorted.length]={key:i,value:values[i]};} +sorted.sort(function(a,b){return a.value-b.value;});this.__sortedValues=sorted;} +var parts=[];var v=value;for(i=sorted.length-1;i>=0;i--){var kvp=sorted[i];var vali=kvp.value;if(vali===0)continue;if((vali&value)===vali){parts[parts.length]=kvp.key;v-=vali;if(v===0)break;}} +if(parts.length&&v===0)return parts.reverse().join(', ');} +throw Error.argumentOutOfRange('value',value,String.format(Sys.Res.enumInvalidValue,value,this.__typeName));} +Type.prototype.registerEnum=function Type$registerEnum(name,flags){var e=Function._validateParams(arguments,[{name:"name",type:String},{name:"flags",type:Boolean,optional:true}]);if(e)throw e;if(!Type.__fullyQualifiedIdentifierRegExp.test(name))throw Error.argument('name',Sys.Res.notATypeName);var parsedName;try{parsedName=eval(name);} +catch(e){throw Error.argument('name',Sys.Res.argumentTypeName);} +if(parsedName!==this)throw Error.argument('name',Sys.Res.badTypeName);if(window.__registeredTypes[name])throw Error.invalidOperation(String.format(Sys.Res.typeRegisteredTwice,name));for(var i in this.prototype){var val=this.prototype[i];if(!Type.__identifierRegExp.test(i))throw Error.invalidOperation(String.format(Sys.Res.enumInvalidValueName,i));if(typeof(val)!=='number'||(val%1)!==0)throw Error.invalidOperation(Sys.Res.enumValueNotInteger);if(typeof(this[i])!=='undefined')throw Error.invalidOperation(String.format(Sys.Res.enumReservedName,i));} +for(var i in this.prototype){this[i]=this.prototype[i];} +this.__typeName=name;this.parse=Sys$Enum$parse;this.__string=this.toString();this.toString=Sys$Enum$toString;this.__flags=flags;this.__enum=true;window.__registeredTypes[name]=true;} +Type.isEnum=function Type$isEnum(type){var e=Function._validateParams(arguments,[{name:"type",mayBeNull:true}]);if(e)throw e;if((typeof(type)==='undefined')||(type===null))return false;return!!type.__enum;} +Type.isFlags=function Type$isFlags(type){var e=Function._validateParams(arguments,[{name:"type",mayBeNull:true}]);if(e)throw e;if((typeof(type)==='undefined')||(type===null))return false;return!!type.__flags;} +Sys.EventHandlerList=function Sys$EventHandlerList(){if(arguments.length!==0)throw Error.parameterCount();this._list={};} +function Sys$EventHandlerList$addHandler(id,handler){var e=Function._validateParams(arguments,[{name:"id",type:String},{name:"handler",type:Function}]);if(e)throw e;Array.add(this._getEvent(id,true),handler);} +function Sys$EventHandlerList$removeHandler(id,handler){var e=Function._validateParams(arguments,[{name:"id",type:String},{name:"handler",type:Function}]);if(e)throw e;var evt=this._getEvent(id);if(!evt)return;Array.remove(evt,handler);} +function Sys$EventHandlerList$getHandler(id){var e=Function._validateParams(arguments,[{name:"id",type:String}]);if(e)throw e;var evt=this._getEvent(id);if(!evt||(evt.length===0))return null;evt=Array.clone(evt);if(!evt._handler){evt._handler=function(source,args){for(var i=0,l=evt.length;i=0;i--){$removeHandler(element,name,handlers[i].handler);}} +element._events=null;}} +var $removeHandler=Sys.UI.DomEvent.removeHandler=function Sys$UI$DomEvent$removeHandler(element,eventName,handler){var e=Function._validateParams(arguments,[{name:"element",domElement:true},{name:"eventName",type:String},{name:"handler",type:Function}]);if(e)throw e;var browserHandler=null;if((typeof(element._events)!=='object')||(element._events==null))throw Error.invalidOperation(Sys.Res.eventHandlerInvalid);var cache=element._events[eventName];if(!(cache instanceof Array))throw Error.invalidOperation(Sys.Res.eventHandlerInvalid);var browserHandler=null;for(var i=0,l=cache.length;i0){var nextScript=Array.dequeue(this._scriptsToLoad);var scriptElement=this._createScriptElement(nextScript);if(scriptElement.text&&Sys.Browser.agent===Sys.Browser.Safari){scriptElement.innerHTML=scriptElement.text;delete scriptElement.text;} +if(typeof(nextScript.src)==="string"){this._currentTask=new Sys._ScriptLoaderTask(scriptElement,this._scriptLoadedDelegate);this._currentTask.execute();} +else{document.getElementsByTagName('HEAD')[0].appendChild(scriptElement);Sys._ScriptLoader._clearScript(scriptElement);this._loadScriptsInternal();}} +else{var callback=this._allScriptsLoadedCallback;this._stopLoading();if(callback){callback(this);}}} +function Sys$_ScriptLoader$_raiseError(multipleCallbacks){var callback=this._scriptLoadFailedCallback;var scriptElement=this._currentTask.get_scriptElement();this._stopLoading();if(callback){callback(this,scriptElement,multipleCallbacks);} +else{throw Sys._ScriptLoader._errorScriptLoadFailed(scriptElement.src,multipleCallbacks);}} +function Sys$_ScriptLoader$_scriptLoadedHandler(scriptElement,loaded){if(loaded&&this._currentTask._notified){if(this._currentTask._notified>1){this._raiseError(true);} +else{Array.add(Sys._ScriptLoader._getLoadedScripts(),scriptElement.src);this._currentTask.dispose();this._currentTask=null;this._loadScriptsInternal();}} +else{this._raiseError(false);}} +function Sys$_ScriptLoader$_scriptLoadTimeoutHandler(){var callback=this._scriptLoadTimeoutCallback;this._stopLoading();if(callback){callback(this);}} +function Sys$_ScriptLoader$_stopLoading(){if(this._timeoutCookie){window.clearTimeout(this._timeoutCookie);this._timeoutCookie=null;} +if(this._currentTask){this._currentTask.dispose();this._currentTask=null;} +this._scriptsToLoad=null;this._loading=null;this._allScriptsLoadedCallback=null;this._scriptLoadFailedCallback=null;this._scriptLoadTimeoutCallback=null;} +Sys._ScriptLoader.prototype={dispose:Sys$_ScriptLoader$dispose,loadScripts:Sys$_ScriptLoader$loadScripts,notifyScriptLoaded:Sys$_ScriptLoader$notifyScriptLoaded,queueCustomScriptTag:Sys$_ScriptLoader$queueCustomScriptTag,queueScriptBlock:Sys$_ScriptLoader$queueScriptBlock,queueScriptReference:Sys$_ScriptLoader$queueScriptReference,_createScriptElement:Sys$_ScriptLoader$_createScriptElement,_loadScriptsInternal:Sys$_ScriptLoader$_loadScriptsInternal,_raiseError:Sys$_ScriptLoader$_raiseError,_scriptLoadedHandler:Sys$_ScriptLoader$_scriptLoadedHandler,_scriptLoadTimeoutHandler:Sys$_ScriptLoader$_scriptLoadTimeoutHandler,_stopLoading:Sys$_ScriptLoader$_stopLoading} +Sys._ScriptLoader.registerClass('Sys._ScriptLoader',null,Sys.IDisposable);Sys._ScriptLoader.getInstance=function Sys$_ScriptLoader$getInstance(){var sl=Sys._ScriptLoader._activeInstance;if(!sl){sl=Sys._ScriptLoader._activeInstance=new Sys._ScriptLoader();} +return sl;} +Sys._ScriptLoader.isScriptLoaded=function Sys$_ScriptLoader$isScriptLoaded(scriptSrc){var dummyScript=document.createElement('script');dummyScript.src=scriptSrc;return Array.contains(Sys._ScriptLoader._getLoadedScripts(),dummyScript.src);} +Sys._ScriptLoader.readLoadedScripts=function Sys$_ScriptLoader$readLoadedScripts(){if(!Sys._ScriptLoader._referencedScripts){var referencedScripts=Sys._ScriptLoader._referencedScripts=[];var existingScripts=document.getElementsByTagName('SCRIPT');for(i=existingScripts.length-1;i>=0;i--){var scriptNode=existingScripts[i];var scriptSrc=scriptNode.src;if(scriptSrc.length){if(!Array.contains(referencedScripts,scriptSrc)){Array.add(referencedScripts,scriptSrc);}}}}} +Sys._ScriptLoader._clearScript=function Sys$_ScriptLoader$_clearScript(scriptElement){if(!Sys.Debug.isDebug){scriptElement.parentNode.removeChild(scriptElement);}} +Sys._ScriptLoader._errorScriptLoadFailed=function Sys$_ScriptLoader$_errorScriptLoadFailed(scriptUrl,multipleCallbacks){var errorMessage;if(multipleCallbacks){errorMessage=Sys.Res.scriptLoadMultipleCallbacks;} +else{errorMessage=Sys.Res.scriptLoadFailedDebug;} +var displayMessage="Sys.ScriptLoadFailedException: "+String.format(errorMessage,scriptUrl);var e=Error.create(displayMessage,{name:'Sys.ScriptLoadFailedException','scriptUrl':scriptUrl});e.popStackFrame();return e;} +Sys._ScriptLoader._getLoadedScripts=function Sys$_ScriptLoader$_getLoadedScripts(){if(!Sys._ScriptLoader._referencedScripts){Sys._ScriptLoader._referencedScripts=[];Sys._ScriptLoader.readLoadedScripts();} +return Sys._ScriptLoader._referencedScripts;} +Sys._ScriptLoaderTask=function Sys$_ScriptLoaderTask(scriptElement,completedCallback){var e=Function._validateParams(arguments,[{name:"scriptElement",domElement:true},{name:"completedCallback",type:Function}]);if(e)throw e;this._scriptElement=scriptElement;this._completedCallback=completedCallback;this._notified=0;} +function Sys$_ScriptLoaderTask$get_scriptElement(){if(arguments.length!==0)throw Error.parameterCount();return this._scriptElement;} +function Sys$_ScriptLoaderTask$dispose(){if(this._disposed){return;} +this._disposed=true;this._removeScriptElementHandlers();Sys._ScriptLoader._clearScript(this._scriptElement);this._scriptElement=null;} +function Sys$_ScriptLoaderTask$execute(){if(arguments.length!==0)throw Error.parameterCount();this._addScriptElementHandlers();document.getElementsByTagName('HEAD')[0].appendChild(this._scriptElement);} +function Sys$_ScriptLoaderTask$_addScriptElementHandlers(){this._scriptLoadDelegate=Function.createDelegate(this,this._scriptLoadHandler);if(Sys.Browser.agent!==Sys.Browser.InternetExplorer){this._scriptElement.readyState='loaded';$addHandler(this._scriptElement,'load',this._scriptLoadDelegate);} +else{$addHandler(this._scriptElement,'readystatechange',this._scriptLoadDelegate);} +this._scriptErrorDelegate=Function.createDelegate(this,this._scriptErrorHandler);$addHandler(this._scriptElement,'error',this._scriptErrorDelegate);} +function Sys$_ScriptLoaderTask$_removeScriptElementHandlers(){if(this._scriptLoadDelegate){var scriptElement=this.get_scriptElement();if(Sys.Browser.agent!==Sys.Browser.InternetExplorer){$removeHandler(scriptElement,'load',this._scriptLoadDelegate);} +else{$removeHandler(scriptElement,'readystatechange',this._scriptLoadDelegate);} +$removeHandler(scriptElement,'error',this._scriptErrorDelegate);this._scriptErrorDelegate=null;this._scriptLoadDelegate=null;}} +function Sys$_ScriptLoaderTask$_scriptErrorHandler(){if(this._disposed){return;} +this._completedCallback(this.get_scriptElement(),false);} +function Sys$_ScriptLoaderTask$_scriptLoadHandler(){if(this._disposed){return;} +var scriptElement=this.get_scriptElement();if((scriptElement.readyState!=='loaded')&&(scriptElement.readyState!=='complete')){return;} +var _this=this;window.setTimeout(function(){_this._completedCallback(scriptElement,true);},0);} +Sys._ScriptLoaderTask.prototype={get_scriptElement:Sys$_ScriptLoaderTask$get_scriptElement,dispose:Sys$_ScriptLoaderTask$dispose,execute:Sys$_ScriptLoaderTask$execute,_addScriptElementHandlers:Sys$_ScriptLoaderTask$_addScriptElementHandlers,_removeScriptElementHandlers:Sys$_ScriptLoaderTask$_removeScriptElementHandlers,_scriptErrorHandler:Sys$_ScriptLoaderTask$_scriptErrorHandler,_scriptLoadHandler:Sys$_ScriptLoaderTask$_scriptLoadHandler} +Sys._ScriptLoaderTask.registerClass("Sys._ScriptLoaderTask",null,Sys.IDisposable);Sys.ApplicationLoadEventArgs=function Sys$ApplicationLoadEventArgs(components,isPartialLoad){var e=Function._validateParams(arguments,[{name:"components",type:Array,elementType:Sys.Component},{name:"isPartialLoad",type:Boolean}]);if(e)throw e;Sys.ApplicationLoadEventArgs.initializeBase(this);this._components=components;this._isPartialLoad=isPartialLoad;} +function Sys$ApplicationLoadEventArgs$get_components(){if(arguments.length!==0)throw Error.parameterCount();return this._components;} +function Sys$ApplicationLoadEventArgs$get_isPartialLoad(){if(arguments.length!==0)throw Error.parameterCount();return this._isPartialLoad;} +Sys.ApplicationLoadEventArgs.prototype={get_components:Sys$ApplicationLoadEventArgs$get_components,get_isPartialLoad:Sys$ApplicationLoadEventArgs$get_isPartialLoad} +Sys.ApplicationLoadEventArgs.registerClass('Sys.ApplicationLoadEventArgs',Sys.EventArgs);Sys._Application=function Sys$_Application(){Sys._Application.initializeBase(this);this._disposableObjects=[];this._components={};this._createdComponents=[];this._secondPassComponents=[];this._unloadHandlerDelegate=Function.createDelegate(this,this._unloadHandler);this._loadHandlerDelegate=Function.createDelegate(this,this._loadHandler);Sys.UI.DomEvent.addHandler(window,"unload",this._unloadHandlerDelegate);Sys.UI.DomEvent.addHandler(window,"load",this._loadHandlerDelegate);} +function Sys$_Application$get_isCreatingComponents(){if(arguments.length!==0)throw Error.parameterCount();return this._creatingComponents;} +function Sys$_Application$add_load(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this.get_events().addHandler("load",handler);} +function Sys$_Application$remove_load(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this.get_events().removeHandler("load",handler);} +function Sys$_Application$add_init(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;if(this._initialized){handler(this,Sys.EventArgs.Empty);} +else{this.get_events().addHandler("init",handler);}} +function Sys$_Application$remove_init(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this.get_events().removeHandler("init",handler);} +function Sys$_Application$add_unload(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this.get_events().addHandler("unload",handler);} +function Sys$_Application$remove_unload(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this.get_events().removeHandler("unload",handler);} +function Sys$_Application$addComponent(component){var e=Function._validateParams(arguments,[{name:"component",type:Sys.Component}]);if(e)throw e;var id=component.get_id();if(!id)throw Error.invalidOperation(Sys.Res.cantAddWithoutId);if(typeof(this._components[id])!=='undefined')throw Error.invalidOperation(String.format(Sys.Res.appDuplicateComponent,id));this._components[id]=component;} +function Sys$_Application$beginCreateComponents(){this._creatingComponents=true;} +function Sys$_Application$dispose(){if(!this._disposing){this._disposing=true;if(window.pageUnload){window.pageUnload(this,Sys.EventArgs.Empty);} +var unloadHandler=this.get_events().getHandler("unload");if(unloadHandler){unloadHandler(this,Sys.EventArgs.Empty);} +var disposableObjects=Array.clone(this._disposableObjects);for(var i=0,l=disposableObjects.length;i0){this._timer=window.setTimeout(Function.createDelegate(this,this._onTimeout),timeout);} +this._xmlHttpRequest.send(body);this._started=true;} +function Sys$Net$XMLHttpExecutor$getResponseHeader(header){var e=Function._validateParams(arguments,[{name:"header",type:String}]);if(e)throw e;if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'getResponseHeader'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'getResponseHeader'));} +var result;try{result=this._xmlHttpRequest.getResponseHeader(header);}catch(e){} +if(!result)result="";return result;} +function Sys$Net$XMLHttpExecutor$getAllResponseHeaders(){if(arguments.length!==0)throw Error.parameterCount();if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'getAllResponseHeaders'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'getAllResponseHeaders'));} +return this._xmlHttpRequest.getAllResponseHeaders();} +function Sys$Net$XMLHttpExecutor$get_responseData(){if(arguments.length!==0)throw Error.parameterCount();if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'get_responseData'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'get_responseData'));} +return this._xmlHttpRequest.responseText;} +function Sys$Net$XMLHttpExecutor$get_statusCode(){if(arguments.length!==0)throw Error.parameterCount();if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'get_statusCode'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'get_statusCode'));} +return this._xmlHttpRequest.status;} +function Sys$Net$XMLHttpExecutor$get_statusText(){if(arguments.length!==0)throw Error.parameterCount();if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'get_statusText'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'get_statusText'));} +return this._xmlHttpRequest.statusText;} +function Sys$Net$XMLHttpExecutor$get_xml(){if(arguments.length!==0)throw Error.parameterCount();if(!this._responseAvailable){throw Error.invalidOperation(String.format(Sys.Res.cannotCallBeforeResponse,'get_xml'));} +if(!this._xmlHttpRequest){throw Error.invalidOperation(String.format(Sys.Res.cannotCallOutsideHandler,'get_xml'));} +var xml=this._xmlHttpRequest.responseXML;if(!xml||!xml.documentElement){xml=new XMLDOM(this._xmlHttpRequest.responseText);if(!xml||!xml.documentElement) +return null;} +else if(navigator.userAgent.indexOf('MSIE')!==-1){xml.setProperty('SelectionLanguage','XPath');} +if(xml.documentElement.namespaceURI==="http://www.mozilla.org/newlayout/xml/parsererror.xml"&&xml.documentElement.tagName==="parsererror"){return null;} +if(xml.documentElement.firstChild&&xml.documentElement.firstChild.tagName==="parsererror"){return null;} +return xml;} +function Sys$Net$XMLHttpExecutor$abort(){if(arguments.length!==0)throw Error.parameterCount();if(!this._started){throw Error.invalidOperation(Sys.Res.cannotAbortBeforeStart);} +if(this._aborted||this._responseAvailable||this._timedOut) +return;this._aborted=true;this._clearTimer();if(this._xmlHttpRequest&&!this._responseAvailable){this._xmlHttpRequest.onreadystatechange=Function.emptyMethod;this._xmlHttpRequest.abort();this._xmlHttpRequest=null;var handler=this._webRequest._get_eventHandlerList().getHandler("completed");if(handler){handler(this,Sys.EventArgs.Empty);}}} +Sys.Net.XMLHttpExecutor.prototype={get_timedOut:Sys$Net$XMLHttpExecutor$get_timedOut,get_started:Sys$Net$XMLHttpExecutor$get_started,get_responseAvailable:Sys$Net$XMLHttpExecutor$get_responseAvailable,get_aborted:Sys$Net$XMLHttpExecutor$get_aborted,executeRequest:Sys$Net$XMLHttpExecutor$executeRequest,getResponseHeader:Sys$Net$XMLHttpExecutor$getResponseHeader,getAllResponseHeaders:Sys$Net$XMLHttpExecutor$getAllResponseHeaders,get_responseData:Sys$Net$XMLHttpExecutor$get_responseData,get_statusCode:Sys$Net$XMLHttpExecutor$get_statusCode,get_statusText:Sys$Net$XMLHttpExecutor$get_statusText,get_xml:Sys$Net$XMLHttpExecutor$get_xml,abort:Sys$Net$XMLHttpExecutor$abort} +Sys.Net.XMLHttpExecutor.registerClass('Sys.Net.XMLHttpExecutor',Sys.Net.WebRequestExecutor);Sys.Net._WebRequestManager=function Sys$Net$_WebRequestManager(){this._this=this;this._defaultTimeout=0;this._defaultExecutorType="Sys.Net.XMLHttpExecutor";} +function Sys$Net$_WebRequestManager$add_invokingRequest(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().addHandler("invokingRequest",handler);} +function Sys$Net$_WebRequestManager$remove_invokingRequest(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().removeHandler("invokingRequest",handler);} +function Sys$Net$_WebRequestManager$add_completedRequest(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().addHandler("completedRequest",handler);} +function Sys$Net$_WebRequestManager$remove_completedRequest(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().removeHandler("completedRequest",handler);} +function Sys$Net$_WebRequestManager$_get_eventHandlerList(){if(!this._events){this._events=new Sys.EventHandlerList();} +return this._events;} +function Sys$Net$_WebRequestManager$get_defaultTimeout(){if(arguments.length!==0)throw Error.parameterCount();return this._defaultTimeout;} +function Sys$Net$_WebRequestManager$set_defaultTimeout(value){var e=Function._validateParams(arguments,[{name:"value",type:Number}]);if(e)throw e;if(value<0){throw Error.argumentOutOfRange("value",value,Sys.Res.invalidTimeout);} +this._defaultTimeout=value;} +function Sys$Net$_WebRequestManager$get_defaultExecutorType(){if(arguments.length!==0)throw Error.parameterCount();return this._defaultExecutorType;} +function Sys$Net$_WebRequestManager$set_defaultExecutorType(value){var e=Function._validateParams(arguments,[{name:"value",type:String}]);if(e)throw e;this._defaultExecutorType=value;} +function Sys$Net$_WebRequestManager$executeRequest(webRequest){var e=Function._validateParams(arguments,[{name:"webRequest",type:Sys.Net.WebRequest}]);if(e)throw e;var executor=webRequest.get_executor();if(!executor){var failed=false;try{var executorType=eval(this._defaultExecutorType);executor=new executorType();}catch(e){failed=true;} +if(failed||!Sys.Net.WebRequestExecutor.isInstanceOfType(executor)||!executor){throw Error.argument("defaultExecutorType",String.format(Sys.Res.invalidExecutorType,this._defaultExecutorType));} +webRequest.set_executor(executor);} +if(executor.get_aborted()){return;} +var evArgs=new Sys.Net.NetworkRequestEventArgs(webRequest);var handler=this._get_eventHandlerList().getHandler("invokingRequest");if(handler){handler(this,evArgs);} +if(!evArgs.get_cancel()){executor.executeRequest();}} +Sys.Net._WebRequestManager.prototype={add_invokingRequest:Sys$Net$_WebRequestManager$add_invokingRequest,remove_invokingRequest:Sys$Net$_WebRequestManager$remove_invokingRequest,add_completedRequest:Sys$Net$_WebRequestManager$add_completedRequest,remove_completedRequest:Sys$Net$_WebRequestManager$remove_completedRequest,_get_eventHandlerList:Sys$Net$_WebRequestManager$_get_eventHandlerList,get_defaultTimeout:Sys$Net$_WebRequestManager$get_defaultTimeout,set_defaultTimeout:Sys$Net$_WebRequestManager$set_defaultTimeout,get_defaultExecutorType:Sys$Net$_WebRequestManager$get_defaultExecutorType,set_defaultExecutorType:Sys$Net$_WebRequestManager$set_defaultExecutorType,executeRequest:Sys$Net$_WebRequestManager$executeRequest} +Sys.Net._WebRequestManager.registerClass('Sys.Net._WebRequestManager');Sys.Net.WebRequestManager=new Sys.Net._WebRequestManager();Sys.Net.NetworkRequestEventArgs=function Sys$Net$NetworkRequestEventArgs(webRequest){var e=Function._validateParams(arguments,[{name:"webRequest",type:Sys.Net.WebRequest}]);if(e)throw e;Sys.Net.NetworkRequestEventArgs.initializeBase(this);this._webRequest=webRequest;} +function Sys$Net$NetworkRequestEventArgs$get_webRequest(){if(arguments.length!==0)throw Error.parameterCount();return this._webRequest;} +Sys.Net.NetworkRequestEventArgs.prototype={get_webRequest:Sys$Net$NetworkRequestEventArgs$get_webRequest} +Sys.Net.NetworkRequestEventArgs.registerClass('Sys.Net.NetworkRequestEventArgs',Sys.CancelEventArgs);Sys.Net.WebRequest=function Sys$Net$WebRequest(){if(arguments.length!==0)throw Error.parameterCount();this._url="";this._headers={};this._body=null;this._userContext=null;this._httpVerb=null;this._executor=null;this._invokeCalled=false;this._timeout=0;} +function Sys$Net$WebRequest$add_completed(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().addHandler("completed",handler);} +function Sys$Net$WebRequest$remove_completed(handler){var e=Function._validateParams(arguments,[{name:"handler",type:Function}]);if(e)throw e;this._get_eventHandlerList().removeHandler("completed",handler);} +function Sys$Net$WebRequest$completed(eventArgs){var e=Function._validateParams(arguments,[{name:"eventArgs",type:Sys.EventArgs}]);if(e)throw e;var handler=Sys.Net.WebRequestManager._get_eventHandlerList().getHandler("completedRequest");if(handler){handler(this._executor,eventArgs);} +handler=this._get_eventHandlerList().getHandler("completed");if(handler){handler(this._executor,eventArgs);}} +function Sys$Net$WebRequest$_get_eventHandlerList(){if(!this._events){this._events=new Sys.EventHandlerList();} +return this._events;} +function Sys$Net$WebRequest$get_url(){if(arguments.length!==0)throw Error.parameterCount();return this._url;} +function Sys$Net$WebRequest$set_url(value){var e=Function._validateParams(arguments,[{name:"value",type:String}]);if(e)throw e;this._url=value;} +function Sys$Net$WebRequest$get_headers(){if(arguments.length!==0)throw Error.parameterCount();return this._headers;} +function Sys$Net$WebRequest$get_httpVerb(){if(arguments.length!==0)throw Error.parameterCount();if(this._httpVerb===null){if(this._body===null){return"GET";} +return"POST";} +return this._httpVerb;} +function Sys$Net$WebRequest$set_httpVerb(value){var e=Function._validateParams(arguments,[{name:"value",type:String}]);if(e)throw e;if(value.length===0){throw Error.argument('value',Sys.Res.invalidHttpVerb);} +this._httpVerb=value;} +function Sys$Net$WebRequest$get_body(){if(arguments.length!==0)throw Error.parameterCount();return this._body;} +function Sys$Net$WebRequest$set_body(value){var e=Function._validateParams(arguments,[{name:"value",mayBeNull:true}]);if(e)throw e;this._body=value;} +function Sys$Net$WebRequest$get_userContext(){if(arguments.length!==0)throw Error.parameterCount();return this._userContext;} +function Sys$Net$WebRequest$set_userContext(value){var e=Function._validateParams(arguments,[{name:"value",mayBeNull:true}]);if(e)throw e;this._userContext=value;} +function Sys$Net$WebRequest$get_executor(){if(arguments.length!==0)throw Error.parameterCount();return this._executor;} +function Sys$Net$WebRequest$set_executor(value){var e=Function._validateParams(arguments,[{name:"value",type:Sys.Net.WebRequestExecutor}]);if(e)throw e;if(this._executor!==null&&this._executor.get_started()){throw Error.invalidOperation(Sys.Res.setExecutorAfterActive);} +this._executor=value;this._executor._set_webRequest(this);} +function Sys$Net$WebRequest$get_timeout(){if(arguments.length!==0)throw Error.parameterCount();if(this._timeout===0){return Sys.Net.WebRequestManager.get_defaultTimeout();} +return this._timeout;} +function Sys$Net$WebRequest$set_timeout(value){var e=Function._validateParams(arguments,[{name:"value",type:Number}]);if(e)throw e;if(value<0){throw Error.argumentOutOfRange("value",value,Sys.Res.invalidTimeout);} +this._timeout=value;} +function Sys$Net$WebRequest$getResolvedUrl(){if(arguments.length!==0)throw Error.parameterCount();return Sys.Net.WebRequest._resolveUrl(this._url);} +function Sys$Net$WebRequest$invoke(){if(arguments.length!==0)throw Error.parameterCount();if(this._invokeCalled){throw Error.invalidOperation(Sys.Res.invokeCalledTwice);} +Sys.Net.WebRequestManager.executeRequest(this);this._invokeCalled=true;} +Sys.Net.WebRequest.prototype={add_completed:Sys$Net$WebRequest$add_completed,remove_completed:Sys$Net$WebRequest$remove_completed,completed:Sys$Net$WebRequest$completed,_get_eventHandlerList:Sys$Net$WebRequest$_get_eventHandlerList,get_url:Sys$Net$WebRequest$get_url,set_url:Sys$Net$WebRequest$set_url,get_headers:Sys$Net$WebRequest$get_headers,get_httpVerb:Sys$Net$WebRequest$get_httpVerb,set_httpVerb:Sys$Net$WebRequest$set_httpVerb,get_body:Sys$Net$WebRequest$get_body,set_body:Sys$Net$WebRequest$set_body,get_userContext:Sys$Net$WebRequest$get_userContext,set_userContext:Sys$Net$WebRequest$set_userContext,get_executor:Sys$Net$WebRequest$get_executor,set_executor:Sys$Net$WebRequest$set_executor,get_timeout:Sys$Net$WebRequest$get_timeout,set_timeout:Sys$Net$WebRequest$set_timeout,getResolvedUrl:Sys$Net$WebRequest$getResolvedUrl,invoke:Sys$Net$WebRequest$invoke} +Sys.Net.WebRequest._resolveUrl=function Sys$Net$WebRequest$_resolveUrl(url,baseUrl){if(url&&url.indexOf('://')!==-1){return url;} +if(!baseUrl||baseUrl.length===0){var baseElement=document.getElementsByTagName('base')[0];if(baseElement&&baseElement.href&&baseElement.href.length>0){baseUrl=baseElement.href;} +else{baseUrl=document.URL;}} +var qsStart=baseUrl.indexOf('?');if(qsStart!==-1){baseUrl=baseUrl.substr(0,qsStart);} +baseUrl=baseUrl.substr(0,baseUrl.lastIndexOf('/')+1);if(!url||url.length===0){return baseUrl;} +if(url.charAt(0)==='/'){var slashslash=baseUrl.indexOf('://');if(slashslash===-1){throw Error.argument("baseUrl",Sys.Res.badBaseUrl1);} +var nextSlash=baseUrl.indexOf('/',slashslash+3);if(nextSlash===-1){throw Error.argument("baseUrl",Sys.Res.badBaseUrl2);} +return baseUrl.substr(0,nextSlash)+url;} +else{var lastSlash=baseUrl.lastIndexOf('/');if(lastSlash===-1){throw Error.argument("baseUrl",Sys.Res.badBaseUrl3);} +return baseUrl.substr(0,lastSlash+1)+url;}} +Sys.Net.WebRequest._createQueryString=function Sys$Net$WebRequest$_createQueryString(queryString,encodeMethod){if(!encodeMethod) +encodeMethod=encodeURIComponent;var sb=new Sys.StringBuilder();var i=0;for(var arg in queryString){var obj=queryString[arg];if(typeof(obj)==="function")continue;var val=Sys.Serialization.JavaScriptSerializer.serialize(obj);if(i!==0){sb.append('&');} +sb.append(arg);sb.append('=');sb.append(encodeMethod(val));i++;} +return sb.toString();} +Sys.Net.WebRequest._createUrl=function Sys$Net$WebRequest$_createUrl(url,queryString){if(!queryString){return url;} +var qs=Sys.Net.WebRequest._createQueryString(queryString);if(qs.length>0){var sep='?';if(url&&url.indexOf('?')!==-1) +sep='&';return url+sep+qs;}else{return url;}} +Sys.Net.WebRequest.registerClass('Sys.Net.WebRequest');Sys.Net.WebServiceProxy=function Sys$Net$WebServiceProxy(){} +function Sys$Net$WebServiceProxy$set_timeout(value){this._timeout=value;} +function Sys$Net$WebServiceProxy$get_timeout(){if(arguments.length!==0)throw Error.parameterCount();return this._timeout;} +function Sys$Net$WebServiceProxy$set_defaultUserContext(value){this._userContext=value;} +function Sys$Net$WebServiceProxy$get_defaultUserContext(){if(arguments.length!==0)throw Error.parameterCount();return this._userContext;} +function Sys$Net$WebServiceProxy$set_defaultSucceededCallback(value){this._succeeded=value;} +function Sys$Net$WebServiceProxy$get_defaultSucceededCallback(){if(arguments.length!==0)throw Error.parameterCount();return this._succeeded;} +function Sys$Net$WebServiceProxy$set_defaultFailedCallback(value){this._failed=value;} +function Sys$Net$WebServiceProxy$get_defaultFailedCallback(){if(arguments.length!==0)throw Error.parameterCount();return this._failed;} +function Sys$Net$WebServiceProxy$set_path(value){this._path=value;} +function Sys$Net$WebServiceProxy$get_path(){if(arguments.length!==0)throw Error.parameterCount();return this._path;} +function Sys$Net$WebServiceProxy$_invoke(servicePath,methodName,useGet,params,onSuccess,onFailure,userContext){var e=Function._validateParams(arguments,[{name:"servicePath",type:String},{name:"methodName",type:String},{name:"useGet",type:Boolean},{name:"params"},{name:"onSuccess",type:Function,mayBeNull:true,optional:true},{name:"onFailure",type:Function,mayBeNull:true,optional:true},{name:"userContext",mayBeNull:true,optional:true}]);if(e)throw e;if(onSuccess===null||typeof onSuccess==='undefined')onSuccess=this.get_defaultSucceededCallback();if(onFailure===null||typeof onFailure==='undefined')onFailure=this.get_defaultFailedCallback();if(userContext===null||typeof userContext==='undefined')userContext=this.get_defaultUserContext();return Sys.Net.WebServiceProxy.invoke(servicePath,methodName,useGet,params,onSuccess,onFailure,userContext,this.get_timeout());} +Sys.Net.WebServiceProxy.prototype={set_timeout:Sys$Net$WebServiceProxy$set_timeout,get_timeout:Sys$Net$WebServiceProxy$get_timeout,set_defaultUserContext:Sys$Net$WebServiceProxy$set_defaultUserContext,get_defaultUserContext:Sys$Net$WebServiceProxy$get_defaultUserContext,set_defaultSucceededCallback:Sys$Net$WebServiceProxy$set_defaultSucceededCallback,get_defaultSucceededCallback:Sys$Net$WebServiceProxy$get_defaultSucceededCallback,set_defaultFailedCallback:Sys$Net$WebServiceProxy$set_defaultFailedCallback,get_defaultFailedCallback:Sys$Net$WebServiceProxy$get_defaultFailedCallback,set_path:Sys$Net$WebServiceProxy$set_path,get_path:Sys$Net$WebServiceProxy$get_path,_invoke:Sys$Net$WebServiceProxy$_invoke} +Sys.Net.WebServiceProxy.registerClass('Sys.Net.WebServiceProxy');Sys.Net.WebServiceProxy.invoke=function Sys$Net$WebServiceProxy$invoke(servicePath,methodName,useGet,params,onSuccess,onFailure,userContext,timeout){var e=Function._validateParams(arguments,[{name:"servicePath",type:String},{name:"methodName",type:String},{name:"useGet",type:Boolean,optional:true},{name:"params",mayBeNull:true,optional:true},{name:"onSuccess",type:Function,mayBeNull:true,optional:true},{name:"onFailure",type:Function,mayBeNull:true,optional:true},{name:"userContext",mayBeNull:true,optional:true},{name:"timeout",type:Number,optional:true}]);if(e)throw e;var request=new Sys.Net.WebRequest();request.get_headers()['Content-Type']='application/json; charset=utf-8';if(!params)params={};var urlParams=params;if(!useGet||!urlParams)urlParams={};request.set_url(Sys.Net.WebRequest._createUrl(servicePath+"/"+methodName,urlParams));var body=null;if(!useGet){body=Sys.Serialization.JavaScriptSerializer.serialize(params);if(body==="{}")body="";} +request.set_body(body);request.add_completed(onComplete);if(timeout&&timeout>0)request.set_timeout(timeout);request.invoke();function onComplete(response,eventArgs){if(response.get_responseAvailable()){var statusCode=response.get_statusCode();var result=null;try{var contentType=response.getResponseHeader("Content-Type");if(contentType.startsWith("application/json")){result=response.get_object();} +else if(contentType.startsWith("text/xml")){result=response.get_xml();} +else{result=response.get_responseData();}}catch(ex){} +var error=response.getResponseHeader("jsonerror");var errorObj=(error==="true");if(errorObj){result=new Sys.Net.WebServiceError(false,result.Message,result.StackTrace,result.ExceptionType);} +if(((statusCode<200)||(statusCode>=300))||errorObj){if(onFailure){if(!result||!errorObj){result=new Sys.Net.WebServiceError(false,String.format(Sys.Res.webServiceFailedNoMsg,methodName),"","");} +result._statusCode=statusCode;onFailure(result,userContext,methodName);} +else{var error;if(result&&errorObj){error=result.get_exceptionType()+"-- "+result.get_message();} +else{error=response.get_responseData();} +alert(String.format(Sys.Res.webServiceFailed,methodName,error));}} +else if(onSuccess){onSuccess(result,userContext,methodName);}} +else{var msg;if(response.get_timedOut()){msg=String.format(Sys.Res.webServiceTimedOut,methodName);} +else{msg=String.format(Sys.Res.webServiceFailedNoMsg,methodName)} +if(onFailure){onFailure(new Sys.Net.WebServiceError(response.get_timedOut(),msg,"",""),userContext,methodName);} +else{alert(msg);}}} +return request;} +Sys.Net.WebServiceProxy._generateTypedConstructor=function Sys$Net$WebServiceProxy$_generateTypedConstructor(type){return function(properties){if(properties){for(var name in properties){this[name]=properties[name];}} +this.__type=type;}} +Sys.Net.WebServiceError=function Sys$Net$WebServiceError(timedOut,message,stackTrace,exceptionType){var e=Function._validateParams(arguments,[{name:"timedOut",type:Boolean},{name:"message",type:String,mayBeNull:true},{name:"stackTrace",type:String,mayBeNull:true},{name:"exceptionType",type:String,mayBeNull:true}]);if(e)throw e;this._timedOut=timedOut;this._message=message;this._stackTrace=stackTrace;this._exceptionType=exceptionType;this._statusCode=-1;} +function Sys$Net$WebServiceError$get_timedOut(){if(arguments.length!==0)throw Error.parameterCount();return this._timedOut;} +function Sys$Net$WebServiceError$get_statusCode(){if(arguments.length!==0)throw Error.parameterCount();return this._statusCode;} +function Sys$Net$WebServiceError$get_message(){if(arguments.length!==0)throw Error.parameterCount();return this._message;} +function Sys$Net$WebServiceError$get_stackTrace(){if(arguments.length!==0)throw Error.parameterCount();return this._stackTrace;} +function Sys$Net$WebServiceError$get_exceptionType(){if(arguments.length!==0)throw Error.parameterCount();return this._exceptionType;} +Sys.Net.WebServiceError.prototype={get_timedOut:Sys$Net$WebServiceError$get_timedOut,get_statusCode:Sys$Net$WebServiceError$get_statusCode,get_message:Sys$Net$WebServiceError$get_message,get_stackTrace:Sys$Net$WebServiceError$get_stackTrace,get_exceptionType:Sys$Net$WebServiceError$get_exceptionType} +Sys.Net.WebServiceError.registerClass('Sys.Net.WebServiceError');Type.registerNamespace('Sys.Services');Sys.Services._ProfileService=function Sys$Services$_ProfileService(){Sys.Services._ProfileService.initializeBase(this);this.properties={};} +Sys.Services._ProfileService.DefaultWebServicePath='';function Sys$Services$_ProfileService$get_defaultFailedCallback(){if(arguments.length!==0)throw Error.parameterCount();return this._defaultFailedCallback;} +function Sys$Services$_ProfileService$set_defaultFailedCallback(value){var e=Function._validateParams(arguments,[{name:"value",type:Function,mayBeNull:true}]);if(e)throw e;this._defaultFailedCallback=value;} +function Sys$Services$_ProfileService$get_defaultLoadCompletedCallback(){if(arguments.length!==0)throw Error.parameterCount();return this._defaultLoadCompletedCallback;} +function Sys$Services$_ProfileService$set_defaultLoadCompletedCallback(value){var e=Function._validateParams(arguments,[{name:"value",type:Function,mayBeNull:true}]);if(e)throw e;this._defaultLoadCompletedCallback=value;} +function Sys$Services$_ProfileService$get_defaultSaveCompletedCallback(){if(arguments.length!==0)throw Error.parameterCount();return this._defaultSaveCompletedCallback;} +function Sys$Services$_ProfileService$set_defaultSaveCompletedCallback(value){var e=Function._validateParams(arguments,[{name:"value",type:Function,mayBeNull:true}]);if(e)throw e;this._defaultSaveCompletedCallback=value;} +function Sys$Services$_ProfileService$get_path(){if(arguments.length!==0)throw Error.parameterCount();return this._path;} +function Sys$Services$_ProfileService$set_path(value){var e=Function._validateParams(arguments,[{name:"value",type:String,mayBeNull:true}]);if(e)throw e;if((!value)||(!value.length)){value='';} +this._path=value;} +function Sys$Services$_ProfileService$get_timeout(){if(arguments.length!==0)throw Error.parameterCount();return this._timeout;} +function Sys$Services$_ProfileService$set_timeout(value){var e=Function._validateParams(arguments,[{name:"value",type:Number}]);if(e)throw e;this._timeout=value;} +function Sys$Services$_ProfileService$load(propertyNames,loadCompletedCallback,failedCallback,userContext){var e=Function._validateParams(arguments,[{name:"propertyNames",type:Array,mayBeNull:true,optional:true,elementType:String},{name:"loadCompletedCallback",type:Function,mayBeNull:true,optional:true},{name:"failedCallback",type:Function,mayBeNull:true,optional:true},{name:"userContext",mayBeNull:true,optional:true}]);if(e)throw e;var parameters={};var methodName;if(!propertyNames){methodName="GetAllPropertiesForCurrentUser";} +else{methodName="GetPropertiesForCurrentUser";parameters={properties:this._clonePropertyNames(propertyNames)};} +this._invoke(this._get_path(),methodName,false,parameters,Function.createDelegate(this,this._onLoadComplete),Function.createDelegate(this,this._onLoadFailed),[loadCompletedCallback,failedCallback,userContext]);} +function Sys$Services$_ProfileService$save(propertyNames,saveCompletedCallback,failedCallback,userContext){var e=Function._validateParams(arguments,[{name:"propertyNames",type:Array,mayBeNull:true,optional:true,elementType:String},{name:"saveCompletedCallback",type:Function,mayBeNull:true,optional:true},{name:"failedCallback",type:Function,mayBeNull:true,optional:true},{name:"userContext",mayBeNull:true,optional:true}]);if(e)throw e;var flattenedProperties=this._flattenProperties(propertyNames,this.properties);this._invoke(this._get_path(),"SetPropertiesForCurrentUser",false,{values:flattenedProperties},Function.createDelegate(this,this._onSaveComplete),Function.createDelegate(this,this._onSaveFailed),[saveCompletedCallback,failedCallback,userContext]);} +function Sys$Services$_ProfileService$_clonePropertyNames(arr){var nodups=[];var seen={};for(var i=0;i0){stringBuilder.append(',');} +Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object[i],stringBuilder);} +stringBuilder.append(']');} +else{if(Date.isInstanceOfType(object)){stringBuilder.append('"\\/Date(');stringBuilder.append(object.getTime());stringBuilder.append(')\\/"');break;} +var properties=[];var propertyCount=0;for(var name in object){if(name.startsWith('$')){continue;} +properties[propertyCount++]=name;} +if(sort)properties.sort();stringBuilder.append('{');var needComma=false;for(i=0;i=' '){if(curChar==='\\'||curChar==='"'){stringBuilder.append('\\');} +stringBuilder.append(curChar);} +else{switch(curChar){case'\b':stringBuilder.append('\\b');break;case'\f':stringBuilder.append('\\f');break;case'\n':stringBuilder.append('\\n');break;case'\r':stringBuilder.append('\\r');break;case'\t':stringBuilder.append('\\t');break;default:stringBuilder.append('\\u00');if(curChar.charCodeAt()<16)stringBuilder.append('0');stringBuilder.append(curChar.charCodeAt().toString(16));}}}}else{stringBuilder.append(object);} +stringBuilder.append('"');break;case'boolean':stringBuilder.append(object.toString());break;default:stringBuilder.append('null');break;}} +Sys.Serialization.JavaScriptSerializer.serialize=function Sys$Serialization$JavaScriptSerializer$serialize(object){var e=Function._validateParams(arguments,[{name:"object",mayBeNull:true}]);if(e)throw e;var stringBuilder=new Sys.StringBuilder();Sys.Serialization.JavaScriptSerializer._serializeWithBuilder(object,stringBuilder,false);return stringBuilder.toString();} +Sys.Serialization.JavaScriptSerializer.deserialize=function Sys$Serialization$JavaScriptSerializer$deserialize(data){var e=Function._validateParams(arguments,[{name:"data",type:String}]);if(e)throw e;if(data.length===0)throw Error.argument('data',Sys.Res.cannotDeserializeEmptyString);try{var exp=data.replace(new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)\\)\\\\/\\"','g'),"$1new Date($2)");return eval('('+exp+')');} +catch(e){throw Error.argument('data',Sys.Res.cannotDeserializeInvalidJson);}} +Sys.CultureInfo=function Sys$CultureInfo(name,numberFormat,dateTimeFormat){var e=Function._validateParams(arguments,[{name:"name",type:String},{name:"numberFormat",type:Object},{name:"dateTimeFormat",type:Object}]);if(e)throw e;this.name=name;this.numberFormat=numberFormat;this.dateTimeFormat=dateTimeFormat;} +function Sys$CultureInfo$_getDateTimeFormats(){if(!this._dateTimeFormats){var dtf=this.dateTimeFormat;this._dateTimeFormats=[dtf.MonthDayPattern,dtf.YearMonthPattern,dtf.ShortDatePattern,dtf.ShortTimePattern,dtf.LongDatePattern,dtf.LongTimePattern,dtf.FullDateTimePattern,dtf.RFC1123Pattern,dtf.SortableDateTimePattern,dtf.UniversalSortableDateTimePattern];} +return this._dateTimeFormats;} +function Sys$CultureInfo$_getMonthIndex(value){if(!this._upperMonths){this._upperMonths=this._toUpperArray(this.dateTimeFormat.MonthNames);} +return Array.indexOf(this._upperMonths,this._toUpper(value));} +function Sys$CultureInfo$_getAbbrMonthIndex(value){if(!this._upperAbbrMonths){this._upperAbbrMonths=this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames);} +return Array.indexOf(this._upperMonths,this._toUpper(value));} +function Sys$CultureInfo$_getDayIndex(value){if(!this._upperDays){this._upperDays=this._toUpperArray(this.dateTimeFormat.DayNames);} +return Array.indexOf(this._upperDays,this._toUpper(value));} +function Sys$CultureInfo$_getAbbrDayIndex(value){if(!this._upperAbbrDays){this._upperAbbrDays=this._toUpperArray(this.dateTimeFormat.AbbreviatedDayNames);} +return Array.indexOf(this._upperAbbrDays,this._toUpper(value));} +function Sys$CultureInfo$_toUpperArray(arr){var result=[];for(var i=0,il=arr.length;i=0){element.className=(currentClassName.substr(0,index)+' '+ +currentClassName.substring(index+className.length+1,currentClassName.length)).trim();}} +Sys.UI.DomElement.setLocation=function Sys$UI$DomElement$setLocation(element,x,y){var e=Function._validateParams(arguments,[{name:"element",domElement:true},{name:"x",type:Number,integer:true},{name:"y",type:Number,integer:true}]);if(e)throw e;var style=element.style;style.position='absolute';style.left=x+"px";style.top=y+"px";} +Sys.UI.DomElement.toggleCssClass=function Sys$UI$DomElement$toggleCssClass(element,className){var e=Function._validateParams(arguments,[{name:"element",domElement:true},{name:"className",type:String}]);if(e)throw e;if(Sys.UI.DomElement.containsCssClass(element,className)){Sys.UI.DomElement.removeCssClass(element,className);} +else{Sys.UI.DomElement.addCssClass(element,className);}} +Sys.UI.DomElement._getCurrentStyle=function Sys$UI$DomElement$_getCurrentStyle(element){var w=(element.ownerDocument?element.ownerDocument:element.documentElement).defaultView;return((w&&(element!==w)&&w.getComputedStyle)?w.getComputedStyle(element,null):element.style);} +Sys.UI.Behavior=function Sys$UI$Behavior(element){var e=Function._validateParams(arguments,[{name:"element",domElement:true}]);if(e)throw e;Sys.UI.Behavior.initializeBase(this);this._element=element;var behaviors=element._behaviors;if(!behaviors){element._behaviors=[this];} +else{behaviors[behaviors.length]=this;}} +function Sys$UI$Behavior$get_element(){if(arguments.length!==0)throw Error.parameterCount();return this._element;} +function Sys$UI$Behavior$get_id(){if(arguments.length!==0)throw Error.parameterCount();var baseId=Sys.UI.Behavior.callBaseMethod(this,'get_id');if(baseId)return baseId;if(!this._element||!this._element.id)return'';return this._element.id+'$'+this.get_name();} +function Sys$UI$Behavior$get_name(){if(arguments.length!==0)throw Error.parameterCount();if(this._name)return this._name;var name=Object.getTypeName(this);var i=name.lastIndexOf('.');if(i!=-1)name=name.substr(i+1);if(!this.get_isInitialized())this._name=name;return name;} +function Sys$UI$Behavior$set_name(value){if((value==='')||(value.charAt(0)===' ')||(value.charAt(value.length-1)===' ')) +throw Error.argument('value',Sys.Res.invalidId);if(typeof(this._element[value])!=='undefined') +throw Error.invalidOperation(String.format(Sys.Res.behaviorDuplicateName,value));if(this.get_isInitialized())throw Error.invalidOperation(Sys.Res.cantSetNameAfterInit);this._name=value;} +function Sys$UI$Behavior$initialize(){Sys.UI.Behavior.callBaseMethod(this,'initialize');var name=this.get_name();if(name)this._element[name]=this;} +function Sys$UI$Behavior$dispose(){Sys.UI.Behavior.callBaseMethod(this,'dispose');if(this._element){var name=this.get_name();if(name){this._element[name]=null;} +Array.remove(this._element._behaviors,this);delete this._element;}} +Sys.UI.Behavior.prototype={_name:null,get_element:Sys$UI$Behavior$get_element,get_id:Sys$UI$Behavior$get_id,get_name:Sys$UI$Behavior$get_name,set_name:Sys$UI$Behavior$set_name,initialize:Sys$UI$Behavior$initialize,dispose:Sys$UI$Behavior$dispose} +Sys.UI.Behavior.registerClass('Sys.UI.Behavior',Sys.Component);Sys.UI.Behavior.getBehaviorByName=function Sys$UI$Behavior$getBehaviorByName(element,name){var e=Function._validateParams(arguments,[{name:"element",domElement:true},{name:"name",type:String}]);if(e)throw e;var b=element[name];return(b&&Sys.UI.Behavior.isInstanceOfType(b))?b:null;} +Sys.UI.Behavior.getBehaviors=function Sys$UI$Behavior$getBehaviors(element){var e=Function._validateParams(arguments,[{name:"element",domElement:true}]);if(e)throw e;if(!element._behaviors)return[];return Array.clone(element._behaviors);} +Sys.UI.Behavior.getBehaviorsByType=function Sys$UI$Behavior$getBehaviorsByType(element,type){var e=Function._validateParams(arguments,[{name:"element",domElement:true},{name:"type",type:Type}]);if(e)throw e;var behaviors=element._behaviors;var results=[];if(behaviors){for(var i=0,l=behaviors.length;i=0;i--){var node=childNodes[i];if(node.nodeType===1){if(node.dispose&&typeof(node.dispose)==="function"){node.dispose();} +else if(node.control&&typeof(node.control.dispose)==="function"){node.control.dispose();} +var behaviors=Sys.UI.Behavior.getBehaviors(node);for(var j=behaviors.length-1;j>=0;j--){behaviors[j].dispose();} +this._destroyTree(node);}}}} +function Sys$WebForms$PageRequestManager$dispose(){if(this._form){Sys.UI.DomEvent.removeHandler(this._form,'submit',this._onFormSubmitHandler);Sys.UI.DomEvent.removeHandler(this._form,'click',this._onFormElementClickHandler);Sys.UI.DomEvent.removeHandler(window,'unload',this._onWindowUnloadHandler);Sys.UI.DomEvent.removeHandler(window,'load',this._pageLoadedHandler);} +if(this._originalDoPostBack){window.__doPostBack=this._originalDoPostBack;this._originalDoPostBack=null;} +this._form=null;this._updatePanelIDs=null;this._oldUpdatePanelIDs=null;this._childUpdatePanelIDs=null;this._updatePanelClientIDs=null;this._asyncPostBackControlIDs=null;this._asyncPostBackControlClientIDs=null;this._postBackControlIDs=null;this._postBackControlClientIDs=null;this._asyncPostBackTimeout=null;this._scrollPosition=null;this._dataItems=null;} +function Sys$WebForms$PageRequestManager$_doPostBack(eventTarget,eventArgument){this._additionalInput=null;var form=this._form;if(form.action!==form._initialAction){this._postBackSettings=this._createPostBackSettings(false,null,null);} +else{var clientID=this._uniqueIDToClientID(eventTarget);var postBackElement=document.getElementById(clientID);if(!postBackElement){if(Array.contains(this._asyncPostBackControlIDs,eventTarget)){this._postBackSettings=this._createPostBackSettings(true,this._scriptManagerID+'|'+eventTarget,null);} +else{if(Array.contains(this._postBackControlIDs,eventTarget)){this._postBackSettings=this._createPostBackSettings(false,null,null);} +else{var nearestUniqueIDMatch=this._findNearestElement(eventTarget);if(nearestUniqueIDMatch){this._postBackSettings=this._getPostBackSettings(nearestUniqueIDMatch,eventTarget);} +else{this._postBackSettings=this._createPostBackSettings(false,null,null);}}}} +else{this._postBackSettings=this._getPostBackSettings(postBackElement,eventTarget);}} +if(!this._postBackSettings.async){form.onsubmit=this._onsubmit;this._originalDoPostBack(eventTarget,eventArgument);form.onsubmit=null;return;} +form.__EVENTTARGET.value=eventTarget;form.__EVENTARGUMENT.value=eventArgument;this._onFormSubmit();} +function Sys$WebForms$PageRequestManager$_elementContains(container,element){while(element){if(element===container){return true;} +element=element.parentNode;} +return false;} +function Sys$WebForms$PageRequestManager$_endPostBack(error,response){this._processingRequest=false;this._request=null;this._additionalInput=null;var handler=this._get_eventHandlerList().getHandler("endRequest");var errorHandled=false;if(handler){var eventArgs=new Sys.WebForms.EndRequestEventArgs(error,this._dataItems,response);handler(this,eventArgs);errorHandled=eventArgs.get_errorHandled();} +this._dataItems=null;if(error&&!errorHandled){alert(error.message);}} +function Sys$WebForms$PageRequestManager$_findNearestElement(uniqueID){while(uniqueID.length>0){var clientID=this._uniqueIDToClientID(uniqueID);var element=document.getElementById(clientID);if(element){return element;} +var indexOfLastDollar=uniqueID.lastIndexOf('$');if(indexOfLastDollar===-1){return null;} +uniqueID=uniqueID.substring(0,indexOfLastDollar);} +return null;} +function Sys$WebForms$PageRequestManager$_findText(text,location){var startIndex=Math.max(0,location-20);var endIndex=Math.min(text.length,location+20);return text.substring(startIndex,endIndex);} +function Sys$WebForms$PageRequestManager$_getPageLoadedEventArgs(initialLoad){var updated=[];var created=[];var oldIDs=this._oldUpdatePanelIDs||[];var newIDs=this._updatePanelIDs;var childIDs=this._childUpdatePanelIDs||[];var refreshedIDs=this._panelsToRefreshIDs||[];for(var i=0;i-1)){Array.add(deleted,document.getElementById(this._uniqueIDToClientID(oldIDs[i])));}} +return new Sys.WebForms.PageLoadingEventArgs(updated,deleted,this._dataItems);} +function Sys$WebForms$PageRequestManager$_getPostBackSettings(element,elementUniqueID){var originalElement=element;var proposedSettings=null;while(element){if(element.id){if(!proposedSettings&&Array.contains(this._asyncPostBackControlClientIDs,element.id)){proposedSettings=this._createPostBackSettings(true,this._scriptManagerID+'|'+elementUniqueID,originalElement);} +else{if(!proposedSettings&&Array.contains(this._postBackControlClientIDs,element.id)){return this._createPostBackSettings(false,null,null);} +else{var indexOfPanel=Array.indexOf(this._updatePanelClientIDs,element.id);if(indexOfPanel!==-1){if(this._updatePanelHasChildrenAsTriggers[indexOfPanel]){return this._createPostBackSettings(true,this._updatePanelIDs[indexOfPanel]+'|'+elementUniqueID,originalElement);} +else{return this._createPostBackSettings(true,this._scriptManagerID+'|'+elementUniqueID,originalElement);}}}} +if(!proposedSettings&&this._matchesParentIDInList(element.id,this._asyncPostBackControlClientIDs)){proposedSettings=this._createPostBackSettings(true,this._scriptManagerID+'|'+elementUniqueID,originalElement);} +else{if(!proposedSettings&&this._matchesParentIDInList(element.id,this._postBackControlClientIDs)){return this._createPostBackSettings(false,null,null);}}} +element=element.parentNode;} +if(!proposedSettings){return this._createPostBackSettings(false,null,null);} +else{return proposedSettings;}} +function Sys$WebForms$PageRequestManager$_getScrollPosition(){var d=document.documentElement;if(d&&(this._validPosition(d.scrollLeft)||this._validPosition(d.scrollTop))){return{x:d.scrollLeft,y:d.scrollTop};} +else{d=document.body;if(d&&(this._validPosition(d.scrollLeft)||this._validPosition(d.scrollTop))){return{x:d.scrollLeft,y:d.scrollTop};} +else{if(this._validPosition(window.pageXOffset)||this._validPosition(window.pageYOffset)){return{x:window.pageXOffset,y:window.pageYOffset};} +else{return{x:0,y:0};}}}} +function Sys$WebForms$PageRequestManager$_initializeInternal(scriptManagerID,formElement){this._scriptManagerID=scriptManagerID;this._form=formElement;this._form._initialAction=this._form.action;this._onsubmit=this._form.onsubmit;this._form.onsubmit=null;this._onFormSubmitHandler=Function.createDelegate(this,this._onFormSubmit);this._onFormElementClickHandler=Function.createDelegate(this,this._onFormElementClick);this._onWindowUnloadHandler=Function.createDelegate(this,this._onWindowUnload);Sys.UI.DomEvent.addHandler(this._form,'submit',this._onFormSubmitHandler);Sys.UI.DomEvent.addHandler(this._form,'click',this._onFormElementClickHandler);Sys.UI.DomEvent.addHandler(window,'unload',this._onWindowUnloadHandler);this._originalDoPostBack=window.__doPostBack;if(this._originalDoPostBack){window.__doPostBack=Function.createDelegate(this,this._doPostBack);} +this._pageLoadedHandler=Function.createDelegate(this,this._pageLoadedInitialLoad);Sys.UI.DomEvent.addHandler(window,'load',this._pageLoadedHandler);} +function Sys$WebForms$PageRequestManager$_matchesParentIDInList(clientID,parentIDList){for(var i=0;i=reply.length){parserErrorDetails=this._findText(reply,reply.length);break;} +content=this._decodeString(reply.substr(replyIndex,len));replyIndex+=len;if(reply.charAt(replyIndex)!==delimitByLengthDelimiter){parserErrorDetails=this._findText(reply,replyIndex);break;} +replyIndex++;Array.add(delta,{type:type,id:id,content:content});} +if(parserErrorDetails){this._endPostBack(this._createPageRequestManagerParserError(String.format(Sys.WebForms.Res.PRM_ParserErrorDetails,parserErrorDetails)),sender);return;} +var updatePanelNodes=[];var hiddenFieldNodes=[];var arrayDeclarationNodes=[];var scriptBlockNodes=[];var expandoNodes=[];var onSubmitNodes=[];var dataItemNodes=[];var dataItemJsonNodes=[];var scriptDisposeNodes=[];var asyncPostBackControlIDsNode,postBackControlIDsNode,updatePanelIDsNode,asyncPostBackTimeoutNode,childUpdatePanelIDsNode,panelsToRefreshNode,formActionNode;for(var i=0;i", "", ""); + var dtToday = new Date(); + var thisMonth = firstDay.getMonth(); + var thisYear = firstDay.getFullYear(); + var nPrevMonth = (thisMonth == 0 ) ? 11 : (thisMonth - 1); + var nNextMonth = (thisMonth == 11 ) ? 0 : (thisMonth + 1); + var nPrevMonthYear = (nPrevMonth == 11) ? (thisYear - 1): thisYear; + var nNextMonthYear = (nNextMonth == 0) ? (thisYear + 1): thisYear; + var sToday = String((dtToday.getMonth()+1) + "/01/" + dtToday.getFullYear()); + var sPrevMonth = String((nPrevMonth+1) + "/01/" + nPrevMonthYear); + var sNextMonth = String((nNextMonth+1) + "/01/" + nNextMonthYear); + var sPrevYear1 = String((thisMonth+1) + "/01/" + (thisYear - 1)); + var sNextYear1 = String((thisMonth+1) + "/01/" + (thisYear + 1)); + var tmpDate = new Date( sNextMonth ); + + tmpDate = new Date( tmpDate.valueOf() - 1001 ); + lastDate = tmpDate.getDate(); + + if (this.popCalMonths.split) // javascript 1.1 defensive code + { + var monthNames = this.popCalMonths.split(","); + var dayNames = this.popCalDays.split(","); + } + else // Need to build a js 1.0 split algorithm, default English for now + { + var monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December"); + var dayNames = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat") + } + + var styles = "" + var cellAttribs = "align=\"center\" class=\"day\" BGCOLOR=\"#F1F1F1\"onMouseOver=\"temp=this.style.backgroundColor;this.style.backgroundColor='#CCCCCC';\" onMouseOut=\"this.style.backgroundColor=temp;\"" + var cellAttribs2 = "align=\"center\" BGCOLOR=\"#F1F1F1\" onMouseOver=\"temp=this.style.backgroundColor;this.style.backgroundColor='#CCCCCC';\" onMouseOut=\"this.style.backgroundColor=temp;\"" + var htmlHead = ""+popCalTitle+"" + styles + ""; + var htmlTail = ""; + var closeAnchor = "
    "; + var todayAnchor = ""+popCalToday+""; + var prevMonthAnchor = "" + monthNames[nPrevMonth] + ""; + var nextMonthAnchor = "" + monthNames[nNextMonth] + ""; + var prevYear1Anchor = ""+(thisYear-1)+""; + var nextYear1Anchor = ""+(thisYear+1)+""; + + popCalData += (htmlHead + fnt[1]); + popCalData += ("
    "); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += ("
     "); + popCalData += (fnt[0]+prevYear1Anchor+""); + popCalData += (fnt[0]+todayAnchor+""); + popCalData += (fnt[0]+nextYear1Anchor+" 
    "); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += ("
    "); + popCalData += (fnt[0] + prevMonthAnchor + ""); + popCalData += ("  "+fnt[1]+"" + monthNames[thisMonth] + ", " + thisYear + "  "); + popCalData += (fnt[0]+nextMonthAnchor+"

    "); + popCalData += ("" ); + popCalData += (""); + popCalData += (""); + + /* + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += (""); + popCalData += (""); + */ + var xday = 0; + for (xday = 0; xday < 7; xday++) + { + popCalData += (""); + }; + popCalData += (""); + + var calDay = 0; + var monthDate = 1; + var weekDay = firstDay.getDay(); + do + { + popCalData += (""); + for (calDay = 0; calDay < 7; calDay++ ) + { + if(((weekDay+7-popCalFirstDayWeek)%7 != calDay) || (monthDate > lastDate)) + { + popCalData += (""); + continue; + } + else + { + anchorVal = ""; + jsVal = "javascript:window.opener.calPopupSetDate(window.opener.popCalDstFld,'" + constructDate(monthDate,thisMonth+1,thisYear) + "');window.opener.closeCalPopup()"; + + popCalData += (""); + else + popCalData += (anchorVal+fnt[1]+monthDate+""); + + weekDay++; + monthDate++; + } + } + weekDay = popCalFirstDayWeek; + popCalData += (""); + } while( monthDate <= lastDate ); + + popCalData += ("
    "+fnt[1]+""+dayNames[0]+""+fnt[1]+""+dayNames[1]+""+fnt[1]+""+dayNames[2]+""+fnt[1]+""+dayNames[3]+""+fnt[1]+""+dayNames[4]+""+fnt[1]+""+dayNames[5]+""+fnt[1]+""+dayNames[6]+""+fnt[1]+""+dayNames[(xday+popCalFirstDayWeek)%7]+"
    "+fnt[1]+" "); + + if ((firstDay.getMonth() == dtToday.getMonth()) && (monthDate == dtToday.getDate()) && (thisYear == dtToday.getFullYear()) ) + popCalData += (anchorVal+fnt[2]+monthDate+"

    "); + + popCalData += (closeAnchor+"
    "+htmlTail); + return( popCalData ); +} + +function calPopupSetDate() +{ + calPopupSetDate.arguments[0].value = calPopupSetDate.arguments[1]; +} + +// utility function +function padZero(num) +{ + return ((num <= 9) ? ("0" + num) : num); +} + +// Format short date +function constructDate(d,m,y) +{ + var fmtDate = this.popCalDstFmt + fmtDate = fmtDate.replace ('dd', padZero(d)) + fmtDate = fmtDate.replace ('d', d) + fmtDate = fmtDate.replace ('MM', padZero(m)) + fmtDate = fmtDate.replace ('M', m) + fmtDate = fmtDate.replace ('yyyy', y) + fmtDate = fmtDate.replace ('yy', padZero(y%100)) + return fmtDate; +} + +// ------------------------------------------------------------------ +// Utility functions for parsing in getDateFromFormat() +// ------------------------------------------------------------------ +function _isInteger(val) { + var digits="1234567890"; + for (var i=0; i < val.length; i++) { + if (digits.indexOf(val.charAt(i))==-1) { return false; } + } + return true; + } +function _getInt(str,i,minlength,maxlength) { + for (var x=maxlength; x>=minlength; x--) { + var token=str.substring(i,i+x); + if (token.length < minlength) { return null; } + if (_isInteger(token)) { return token; } + } + return null; + } + +// ------------------------------------------------------------------ +// getDateFromFormat( date_string , format_string ) +// +// This function takes a date string and a format string. It matches +// If the date string matches the format string, it returns the +// getTime() of the date. If it does not match, it returns 0. +// ------------------------------------------------------------------ +function getDateFromFormat(val,format) { + val=val+""; + format=format+""; + var i_val=0; + var i_format=0; + var c=""; + var token=""; + var x,y; + var now=new Date(); + var year=now.getYear(); + var month=now.getMonth()+1; + var date=1; + + while (i_format < format.length) { + // Get next token from format string + c=format.charAt(i_format); + token=""; + while ((format.charAt(i_format)==c) && (i_format < format.length)) { + token += format.charAt(i_format++); + } + // Extract contents of value based on format token + if (token=="yyyy" || token=="yy" || token=="y") { + if (token=="yyyy") { x=4;y=4; } + if (token=="yy") { x=2;y=2; } + if (token=="y") { x=2;y=4; } + year=_getInt(val,i_val,x,y); + if (year==null) { return 0; } + i_val += year.length; + if (year.length==2) { + if (year > 70) { year=1900+(year-0); } + else { year=2000+(year-0); } + } + } + else if (token=="MM"||token=="M") { + month=_getInt(val,i_val,token.length,2); + if(month==null||(month<1)||(month>12)){return 0;} + i_val+=month.length;} + else if (token=="dd"||token=="d") { + date=_getInt(val,i_val,token.length,2); + if(date==null||(date<1)||(date>31)){return 0;} + i_val+=date.length;} + else { + if (val.substring(i_val,i_val+token.length)!=token) {return 0;} + else {i_val+=token.length;} + } + } + // If there are any trailing characters left in the value, it doesn't match + if (i_val != val.length) { return 0; } + // Is date valid for month? + if (month==2) { + // Check for leap year + if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year + if (date > 29){ return 0; } + } + else { if (date > 28) { return 0; } } + } + if ((month==4)||(month==6)||(month==9)||(month==11)) { + if (date > 30) { return 0; } + } + var newdate=new Date(year,month-1,date); + return newdate; + } + +if (typeof(Sys) != "undefined"){ + Sys.Application.notifyScriptLoaded() ; +} + +// ****************** +// End Popup Calendar +// ****************** diff --git a/Website/js/dnn.controls.dnninputtext.js b/Website/js/dnn.controls.dnninputtext.js new file mode 100644 index 00000000000..574361149b9 --- /dev/null +++ b/Website/js/dnn.controls.dnninputtext.js @@ -0,0 +1,16 @@ + +dnn.controls.DNNInputText=function(multiLine) +{if(multiLine) +this.control=document.createElement('textarea');else +{this.control=document.createElement('input');this.control.type='text';} +this.container=this.control;this.initialized=true;this.supportsMultiLine=multiLine;this.isRichText=false;this.loaded=false;} +dnn.controls.DNNInputText.prototype={focus:function() +{this.control.focus();var len=this.getText().length;if(this.control.createTextRange) +{var range=this.control.createTextRange();range.moveStart('character',len);range.moveEnd('character',len);range.collapse();range.select();} +else +{this.control.selectionStart=len;this.control.selectionEnd=len;}},ltrim:function(s) +{return s.replace(/^\s*/,"");},rtrim:function(s) +{return s.replace(/\s*$/,"");},getText:function() +{return this.control.value;},setText:function(s) +{this.control.value=this.rtrim(this.ltrim(s));}} +dnn.controls.DNNInputText.registerClass('dnn.controls.DNNInputText'); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnnlabeledit.js b/Website/js/dnn.controls.dnnlabeledit.js new file mode 100644 index 00000000000..9913561e42e --- /dev/null +++ b/Website/js/dnn.controls.dnnlabeledit.js @@ -0,0 +1 @@ +Type.registerNamespace("dnn.controls");dnn.extend(dnn.controls,{initLabelEdit:function(a){if(a){var b=new dnn.controls.DNNLabelEdit(a);b.initialize();return b}}});dnn.controls.DNNLabelEdit=function(o){dnn.controls.DNNLabelEdit.initializeBase(this,[o]);this.control=this.container;this.editWrapper=null;this.editContainer=null;this.editControl=null;this.prevText="";this.onblurSave=(this.getProp("blursave","1")=="1");this.toolbarId=this.getProp("tbId","");this.nsPrefix=this.getProp("nsPrefix","");this.toolbarEventName=this.getProp("tbEvent","onmousemove");this.toolbar=null;this.css=o.className;this.cssEdit=this.getProp("cssEdit","");this.cssWork=this.getProp("cssWork","");this.cssOver=this.getProp("cssOver","");this.sysImgPath=this.getProp("sysimgpath","");this.callBack=this.getProp("callback","");this.callBackStatFunc=this.getProp("callbackSF","");if(this.callBackStatFunc.length>0){this.add_handler("callBackStatus",eval(this.callBackStatFunc))}this.beforeSaveFunc=this.getProp("beforeSaveF","");if(this.beforeSaveFunc.length>0){this.add_handler("beforeSave",eval(this.beforeSaveFunc))}this.eventName=this.getProp("eventName","onclick");this.multiLineEnabled=this.getProp("multiline","0")=="1";this.saveOnEnter=this.getProp("saveonenter","1")=="1";this.richTextEnabled=this.getProp("richtext","0")=="1";this.supportsCE=(document.body.contentEditable!=null);if(dnn.dom.browser.isType(dnn.dom.browser.Safari)||dnn.dom.browser.isType(dnn.dom.browser.Opera)){this.supportsCE=false}this.supportsRichText=(this.supportsCE||(dnn.dom.browser.isType(dnn.dom.browser.Mozilla)&&navigator.productSub>="20050111"));if(this.eventName!="none"){this.addHandlers(o,this.getDynamicEventObject(this._getEventName(this.eventName),this.performEdit),this)}if(this.toolbarId.length>0){this.addHandlers(o,this.getDynamicEventObject(this._getEventName(this.toolbarEventName),this.showToolBar),this)}this.addHandlers(o,{mousemove:this.mouseMove,mouseout:this.mouseOut},this);this._toolbarActionDelegate=dnn.createDelegate(this,this.toolbarAction);this._initToolbarDelegate=dnn.createDelegate(this,this.initToolbar);this._performEditDelegate=dnn.createDelegate(this,this.performEdit)};dnn.controls.DNNLabelEdit.prototype={isEditMode:function(){return(this.container.style.display!="")},initToolbar:function(){if(this.toolbar==null){var a=dnn.dom.scriptStatus("dnn.controls.dnntoolbar.js");if(a=="complete"){this.toolbar=new dnn.controls.DNNToolBar(this.ns);this.toolbar.loadDefinition(this.toolbarId,this.nsPrefix,this.container,this.container.parentNode,this.container,this._toolbarActionDelegate);this.handleToolbarDisplay()}else{if(a==""){dnn.dom.loadScript(dnn.dom.getScriptPath()+"dnn.controls.dnntoolbar.js","",this._initToolbarDelegate)}}}},toolbarAction:function(a,d){var c=a.clickAction;if(c=="edit"){this.performEdit()}else{if(c=="save"){this.persistEdit();this.toolbar.hide()}else{if(c=="cancel"){this.cancelEdit();this.toolbar.hide()}else{if(this.isFormatButton(c)){if(this.editWrapper){var b;if(c=="createlink"&&dnn.dom.browser.isType(dnn.dom.browser.InternetExplorer)==false){b=prompt(a.tooltip)}this.editWrapper.focus();this.editWrapper.execCommand(c,null,b)}}}}}},performEdit:function(){if(this.toolbar){this.toolbar.hide()}this.initEditWrapper();if(this.editContainer!=null){this.editContainer.style.width="100%";this.editContainer.style.display="";this.editContainer.style.overflow="auto";this.editContainer.style.overflowX="hidden";this.prevText=this.container.innerHTML;if(dnn.dom.browser.isType(dnn.dom.browser.Safari)&&this.container.innerText){this.prevText=this.container.innerText}this.editWrapper.setText(this.prevText);this.initEditControl();this.container.style.display="none";this.handleToolbarDisplay();var a=new Sys.CancelEventArgs();this.invoke_handler("beforeEdit",a);if(a.get_cancel()){this.cancelEdit();return}}},showToolBar:function(){this.initToolbar();if(this.toolbar){this.toolbar.show(true)}},mouseMove:function(a){if(this.toolbarId.length>0&&this.toolbarEventName=="onmousemove"){this.showToolBar()}this.container.className=this.css+" "+this.cssOver},mouseOut:function(){if(this.toolbar){this.toolbar.beginHide()}this.container.className=this.css},initEditWrapper:function(){if(this.editWrapper==null){var e=(this.richTextEnabled&&this.supportsRichText);var c=(e?"dnn.controls.dnnrichtext.js":"dnn.controls.dnninputtext.js");var b=dnn.dom.scriptStatus(c);if(b=="complete"){var a;if(this.richTextEnabled&&this.supportsRichText){var d=dnn.dom.getObjMethRef(this,"initEditControl");a=new dnn.controls.DNNRichText(d)}else{a=new dnn.controls.DNNInputText(this.multiLineEnabled)}this.editWrapper=a;this.editContainer=this.editWrapper.container;this.container.parentNode.insertBefore(this.editContainer,this.container);if(this.richTextEnabled&&this.supportsCE){this.initEditControl()}}else{if(b==""){dnn.dom.loadScript(dnn.dom.getScriptPath()+c,"",this._performEditDelegate)}}}},initEditControl:function(){if(this.editWrapper.initialized){this.editControl=this.editWrapper.control;this.editControl.className=this.container.className+" "+this.cssEdit;this.editWrapper.focus();if(this.editWrapper.loaded==false){var a={keypress:this.handleKeyPress,mousemove:this.mouseMove,mouseout:this.mouseOut};if(this.onblurSave){a.blur=this.persistEdit}if(this.editWrapper.supportsCE||this.editWrapper.isRichText==false){this.addHandlers(this.editControl,a,this)}else{this.addHandlers(this.editContainer.contentWindow.document,a,this)}this.editWrapper.loaded=true}}},persistEdit:function(){if(this.editWrapper.getText()!=this.prevText){if(this.invoke_compatHandler("beforeSave",null,this)){this.editControl.className=this.container.className+" "+this.cssWork;eval(this.callBack.replace("[TEXT]",dnn.escapeForEval(this.editWrapper.getText())))}}else{this.showLabel()}},cancelEdit:function(){this.editWrapper.setText(this.prevText);this.showLabel()},callBackStatus:function(a,b,c){var d=b;d.invoke_compatHandler("callBackStatus",a,b,c)},callBackSuccess:function(a,b,c){b.callBackStatus(a,b);b.invoke_handler("callBackSuccess",new dnn.controls.DNNCallbackEventArgs(a,b,c));b.showLabel();b.flashLabel()},raiseEvent:function(sFunc,evt,element){if(this[sFunc].length>0){var ptr=eval(this[sFunc]);return ptr(evt,element)!=false}return true},handleToolbarDisplay:function(){if(this.toolbar){var c=this.isEditMode();var b;for(var a in this.toolbar.buttons){b=this.toolbar.buttons[a];if(typeof b=="function"){continue}if(a=="edit"){b.visible=!c;if(b.visible){this.toolbar.css=this.toolbar.css.replace(" editMode","")}else{this.toolbar.css=this.toolbar.css+" editMode"}}else{if(this.isFormatButton(a)){b.visible=(c&&this.editWrapper&&this.editWrapper.isRichText)}else{b.visible=c}}}this.toolbar.refresh()}},isFormatButton:function(a){return"~bold~italic~underline~justifyleft~justifycenter~justifyright~insertorderedlist~insertunorderedlist~outdent~indent~createlink~".indexOf("~"+a+"~")>-1},showLabel:function(){this.container.innerHTML=this.editWrapper.getText();this.container.style.display="";this.container.className=this.css;this.editContainer.style.display="none";this.handleToolbarDisplay()},flashLabel:function(){var a=this;this.container.style.backgroundColor="#fffacd";setTimeout(function(){a.container.style.backgroundColor="#fffff0";setTimeout(function(){a.container.style.backgroundColor="transparent"},300)},2500)},callBackFail:function(a,b,c){b.invoke_handler("callBackFail",new dnn.controls.DNNCallbackEventArgs(a,b,c));b.cancelEdit()},handleKeyPress:function(a){if(a.charCode==KEY_RETURN&&this.editWrapper.supportsMultiLine==false){if(this.saveOnEnter){this.persistEdit()}a.preventDefault()}else{if(a.charCode==KEY_ESCAPE){this.cancelEdit();a.preventDefault()}}},dispose:function(){this._toolbarActionDelegate=null;this._initToolbarDelegate=null;this._performEditDelegate=null;dnn.controls.DNNLabelEdit.callBaseMethod(this,"dispose")}};dnn.controls.DNNLabelEdit.registerClass("dnn.controls.DNNLabelEdit",dnn.controls.control); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnnmenu.js b/Website/js/dnn.controls.dnnmenu.js new file mode 100644 index 00000000000..2d3947ea7da --- /dev/null +++ b/Website/js/dnn.controls.dnnmenu.js @@ -0,0 +1,246 @@ + +Type.registerNamespace('dnn.controls');dnn.extend(dnn.controls,{initMenu:function(ctl) +{if(ctl) +{var menu=new dnn.controls.DNNMenu(ctl);menu.initialize();return menu;}}});dnn.controls.DNNMenu=function(o) +{dnn.controls.DNNMenu.initializeBase(this,[o]);this.rootNode=null;this.nodes=[];this._loadNodes();this.mbcss=this.getProp('mbcss','');this.mcss=this.getProp('mcss','');this.css=this.getProp('css','');this.cssChild=this.getProp('csschild','');this.cssHover=this.getProp('csshover','');this.cssSel=this.getProp('csssel','');this.cssIcon=this.getProp('cssicon','');this.sysImgPath=this.getProp('sysimgpath','images/');this.imagePaths=this.getProp('imagepaths','').split(',');this.imageList=this.getProp('imagelist','').split(',');for(var i=0;i-1) +this.imageList[i]=this.imagePaths[this.imageList[i].substring(1,index)]+this.imageList[i].substring(index+1);} +this.urlList=this.getProp('urllist','').split(',');this.workImg=this.getProp('workimg','dnnanim.gif');this.rootArrow=this.getProp('rarrowimg','');this.childArrow=this.getProp('carrowimg','');this.target=this.getProp('target','');this.defaultJS=this.getProp('js','');this.postBack=this.getProp('postback','');this.callBack=this.getProp('callback','');this.callBackStatFunc=this.getProp('callbacksf','');if(this.callBackStatFunc.length>0) +this.add_handler('callBackStatus',eval(this.callBackStatFunc));this.orient=new Number(this.getProp('orient',dnn.controls.orient.horizontal));this.suborient=new Number(this.getProp('suborient',dnn.controls.orient.vertical));this.openMenus=[];this.moutDelay=this.getProp('moutdelay',500);this.minDelay=new Number(this.getProp('mindelay',250));this.renderMode=new Number(this.getProp('rmode',0));this.useTables=(this.renderMode==dnn.controls.menuRenderMode.normal);this.enablePostbackState=(this.getProp('enablepbstate','0')=='1');this.podInProgress=false;this.keyboardAccess=(this.getProp('kbaccess','1')=='1');this.hoverMNode=null;this.selMNode=null;this.animation=new Number(this.getProp('anim','0'));this.easingType=new Number(this.getProp('easeType','3'));this.easingDir=new Number(this.getProp('easeDir','1'));;this.animationLen=new Number(this.getProp('animLen','1'));this.animationInterval=new Number(this.getProp('animInt','10'));this._attachedHandlers=[];this._onsubmitDelegate=null;this._hideMenusDelegate=null;this._expandNodeDelegate=null;} +dnn.controls.DNNMenu.prototype={initialize:function() +{dnn.controls.DNNMenu.callBaseMethod(this,'initialize');if(this.keyboardAccess) +{this._setupKeyHandling();} +this.generateMenuHTML();if(this.enablePostbackState) +{this._onsubmitDelegate=Function.createDelegate(this,this._onsubmit);dnn.controls.submitComp.add_handler(this._onsubmitDelegate);} +this._hideMenusDelegate=dnn.createDelegate(this,this.hideMenus);this._expandNodeDelegate=dnn.createDelegate(this,this.__expandNode);},generateMenuHTML:function() +{this.container.className=this.mbcss;dnn.dom.disableTextSelect(this.container); +if(this.rootNode!==null){for(var i=0;i0) +menuBuilder.appendChild(this.renderCustomHTML(mNode.lhtml));var icon=this.renderIcon(mNode);menuBuilder.appendChild(icon);if(this.useTables==false||mNode.level==0) +icon.className='icn '+(mNode.cssIcon.length>0?mNode.cssIcon:this.cssIcon);else +menuBuilder.subcont.className='icn '+(mNode.cssIcon.length>0?mNode.cssIcon:this.cssIcon);if(mNode.isBreak==false) +menuBuilder.appendChild(this.renderText(mNode),true);menuBuilder.newCell();this.renderArrow(mNode,menuBuilder.subcont);if(mNode.rhtml.length>0) +menuBuilder.appendChild(this.renderCustomHTML(mNode.rhtml));if(mNode.toolTip.length>0) +menuBuilder.row.title=mNode.toolTip;} +this.assignCss(mNode);if(mNode.enabled) +this.addHandlers(menuBuilder.row,{"click":this._nodeTextClick},this);if(this._attachedHandlers[menuBuilder.container.id]!='mouseover') +{this._attachedHandlers[menuBuilder.container.id]='mouseover';this.addHandlers(menuBuilder.container,{"mouseover":this._nodeMOver,"mouseout":this._nodeMOut},this);} +if(mNode.hasNodes||mNode.hasPendingNodes) +{var subMenu=this.renderSubMenu(mNode);this.container.appendChild(subMenu);dnn.dom.positioning.placeOnTop(subMenu,false,this.sysImgPath+'spacer.gif');for(var i=0;i-1||mNode.image!='') +{var img=this.createChildControl('img',mNode.id,'icn');img.src=(mNode.image.length>0?mNode.image:this.imageList[mNode.imageIndex]);ctl.appendChild(img);} +return ctl;},renderArrow:function(mNode,ctr) +{if(mNode.hasNodes||mNode.hasPendingNodes) +{var imgSrc=(mNode.level==0?this.rootArrow:this.childArrow);if(imgSrc.trim().length>0) +{if(this.useTables&&mNode.level>0) +{var img=dnn.dom.createElement('img');img.src=imgSrc;ctr.appendChild(img);} +else +{ctr.style.backgroundImage='url('+imgSrc+')';ctr.style.backgroundRepeat='no-repeat';ctr.style.backgroundPosition='right';}}}},renderText:function(mNode) +{var ctl=this.createChildControl('span',mNode.id,'t');ctl.className='txt';ctl.innerHTML=mNode.text;ctl.style.cursor='pointer';return ctl;},renderSubMenu:function(mNode) +{var menuBuilder=this._getMenuBuilder(mNode,null);var subMenu=menuBuilder.createSubMenu();subMenu.style.position='absolute';subMenu.style.display='none';var css=this.mcss;css+=' m m'+mNode.level;css+=' mid'+mNode.id;subMenu.className=css;return subMenu;},_getMenuBuilder:function(mNode,ctr) +{var menuBuilder;if(ctr) +{if(this.renderMode==dnn.controls.menuRenderMode.normal&&mNode.level>0&&this.isNodeVertical(mNode)) +menuBuilder=new dnn.controls.DNNMenuTableBuilder(this,mNode,ctr);else if(this.renderMode==dnn.controls.menuRenderMode.unorderdlist) +menuBuilder=new dnn.controls.DNNMenuListBuilder(this,mNode,ctr);else +menuBuilder=new dnn.controls.DNNMenuBuilder(this,mNode,ctr);} +else +{if(this.renderMode==dnn.controls.menuRenderMode.normal&&this.suborient==dnn.controls.orient.vertical) +menuBuilder=new dnn.controls.DNNMenuTableBuilder(this,mNode);else if(this.renderMode==dnn.controls.menuRenderMode.unorderdlist) +menuBuilder=new dnn.controls.DNNMenuListBuilder(this,mNode);else +menuBuilder=new dnn.controls.DNNMenuBuilder(this,mNode);} +return menuBuilder;},hoverNode:function(mNode) +{if(this.hoverMNode!=null) +{this.hoverMNode.hover=false;this.assignCss(this.hoverMNode);} +if(mNode!=null) +{mNode.hover=true;this.assignCss(mNode);} +this.hoverMNode=mNode;},__expandNode:function(ctx) +{this.expandNode(ctx,true);},expandNode:function(mNode,force) +{dnn.cancelDelay(this.ns+'min');if(mNode.hasPendingNodes) +{if(this.podInProgress==false) +{this.podInProgress=true;this.showWorkImage(mNode,true);mNode.menu=this;if(this.callBack.indexOf('[NODEXML]')>-1) +eval(this.callBack.replace('[NODEXML]',dnn.escapeForEval(mNode.node.getXml())));else +eval(this.callBack.replace('[NODEID]',mNode.id));}} +else +{if(this.openMenus.length>0&&this.openMenus[this.openMenus.length-1].id==mNode.id) +return;if(this.minDelay==0||force) +{this.hideMenus(new dnn.controls.DNNMenuNode(mNode.node.parentNode()));var subMenu=this.getChildControl(mNode.id,'sub');if(subMenu!=null) +{this.positionMenu(mNode,subMenu);this.showSubMenu(subMenu,true,mNode);this.openMenus[this.openMenus.length]=mNode;mNode.expanded=true;mNode.update();}} +else +dnn.doDelay(this.ns+'min',this.minDelay,this._expandNodeDelegate,mNode);} +return true;},showSubMenu:function(subMenu,show,mNode) +{dnn.dom.positioning.placeOnTop(subMenu,show,this.sysImgPath+'spacer.gif');subMenu.style.clip='rect(auto,auto,auto,auto)';if(this.animation!=0) +{subMenu.style.display='';var dir;if(this.isNodeVertical(mNode)) +dir=(show?dnn.motion.animationDir.Right:dnn.motion.animationDir.Left);else +dir=(show?dnn.motion.animationDir.Down:dnn.motion.animationDir.Up);dnn.dom.animate(subMenu,this.animation,dir,this.easingType,this.easingDir,this.animationLen,this.animationInterval);} +else +subMenu.style.display=(show?'':'none');},showWorkImage:function(mNode,show) +{if(this.workImg!=null) +{var icon=this.getChildControl(mNode.id,'icn');if(icon!=null) +{if(show) +icon.src=this.sysImgPath+this.workImg;else +icon.src=(mNode.image.length>0?mNode.image:this.imageList[mNode.imageIndex]);}}},isNodeVertical:function(mNode) +{return((mNode.level==0&&this.orient==dnn.controls.orient.vertical)||(mNode.level>0&&this.suborient==dnn.controls.orient.vertical));},hideMenus:function(mNode) +{for(var i=this.openMenus.length-1;i>=0;i--) +{if(mNode!=null&&this.openMenus[i].id==mNode.id) +break;this.collapseNode(this.openMenus[i]);this.openMenus.length=this.openMenus.length-1;}},collapseNode:function(mNode) +{var subMenu=this.getChildControl(mNode.id,'sub');if(subMenu!=null) +{this.positionMenu(mNode,subMenu);this.showSubMenu(subMenu,false,mNode);mNode.expanded=null;mNode.update();return true;}},positionMenu:function(mNode,menu) +{var oPCtl=this.getChildControl(mNode.id,'ctr');if(dnn.dom.browser.isType(dnn.dom.browser.Safari,dnn.dom.browser.Opera)) +{if(oPCtl.tagName=='TR'&&oPCtl.childNodes.length>0) +oPCtl=oPCtl.childNodes[oPCtl.childNodes.length-1];} +var oPDims=new dnn.dom.positioning.dims(oPCtl);var oMDims=new dnn.dom.positioning.dims(menu);var iScrollLeft=dnn.dom.positioning.bodyScrollLeft();var iScrollTop=dnn.dom.positioning.bodyScrollTop() +var iMaxTop=dnn.dom.positioning.viewPortHeight()+iScrollTop-oPDims.rot;var iMaxLeft=dnn.dom.positioning.viewPortWidth()+iScrollLeft-oPDims.rol;var iNewTop=oPDims.t;var iNewLeft=oPDims.l;var iStartTop=oPDims.t;var iStartLeft=oPDims.l;if(this.isNodeVertical(mNode)) +{iNewLeft=oPDims.l+oPDims.w;iStartTop=iMaxTop;} +else +{iNewTop=oPDims.t+oPDims.h;iStartLeft=iMaxLeft;} +if(iNewTop+oMDims.h>=iMaxTop) +{if(oPDims.rot+iStartTop-oMDims.h>iScrollTop) +iNewTop=iStartTop-oMDims.h;} +if(iNewLeft+oMDims.w>iMaxLeft) +{if(oPDims.rol+iStartLeft-oMDims.w>iScrollLeft) +iNewLeft=iStartLeft-oMDims.w;} +if(this.suborient==dnn.controls.orient.horizontal&&this.isNodeVertical(mNode)==false) +{var oRDims=new dnn.dom.positioning.dims(this.container);iNewLeft=oRDims.l;} +menu.style.top=iNewTop+'px';menu.style.left=iNewLeft+'px';},selectNode:function(mNode) +{var arg=new dnn.controls.DNNNodeEventArgs(mNode);this.invoke_handler('click',arg);if(arg.get_cancel()) +return;if(this.selMNode!=null) +{this.selMNode.selected=null;this.selMNode.update('selected');this.assignCss(this.selMNode);} +mNode.selected=true;mNode.update('selected');this.assignCss(mNode);this.selMNode=mNode;if(mNode.hasNodes||mNode.hasPendingNodes) +this.expandNode(mNode,true);if(mNode.selected) +{var sJS=this.defaultJS;if(mNode.js.length>0) +sJS=mNode.js;if(sJS.length>0) +{this.update(true);if(eval(sJS)==false) +return;} +if(mNode.clickAction==dnn.controls.action.postback) +{this.update(true);eval(this.postBack.replace('[NODEID]',mNode.id));} +else if(mNode.clickAction==dnn.controls.action.nav) +dnn.dom.navigate(mNode.getUrl(this),mNode.target.length>0?mNode.target:this.target);} +return true;},assignCss:function(mNode) +{var ctr=this.getChildControl(mNode.id,'ctr');var css=this.css;if(mNode.level>0&&this.cssChild.length>0) +css=this.cssChild;if(mNode.css.length>0) +css=mNode.css;if(mNode.hover) +css+=' hov '+(mNode.cssHover.length>0?mNode.cssHover:this.cssHover);if(mNode.selected) +css+=' sel '+(mNode.cssSel.length>0?mNode.cssSel:this.cssSel);if(mNode.breadcrumb) +css+=' bc';if(mNode.isBreak) +css+=' break';css+=' mi mi'+mNode.node.getNodePath();css+=' id'+mNode.id;if(mNode.level==0) +css+=' root';if(mNode.node.getNodeIndex()==0) +css+=' first';if(mNode.node.getNodeIndex()==mNode.node.parentNode().childNodeCount()-1) +css+=' last';if((mNode.node.getNodeIndex()==0)&&(mNode.node.getNodeIndex()==mNode.node.parentNode().childNodeCount()-1)) +css+=' firstlast';ctr.className=css;},update:function() +{dnn.setVar(this.ns+'_json',this.rootNode.getJSON());},_onsubmit:function() +{this.update(true);},_bodyClick:function() +{this.hideMenus();},focusHandler:function(e) +{var mNode=this.hoverMNode;if(mNode==null) +mNode=this.selMNode;if(mNode==null) +mNode=new dnn.controls.DNNMenuNode(this.nodes[0]);this.hoverNode(mNode);this.container.onfocus=null;},blurHandler:function(e) +{if(this.hoverMNode!=null) +this.hoverNode(null);dnn.cancelDelay(this.ns+'min');if(this.moutDelay>0) +dnn.doDelay(this.ns+'mout',this.moutDelay,this._hideMenusDelegate);else +this.hideMenus();},safariKeyHandler:function(e) +{if(e.charCode==KEY_RETURN) +{if(this.hoverMNode!=null&&this.hoverMNode.enabled) +this.selectNode(this.hoverMNode);return false;}},keyboardHandler:function(e) +{var code=e.keyCode;if(code==null) +code=e.charCode;if(code==KEY_RETURN) +{if(this.hoverMNode!=null&&this.hoverMNode.enabled) +this.selectNode(this.hoverMNode);return false;} +if(code==KEY_ESCAPE) +{this.blurHandler();return false;} +if(code>=KEY_LEFT_ARROW&&code<=KEY_DOWN_ARROW) +{var iDir=(code==KEY_UP_ARROW||code==KEY_LEFT_ARROW)?-1:1;var sAxis=(code==KEY_UP_ARROW||code==KEY_DOWN_ARROW)?'y':'x';var mNode=this.hoverMNode;var oNewMNode;if(mNode==null) +mNode=new dnn.controls.DNNMenuNode(this.nodes[0]);var bHor=!this.isNodeVertical(mNode);if((sAxis=='y'&&!bHor)||(bHor&&sAxis=='x')) +{this.hideMenus(new dnn.controls.DNNMenuNode(mNode.node.parentNode()));oNewMNode=this.__getNextNode(mNode,iDir);} +else +{if(iDir==-1) +{oNewMNode=new dnn.controls.DNNMenuNode(mNode.node.parentNode());if(oNewMNode.level==0&&this.orient==dnn.controls.orient.horizontal) +oNewMNode=this.__getNextNode(new dnn.controls.DNNMenuNode(mNode.node.parentNode()),iDir);this.hideMenus(oNewMNode);} +else if(iDir==1) +{if(mNode.hasNodes||mNode.hasPendingNodes) +{if(mNode.expanded!=true) +{this.expandNode(mNode);if(this.podInProgress==false) +oNewMNode=new dnn.controls.DNNMenuNode(mNode.node.nodes[0]);}} +else +{var node=mNode.node;while(node.parentNode().nodeName()!='root') +node=node.parentNode();oNewMNode=new dnn.controls.DNNMenuNode(node);oNewMNode=this.__getNextNode(oNewMNode,iDir);this.hideMenus(new dnn.controls.DNNMenuNode(oNewMNode.node.parentNode()));}}} +if(oNewMNode!=null&&oNewMNode.node.nodeName()!='root') +this.hoverNode(oNewMNode);return false;}},dispose:function() +{this._onsubmitDelegate=null;this._hideMenusDelegate=null;this._expandNodeDelegate=null;dnn.controls.DNNMenu.callBaseMethod(this,'dispose');},__getNextNode:function(mNode,iDir) +{var node;var parentNode=mNode.node.parentNode();var nodeIndex=mNode.node.getNodeIndex('id');if(nodeIndex+iDir<0) +node=parentNode.nodes[parentNode.childNodeCount()-1];else if(nodeIndex+iDir>parentNode.childNodeCount()-1) +node=parentNode.nodes[0];else +node=parentNode.nodes[nodeIndex+iDir];var oRetNode=new dnn.controls.DNNMenuNode(node);if(oRetNode.isBreak) +{nodeIndex+=iDir;if(nodeIndex+iDir<0) +node=parentNode.childNodes(parentNode.childNodeCount()-1);else if(nodeIndex+iDir>parentNode.childNodeCount()-1) +node=parentNode.childNodes(0);else +node=parentNode.childNodes(nodeIndex+iDir);return new dnn.controls.DNNMenuNode(node);} +else +return oRetNode;},callBackFail:function(result,ctx,req) +{var mNode=ctx;var menu=mNode.menu;menu.invoke_handler('callBackFail',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));},callBackStatus:function(result,ctx,req) +{var mNode=ctx;var menu=mNode.menu;menu.invoke_compatHandler('callBackStatus',result,ctx,req);},callBackSuccess:function(result,ctx,req) +{var mNode=ctx;var node=mNode.node;var menu=mNode.menu;menu.showWorkImage(mNode,false);var json=dnn.evalJSON("{"+result+"}");node.nodes=json.nodes;node.setupJSONNodes(node.rootNode(),node,node.nodes);var subMenu=menu.getChildControl(mNode.id,'sub');for(var i=0;i0) +dnn.doDelay(this.ns+'mout',this.moutDelay,dnn.createDelegate(this,this.hideMenus));else +this.hideMenus();},_nodeMOver:function(evt,element) +{var node=this._findEventNode(evt);if(node!=null) +{var mNode=new dnn.controls.DNNMenuNode(node);mNode.hover=true;this.assignCss(mNode);if(mNode.expanded!=true) +this.expandNode(mNode);evt.stopPropagation();} +this._menuMOver(evt,element);},_nodeMOut:function(evt,element) +{var node=this._findEventNode(evt);if(node!=null) +{var mNode=new dnn.controls.DNNMenuNode(node);this.assignCss(mNode);this._menuMOut(evt,element);evt.stopPropagation();}},getXml:function() +{return this.rootNode.getXml();},_findEventNode:function(evt) +{if(dnn.dom.isNonTextNode(evt.target)) +return this.rootNode.findNode(this.getChildControlBaseId(evt.target));},_loadNodes:function() +{if(dnn.getVar(this.ns+'_json').length>0){var json=dnn.evalJSON(dnn.getVar(this.ns+'_json'));}if(json) +{this.nodes=json.nodes;this.rootNode={};this.rootNode.nodes=this.nodes;this.rootNode.id=this.ns;this.rootNode=new dnn.controls.JSONNode(this.rootNode,'root',0);}},_setupKeyHandling:function() +{if(this.container.tabIndex<=0) +{this.container.tabIndex=0;this.addHandlers(this.container,{"keydown":this.keyboardHandler,"focus":this.focusHandler,"blur":this.blurHandler},this);} +else +{var txt=document.createElement('input');txt.type='text';txt.style.width=0;txt.style.height=0;txt.style.background='transparent';txt.style.border=0;txt.style.positioning='absolute';if(dnn.dom.browser.isType(dnn.dom.browser.Safari)) +{txt.style.width='1px';txt.style.height='1px';txt.style.left='-999em';this.addHandlers(txt,{"keydown":this.keyboardHandler},this);this.addHandlers(this.container.parentNode,{"keypress":this.safariKeyHandler},this);} +else +this.addHandlers(txt,{"keypress":this.keyboardHandler},this);this.addHandlers(txt,{"focus":this.focusHandler,"blur":this.blurHandler},this);this.container.parentNode.appendChild(txt);}}} +dnn.controls.DNNMenu.registerClass('dnn.controls.DNNMenu',dnn.controls.control);dnn.controls.DNNMenuBuilder=function(menu,mNode,ctr) +{this.menu=menu;this.mNode=mNode;this.isVertical=menu.isNodeVertical(mNode);this.container=ctr;this.row=null;this.subcont=null;this.alreadyRendered=false;} +dnn.controls.DNNMenuBuilder.prototype={appendChild:function(ctl,isNewCell) +{this.subcont.appendChild(ctl);},newCell:function(){},newCont:function() +{if(this.isVertical) +this.row=this.menu.createChildControl('div',this.mNode.id,'ctr');else +this.row=this.menu.createChildControl('span',this.mNode.id,'ctr');this.subcont=this.row;this.container.appendChild(this.subcont);},newRow:function() +{},createSubMenu:function() +{return this.menu.createChildControl('DIV',this.mNode.id,'sub');}} +dnn.controls.DNNMenuBuilder.registerClass('dnn.controls.DNNMenuBuilder');dnn.controls.DNNMenuTableBuilder=function(menu,node,cont) +{dnn.controls.DNNMenuTableBuilder.initializeBase(this,[menu,node,cont]);} +dnn.controls.DNNMenuTableBuilder.prototype={appendChild:function(ctl,isNewCell) +{if(isNewCell) +this.newCell();this.subcont.appendChild(ctl);},newCont:function() +{this.subcont=this.newCell();},newCell:function() +{var td=dnn.dom.createElement('td');this.row.appendChild(td);this.subcont=td;return td;},newRow:function() +{this.row=this.menu.createChildControl('tr',this.mNode.id,'ctr');var tb=dnn.dom.getByTagName('TBODY',this.container);tb[0].appendChild(this.row);},createSubMenu:function() +{var subMenu=this.menu.createChildControl('table',this.mNode.id,'sub');subMenu.border=0;subMenu.cellPadding=0;subMenu.cellSpacing=0;subMenu.appendChild(dnn.dom.createElement('tbody'));return subMenu;}} +dnn.controls.DNNMenuTableBuilder.registerClass('dnn.controls.DNNMenuTableBuilder',dnn.controls.DNNMenuBuilder);dnn.controls.DNNMenuListBuilder=function(menu,node,cont) +{dnn.controls.DNNMenuListBuilder.initializeBase(this,[menu,node,cont]);this.alreadyRendered=true;this.row=dnn.dom.getById(this.menu.getChildControlId(this.mNode.id,'ctr'),this.menu.container);this.menu.registerChildControl(this.row,this.mNode.id);this._setStyles(this.row);this.subcont=this.row;this.subMenu=dnn.dom.getById(this.menu.getChildControlId(this.mNode.id,'sub'),this.menu.container);if(this.subMenu) +{this.menu.registerChildControl(this.subMenu,this.mNode.id);this._setStyles(this.subMenu);}} +dnn.controls.DNNMenuListBuilder.prototype={appendChild:function(ctl,isNewCell){},newCont:function(){},createSubMenu:function() +{return this.subMenu;},_setStyles:function(ctl) +{if(this.menu.isNodeVertical(this.mNode)==false) +ctl.style.display='inline';ctl.style.listStyle='none';}} +dnn.controls.DNNMenuListBuilder.registerClass('dnn.controls.DNNMenuListBuilder',dnn.controls.DNNMenuBuilder);dnn.controls.DNNMenuNode=function(node) +{dnn.controls.DNNMenuNode.initializeBase(this,[node]);this._addAbbr({breadcrumb:'bcrumb',clickAction:'ca',imageIndex:'iIdx',urlIndex:'uIdx'});this.hover=false;this.expanded=null;this.selected=node.getAttribute('selected','0')=='1'?true:null;this.breadcrumb=node.getAttribute('bcrumb','0')=='1'?true:null;this.clickAction=node.getAttribute('ca',dnn.controls.action.postback);this.imageIndex=new Number(node.getAttribute('iIdx','-1'));this.urlIndex=new Number(node.getAttribute('uIdx','-1'));this.lhtml=node.getAttribute('lhtml','');this.rhtml=node.getAttribute('rhtml','');} +dnn.controls.DNNMenuNode.prototype={childNodes:function(iIndex) +{if(this.node.nodes(iIndex)!=null) +return new dnn.controls.DNNMenuNode(this.node.nodes(iIndex));},getUrl:function(menu) +{if(this.urlIndex>-1) +return menu.urlList[this.urlIndex]+this.url;else +return this.url;}} +dnn.controls.DNNMenuNode.registerClass('dnn.controls.DNNMenuNode',dnn.controls.DNNNode);Type.registerNamespace('dnn.controls');dnn.controls.menuRenderMode=function(){};dnn.controls.menuRenderMode.prototype={normal:0,notables:1,unorderdlist:2,downlevel:3} +dnn.controls.menuRenderMode.registerEnum("dnn.controls.menuRenderMode"); diff --git a/Website/js/dnn.controls.dnnmultistatebox.js b/Website/js/dnn.controls.dnnmultistatebox.js new file mode 100644 index 00000000000..dfde70d1f44 --- /dev/null +++ b/Website/js/dnn.controls.dnnmultistatebox.js @@ -0,0 +1,24 @@ + +Type.registerNamespace('dnn.controls');dnn.extend(dnn.controls,{initMultiStateBox:function(ctl) +{if(ctl) +{var ts=new dnn.controls.DNNMultiStateBox(ctl);ts.initialize();return ts;}}});dnn.controls.DNNMultiStateBox=function(o) +{dnn.controls.DNNMultiStateBox.initializeBase(this,[o]);this.css=this.getProp('css','');this.enabled=(this.getProp('enabled','1')=='1');this.imgPath=this.getProp('imgpath','images/');this.states=this.getProp('states','[]');this.states=Sys.Serialization.JavaScriptSerializer.deserialize(this.states);this.stateIndex=[] +for(var i=0;ithis.states.length-1) +index=0;this.set_Value(this.states[index].Key);} +this.container.checked=true;},keypress:function(sender,args) +{debugger;},dispose:function() +{dnn.controls.DNNMultiStateBox.callBaseMethod(this,'dispose');}} +dnn.controls.DNNMultiStateBox.registerClass('dnn.controls.DNNMultiStateBox',dnn.controls.control); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnnrichtext.js b/Website/js/dnn.controls.dnnrichtext.js new file mode 100644 index 00000000000..8565cb75577 --- /dev/null +++ b/Website/js/dnn.controls.dnnrichtext.js @@ -0,0 +1,26 @@ + +dnn.controls.DNNRichText=function(initFunc) +{this.supportsCE=(document.body.contentEditable!=null);this.text='';this.supportsMultiLine=true;this.document=null;this.control=null;this.initialized=false;this.isRichText=true;this.loaded=false;if(this.supportsCE) +{this.document=document;this.container=document.createElement('span');this.container.contentEditable=true;this.control=this.container;this.initialized=true;} +else +{this.container=document.createElement('iframe');this.container.src='';this.container.style.border='0';this.initFunc=initFunc;this._initDelegate=Function.createDelegate(this,this.initDocument);dnn.doDelay(this.container.id+'initEdit',10,this._initDelegate);}} +dnn.controls.DNNRichText.prototype={focus:function() +{if(this.supportsCE) +this.control.focus();else +this.container.contentWindow.focus();},execCommand:function(cmd,ui,vValue) +{this.document.execCommand(cmd,ui,vValue);},getText:function() +{return this.control.innerHTML;},setText:function(s) +{if(this.initialized) +this.control.innerHTML=s;else +this.text=s;},initDocument:function() +{if(this.container.contentDocument!=null) +{if(this.document==null) +{this.container.contentDocument.designMode='on';this.document=this.container.contentWindow.document;this.document.open();dnn.dom.addSafeHandler(this.container,'onload',this,'initDocument');this.document.write(''+this._getCSSLinks()+'');this.document.close();} +else if(this.control==null&&this.document.getElementById('__dnn_body')!=null) +{this.control=this.document.getElementById('__dnn_body');this.control.style.margin=0;this.control.tabIndex=0;this.initialized=true;this.setText(this.text);this.initFunc();}} +if(this.initialized==false) +dnn.doDelay(this.container.id+'initEdit',10,this._initDelegate);},_getCSSLinks:function() +{var arr=dnn.dom.getByTagName('link');var s='';for(var i=0;i';} +return s;}} +dnn.controls.DNNRichText.registerClass('dnn.controls.DNNRichText'); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnntabstrip.js b/Website/js/dnn.controls.dnntabstrip.js new file mode 100644 index 00000000000..0644c5a912e --- /dev/null +++ b/Website/js/dnn.controls.dnntabstrip.js @@ -0,0 +1,95 @@ + +Type.registerNamespace('dnn.controls');dnn.extend(dnn.controls,{initTabStrip:function(ctl) +{if(ctl&&dnn.controls.controls[ctl.id]==null) +{var ts=new dnn.controls.DNNTabStrip(ctl);ts.initialize();return ts;}}});dnn.controls.DNNTabStrip=function(o) +{dnn.controls.DNNTabStrip.initializeBase(this,[o]);this.contentContainer=$get(o.id+'_c');this.resultCtr=null;this.workImg=this.getProp('workImage','');;this.tabRenderMode=new Number(this.getProp('trm','0'));this.callBack=this.getProp('callback','');this.callBackStatFunc=this.getProp('callbackSF','');if(this.callBackStatFunc.length>0) +this.add_handler('callBackStatus',eval(this.callBackStatFunc));this.callbackType=this.getProp('cbtype','0');this.tabClickFunc=this.getProp('tabClickF','');if(this.tabClickFunc.length>0) +this.add_handler('tabClick',eval(this.tabClickFunc));this.selectedIndexFunc=this.getProp('selIdxF','');if(this.selectedIndexFunc.length>0) +this.add_handler('selectedIndexChanged',eval(this.selectedIndexFunc));this.lblCss=this.getProp('css','');this.lblCssSel=this.getProp('csssel',this.lblCss);this.lblCssHover=this.getProp('csshover','');this.lblCssDisabled=this.getProp('cssdisabled','');this.pendingLookupId=null;var json=dnn.evalJSON(dnn.getVar(this.ns+'_json'));if(json) +{this.tabData=json.tabs;this.tabLabelData=json.tablabels;} +this.tabs=[];this.tabIds=[];this.selectedIndex=-1;this.selectedTab=null;var clientId;var tabId;var tab;for(var i=0;i0) +{var oPointerFunc=eval(this[sFunc]);return oPointerFunc(evt,element)!=false;} +return true;},update:function() +{var ary=[];for(var i=0;i0) +{if(dnn.dom.scriptStatus(scripts[s].src)=='') +refScripts.push(scripts[s].src);} +else +inlineScripts.push(scripts[s].__text);} +dnn.dom.loadScripts(refScripts,inlineScripts,dnn.createDelegate(ts,ts.callBackScriptComplete));} +else +ts.callBackScriptComplete();},callBackScriptComplete:function() +{var tabId=this.pendingLookupId;this.pendingLookupId=null;this.showTab(tabId);},callBackFail:function(result,ctx,req) +{ctx.invoke_handler('callBackFail',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));},_getTabFromTabElement:function(element) +{},_getLabelData:function(index,prop,def) +{var data=this.tabLabelData[index];if(data[prop]!=null&&data[prop].length>0) +return data[prop];else +return def;},_getTabData:function(index,prop,def) +{var data=this.tabData[index];if(data[prop]!=null&&data[prop].length>0) +return data[prop];else +return def;}} +dnn.controls.DNNTabStrip.registerClass('dnn.controls.DNNTabStrip',dnn.controls.control);dnn.controls.DNNTab=function(strip,index,id,clientId) +{var tab=$get(clientId+'_l');if(tab!=null) +{this.tab=tab;this.container=$get(clientId);this.icon=$get(clientId+'_i');this.work=$get(clientId+'_w');this.rendered=(this.container!=null);this.selected=false;this.hovered=false;this.tabIndex=index;this.strip=strip;this.text=this.tab.innerHTML;this.clientId=clientId;this.tabId=id;this.css=this.strip._getLabelData(index,'css',strip.lblCss);this.cssSel=this.strip._getLabelData(index,'csssel',strip.lblCssSel);this.cssHover=this.strip._getLabelData(index,'csshover',strip.lblCssHover);this.cssDisabled=this.strip._getLabelData(index,'cssdisabled',strip.lblCssDisabled);this.postMode=this.strip._getTabData(index,'postmode',null);this.enabled=(this.strip._getTabData(index,'enabled',"1")=="1");this.callbackType=this.strip._getTabData(index,'cbtype',strip.callbackType);if(this.postMode) +this.postMode='\''+this.postMode+'\'';}} +dnn.controls.DNNTab.prototype={serialize:function() +{return this.tabId+'='+((this.rendered?1:0)+(this.selected?2:0)+(this.enabled?4:0));},showWork:function(show) +{if(this.work!=null) +{if(show) +{this.work.style.display='';if(this.icon!=null) +this.icon.style.display='none';} +else +{this.work.style.display='none';if(this.icon!=null) +this.icon.style.display='';}}},enable:function() +{this.enabled=true;},disable:function() +{this.enabled=false;},assignCss:function() +{var sCss='';if(this.enabled==false&&this.cssDisabled.length>0) +sCss=this.cssDisabled;else +{if(this.hovered&&this.cssHover.length>0) +sCss=this.cssHover;else +sCss=(this.selected?this.cssSel:this.css);} +this.tab.className=sCss;}} +dnn.controls.DNNTab.registerClass('dnn.controls.DNNTab'); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnntextsuggest.js b/Website/js/dnn.controls.dnntextsuggest.js new file mode 100644 index 00000000000..4790060120c --- /dev/null +++ b/Website/js/dnn.controls.dnntextsuggest.js @@ -0,0 +1,126 @@ + +Type.registerNamespace('dnn.controls');dnn.extend(dnn.controls,{initTextSuggest:function(ctl) +{if(ctl) +{var ts=new dnn.controls.DNNTextSuggest(ctl);ts.initialize();return ts;}}});dnn.controls.DNNTextSuggest=function(o) +{dnn.controls.DNNTextSuggest.initializeBase(this,[o]);this.resultCtr=null;this.tscss=this.getProp('tscss','');this.css=this.getProp('css','');this.cssChild=this.getProp('csschild','');this.cssHover=this.getProp('csshover','');this.cssSel=this.getProp('csssel','');this.sysImgPath=this.getProp('sysimgpath','');this.workImg='dnnanim.gif';this.target=this.getProp('target','');this.defaultJS=this.getProp('js','');this.postBack=this.getProp('postback','');this.callBack=this.getProp('callback','');this.callBackStatFunc=this.getProp('callbackSF','');if(this.callBackStatFunc.length>0) +this.add_handler('callBackStatus',eval(this.callBackStatFunc));this.rootNode=null;this.selNode=null;this.selIndex=-1;this.lookupDelay=this.getProp('ludelay','500');this.lostFocusDelay=this.getProp('lfdelay','500');this.inAnimObj=null;this.inAnimType=null;this.prevText='';this.addHandlers(o,{'keyup':this.keyUp,'keypress':this.keyPress,'blur':this.onblur,'focus':this.onfocus},this);o.setAttribute('autocomplete','off');this.delimiter=this.getProp('del','');this.idtoken=this.getProp('idtok','');this.maxRows=new Number(this.getProp('maxRows','10'));if(this.maxRows==0) +this.maxRows=9999;this.minChar=new Number(this.getProp('minChar','1'));this.caseSensitive=this.getProp('casesens','0')=='1';this.prevLookupText='';this.prevLookupOffset=0;this._blurHideDelegate=dnn.createDelegate(this,this.blurHide);this._doLookupDelegate=dnn.createDelegate(this,this.doLookup);} +dnn.controls.DNNTextSuggest.prototype={keyPress:function(e) +{if(e.charCode==KEY_RETURN) +{e.stopPropagation();e.preventDefault();return false;}},onblur:function(e) +{dnn.doDelay(this.ns+'ob',this.lostFocusDelay,this._blurHideDelegate);},onfocus:function(e) +{dnn.cancelDelay(this.ns+'ob');},blurHide:function(e) +{this.clearResults(true);},keyUp:function(e) +{this.prevText=this.container.value;if(e.keyCode==KEY_UP_ARROW) +this.setNodeIndex(this.selIndex-1);else if(e.keyCode==KEY_DOWN_ARROW) +this.setNodeIndex(this.selIndex+1);else if(e.keyCode==KEY_RETURN) +{if(this.selIndex>-1) +{this.selectNode(this.getNodeByIndex(this.selIndex));this.clearResults(true);}} +else if(e.keyCode==KEY_ESCAPE) +this.clearResults(true);else +{dnn.cancelDelay(this.ns+'kd');dnn.doDelay(this.ns+'kd',this.lookupDelay,this._doLookupDelegate);}},nodeMOver:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{var tsNode=new dnn.controls.DNNTextSuggestNode(node);tsNode.hover=true;this.assignCss(tsNode);}},nodeMOut:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{var tsNode=new dnn.controls.DNNTextSuggestNode(node);tsNode.hover=false;this.assignCss(tsNode);}},nodeClick:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{var tsNode=new dnn.controls.DNNTextSuggestNode(node);this.selectNode(tsNode);this.clearResults(true);}},getTextOffset:function() +{var offset=0;if(this.delimiter.length>0) +{var ary=this.container.value.split(this.delimiter);var pos=dnn.dom.cursorPos(this.container);var len=0;for(offset=0;offsetpos) +break;}} +return offset;},setText:function(s,id) +{if(this.idtoken.length>0) +s+=' '+this.idtoken.replace('~',id);if(this.delimiter.length>0) +{var ary=this.container.value.split(this.delimiter);ary[this.getTextOffset()]=s;this.container.value=ary.join(this.delimiter);if(this.container.value.lastIndexOf(this.delimiter)!=this.container.value.length-1) +this.container.value+=this.delimiter;} +else +this.container.value=s;this.prevText=this.container.value;},getText:function() +{if(this.delimiter.length>0&&this.container.value.indexOf(this.delimiter)>-1) +{var ary=this.container.value.split(this.delimiter);return ary[this.getTextOffset()];} +else +return this.container.value;},formatText:function(s) +{if(this.caseSensitive) +return s;else +return s.toLowerCase();},highlightNode:function(index,bHighlight) +{if(index>-1) +{var tsNode=this.getNodeByIndex(index);tsNode.hover=bHighlight;this.assignCss(tsNode);}},getNodeByIndex:function(index) +{var element=this.resultCtr.childNodes[index];if(element) +{var node=this.rootNode.findNode(this.getChildControlBaseId(element));if(node) +return new dnn.controls.DNNTextSuggestNode(node);}},setNodeIndex:function(index) +{if(index>-1&&index0) +js=this.defaultJS;if(tsNode.js.length>0) +js=tsNode.js;if(js.length>0) +{if(eval(js)==false) +return;} +if(tsNode.clickAction==null||tsNode.clickAction==dnn.controls.action.postback) +eval(this.postBack.replace('[TEXT]',this.getText()));else if(tsNode.clickAction==dnn.controls.action.nav) +dnn.dom.navigate(tsNode.url,tsNode.target.length>0?tsNode.target:this.target);} +return true;},positionMenu:function() +{var dims=new dnn.dom.positioning.dims(this.container);this.resultCtr.style.left=dims.l-dnn.dom.positioning.bodyScrollLeft();this.resultCtr.style.top=dims.t+dims.h;},showResults:function() +{if(this.resultCtr) +this.resultCtr.style.display='';},hideResults:function() +{if(this.resultCtr) +this.resultCtr.style.display='none';dnn.dom.positioning.placeOnTop(this.resultCtr,false,this.sysImgPath+'spacer.gif');},clearResults:function(hide) +{if(this.resultCtr!=null) +this.resultCtr.innerHTML='';this.selIndex=-1;this.selNode=null;if(hide) +this.hideResults();},clear:function() +{this.clearResults();this.setText('','');},doLookup:function() +{if(this.getText().length>=this.minChar) +{if(this.needsLookup()) +{this.prevLookupOffset=this.getTextOffset();this.prevLookupText=this.formatText(this.getText());eval(this.callBack.replace('[TEXT]',this.prevLookupText));} +else +this.renderResults(null);} +else +this.clearResults();},needsLookup:function() +{if(this.rootNode==null) +return true;if(this.prevLookupOffset!=this.getTextOffset()||this.rootNode==null) +return true;if(this.formatText(this.getText()).indexOf(this.prevLookupText)==0) +{if(this.rootNode.childNodeCount()0) +newCtr.title=tsNode.toolTip;ctr.appendChild(newCtr);this.assignCss(tsNode);}},renderText:function(tsNode) +{var span=this.createChildControl('SPAN',tsNode.id,'t');span.innerHTML=tsNode.text;span.style.cursor='pointer';return span;},assignCss:function(tsNode) +{var oCtr=this.getChildControl(tsNode.id,'ctr');var nodeCss=this.css;if(tsNode.css.length>0) +nodeCss=tsNode.css;if(tsNode.hover) +nodeCss+=' '+(tsNode.cssHover.length>0?tsNode.cssHover:this.cssHover);if(tsNode.selected) +nodeCss+=' '+(tsNode.cssSel.length>0?tsNode.cssSel:this.cssSel);oCtr.className=nodeCss;},callBackStatus:function(result,ctx,req) +{var ts=ctx;ts.invoke_compatHandler('callBackStatus',result,ctx,req);},callBackSuccess:function(result,ctx,req) +{var ts=ctx;ts.invoke_compatHandler('callBackStatus',result,ctx,req);ts.invoke_handler('callBackSuccess',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));ts.renderResults(result);},callBackFail:function(result,ctx,req) +{var ts=ctx;ts.invoke_handler('callBackFail',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));},_findEventNode:function(evt) +{return this.rootNode.findNode(this.getChildControlBaseId(evt.target));},dispose:function() +{this._blurHideDelegate=null;this._doLookupDelegate=null;dnn.controls.DNNTextSuggest.callBaseMethod(this,'dispose');}} +dnn.controls.DNNTextSuggest.registerClass('dnn.controls.DNNTextSuggest',dnn.controls.control);dnn.controls.DNNTextSuggestNode=function(node) +{dnn.controls.DNNTextSuggestNode.initializeBase(this,[node]);this.hover=false;this.selected=node.getAttribute('selected','0')=='1'?true:null;this.clickAction=node.getAttribute('ca',dnn.controls.action.none);} +dnn.controls.DNNTextSuggestNode.prototype={childNodes:function(index) +{if(this.node.childNodes[index]!=null) +return new dnn.controls.DNNTextSuggestNode(this.node.childNodes[index]);}} +dnn.controls.DNNTextSuggestNode.registerClass('dnn.controls.DNNTextSuggestNode',dnn.controls.DNNNode); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnntoolbar.js b/Website/js/dnn.controls.dnntoolbar.js new file mode 100644 index 00000000000..17d875c024a --- /dev/null +++ b/Website/js/dnn.controls.dnntoolbar.js @@ -0,0 +1 @@ +Type.registerNamespace("dnn.controls");dnn.controls.DNNToolBar=function(b,a){this.ctr=document.createElement("div");this.ctr.id=b+"_tb";dnn.controls.DNNToolBar.initializeBase(this,[this.ctr]);this.initialize(a);this.css=null;this.cssButton=null;this.cssButtonHover=null;this.moutDelay=null;this.buttons=[];this.relatedCtl=null;this.ctr.style.position="relative";this.ctl=document.createElement("div");this.ctr.appendChild(this.ctl);this.ctl.style.display="none";this.moutDelay=1000;this._hideDelegate=dnn.createDelegate(this,this.hide);this.actionHandler=null};dnn.controls.DNNToolBar.prototype={loadDefinition:function(c,f,k,h,b,a){var e=dnn.controls.toolbars[f+":"+c];if(e==null){e=dnn.controls.toolbars[f+"$"+c]}if(e==null){e=dnn.controls.toolbars[c]}if(e){this.relatedCtl=k;this.css=e.css;this.cssButton=e.cssb;this.cssButtonHover=e.cssbh;this.actionHandler=a;for(var g=0;g0){dnn.doDelay(this.ns+"mout",this.moutDelay,this._hideDelegate)}},hide:function(){this.ctl.style.display="none";this.ctr.className=this.ctr.className.replace(" visible","")},buttonClick:function(c){var b=this.tb;var a=new dnn.controls.DNNToolBarEventArgs(this);b.invoke_handler("click",a);if(a.get_cancel()){return}this.click()},buttonMouseOver:function(a){this.tb.show(false);this.hover()},buttonMouseOut:function(a){this.tb.beginHide();this.unhover()},dispose:function(){this._hideDelegate=null;this.actionHandler=null;dnn.controls.DNNToolBar.callBaseMethod(this,"dispose")}};dnn.controls.DNNToolBar.registerClass("dnn.controls.DNNToolBar",dnn.controls.control);dnn.controls.DNNToolBarButton=function(j,d,h,i,f,k,a,c,b,e,g){this.ctl=null;this.key=j;this.clickAction=d;this.tb=g;this.css=h;this.hoverCss=i;this.img=f;this.tooltip=a;this.txt=k;this.js=c;this.url=b;this.visible=e};dnn.controls.DNNToolBarButton.prototype={render:function(){if(!this.ctl){var d=this.tb;this.ctl=d.createChildControl("div",this.key,"");this.ctl.className=this.css;if(this.tooltip){this.ctl.title=this.tooltip}if(this.img){var b=document.createElement("img");b.src=this.img;this.ctl.appendChild(b)}if(this.txt){var c=document.createElement("span");c.innerHTML=this.txt;this.ctl.appendChild(c)}var a="mousedown";d.addHandlers(this.ctl,d.getDynamicEventObject(a,d.buttonClick),this);d.addHandlers(this.ctl,{mouseover:d.buttonMouseOver,mouseout:d.buttonMouseOut},this)}},hover:function(){if(this.hoverCss){this.ctl.className=this.css+" "+this.hoverCss}},unhover:function(){if(this.hoverCss){this.ctl.className=this.css}},click:function(){if(this.clickAction=="js"){eval(this.js)}else{if(this.clickAction=="navigate"){dnn.dom.navigate(this.url)}else{if(this.tb.actionHandler!=null){this.tb.actionHandler(this,this.tb.relatedCtl)}}}},getVal:function(a,b){return(a?a:b)}};dnn.controls.DNNToolBarButton.registerClass("dnn.controls.DNNToolBarButton"); \ No newline at end of file diff --git a/Website/js/dnn.controls.dnntoolbarstub.js b/Website/js/dnn.controls.dnntoolbarstub.js new file mode 100644 index 00000000000..c21022c633c --- /dev/null +++ b/Website/js/dnn.controls.dnntoolbarstub.js @@ -0,0 +1,6 @@ + +function __dnn_toolbarHandler(toolBarId,controlId,behaviorId,namespacePrefix,loadHandler,eventName,hideEventName) +{var status=dnn.dom.scriptStatus('dnn.controls.dnntoolbar.js');if(status=='complete') +{var tb=new dnn.controls.DNNToolBar(controlId,behaviorId);var ctl=$get(controlId);tb.loadDefinition(toolBarId,namespacePrefix,ctl,ctl.parentNode,ctl,loadHandler);dnn.dom.addSafeHandler(ctl,eventName,tb,'show');dnn.dom.addSafeHandler(ctl,hideEventName,tb,'beginHide');tb.show();} +else if(status=='') +dnn.dom.loadScript(dnn.dom.getScriptPath()+'dnn.controls.dnntoolbar.js','',function(){__dnn_toolbarHandler(toolBarId,controlId,behaviorId,namespacePrefix,loadHandler,eventName,hideEventName)});} \ No newline at end of file diff --git a/Website/js/dnn.controls.dnntree.js b/Website/js/dnn.controls.dnntree.js new file mode 100644 index 00000000000..9277d943b7f --- /dev/null +++ b/Website/js/dnn.controls.dnntree.js @@ -0,0 +1,172 @@ + +Type.registerNamespace('dnn.controls');dnn.extend(dnn.controls,{initTree:function(ctl) +{if(ctl) +{var tree=new dnn.controls.DNNTree(ctl);tree.initialize();return tree;}}});dnn.controls.DNNTree=function(o) +{dnn.controls.DNNTree.initializeBase(this,[o]);this.rootNode=null;this.nodes=[];this._loadNodes();this.hoverTreeNode=null;this.selTreeNode=null;this.css=this.getProp('css','');this.cssChild=this.getProp('csschild','');this.cssHover=this.getProp('csshover','');this.cssSel=this.getProp('csssel','');this.cssIcon=this.getProp('cssicon','');this.sysImgPath=this.getProp('sysimgpath','images/');this.imageList=this.getProp('imagelist','').split(',');this.expandImg=this.getProp('expimg','');this.workImg=this.getProp('workimg','dnnanim.gif');this.animf=new Number(this.getProp('animf','5'));this.collapseImg=this.getProp('colimg','');this.indentWidth=new Number(this.getProp('indentw','10'));if(this.indentWidth==0) +this.indentWidth=10;this.checkBoxes=this.getProp('checkboxes','0')=='1';this.checkBoxMode=new Number(this.getProp('cbm','0'));this.target=this.getProp('target','');this.defaultJS=this.getProp('js','');this.postBack=this.getProp('postback','');this.callBack=this.getProp('callback','');this.callBackStatFunc=this.getProp('callbackSF','');if(this.callBackStatFunc.length>0) +this.add_handler('callBackStatus',eval(this.callBackStatFunc));this.expImgWidth=new Number(this.getProp('expcolimgw','12'));kbCtl=this.container;if(this.container.tabIndex<=0) +this.container.tabIndex=0;else +{kbCtl=document.createElement('input');kbCtl.type='text';kbCtl.style.width=0;kbCtl.style.height=0;kbCtl.style.background='transparent';kbCtl.style.border=0;kbCtl.style.positioning='absolute';kbCtl.style.left='-999em';this.container.parentNode.appendChild(kbCtl);} +this.addHandlers(kbCtl,{"keydown":this.keydownHandler,"focus":this.focusHandler},this);this._onsubmitDelegate=Function.createDelegate(this,this._onsubmit);dnn.controls.submitComp.add_handler(this._onsubmitDelegate);} +dnn.controls.DNNTree.prototype={initialize:function() +{dnn.controls.DNNTree.callBaseMethod(this,'initialize');this.generateTreeHTML();},focusHandler:function(e) +{var tNode=this.hoverTreeNode;if(tNode==null) +tNode=new dnn.controls.DNNTreeNode(this.rootNode.childNodes(0));this.hoverNode(tNode);this.container.onfocus=null;},keydownHandler:function(e) +{var dir=0;var axis='';if(e.keyCode==KEY_UP_ARROW) +{dir=-1;axis='y';} +if(e.keyCode==KEY_DOWN_ARROW) +{dir=1;axis='y';} +if(e.keyCode==KEY_LEFT_ARROW) +{dir=-1;axis='x';} +if(e.keyCode==KEY_RIGHT_ARROW) +{dir=1;axis='x';} +if(dir!=0) +{var tNode=this.hoverTreeNode;var node;if(tNode==null) +tNode=new dnn.controls.DNNTreeNode(this.rootNode.childNodes(0));if(axis=='x') +{if(dir==-1) +{if(tNode.hasNodes&&tNode.expanded) +this.collapseNode(tNode);else +node=tNode.node.parentNode();} +if(dir==1) +{if(tNode.hasNodes||tNode.hasPendingNodes) +{if(tNode.expanded!=true) +this.expandNode(tNode);else +node=tNode.node.childNodes(0);}}} +else if(axis=='y') +{var iNodeIndex=tNode.node.getNodeIndex('id');var parentNode=tNode.node.parentNode();if(tNode.hasNodes&&tNode.expanded&&dir>0) +node=tNode.node.childNodes(0);else if(iNodeIndex+dir<0) +node=parentNode;else if(iNodeIndex+dir=tempParent.parentNode().childNodeCount()) +{tempParent=tempParent.parentNode();iNodeIndex=tempParent.getNodeIndex('id');}} +if(tempParent.nodeName()!='root') +node=tempParent.parentNode().childNodes(iNodeIndex+1);}} +if(node!=null&&node.nodeName()!='root') +this.hoverNode(new dnn.controls.DNNTreeNode(node));return false;} +if(e.keyCode==KEY_RETURN&&this.hoverTreeNode!=null) +{this.selectNode(this.hoverTreeNode);return false;}},hoverNode:function(tNode) +{if(this.hoverTreeNode!=null) +{this.hoverTreeNode.hover=false;this.assignCss(this.hoverTreeNode);} +tNode.hover=true;this.assignCss(tNode);this.hoverTreeNode=tNode;},getXml:function() +{return this.rootNode.getXml();},expandNode:function(tNode) +{var ctr=this.getChildControl(tNode.id,'pctr');var expandCol=this.getChildControl(tNode.id,'expcol');expandCol.src=this.expandImg;tNode.expanded=true;tNode.update();this.update();if(tNode.hasPendingNodes) +{var sXml=tNode.node.getXml();tNode.tree=this;if(this.workImg!=null) +{var icon=this.getChildControl(tNode.id,'icn');if(icon) +icon.src=this.sysImgPath+this.workImg;} +if(this.callBack.indexOf('[NODEXML]')>-1) +eval(this.callBack.replace('[NODEXML]',dnn.escapeForEval(sXml)));else +eval(this.callBack.replace('[NODEID]',tNode.id));tNode.hasPendingNodes=false;tNode.hasNodes=true;this.hoverTreeNode=tNode;} +else +{dnn.dom.expandElement(ctr,this.animf);} +return true;},collapseNode:function(tNode) +{var ctr=this.getChildControl(tNode.id,'pctr');var expandCol=this.getChildControl(tNode.id,'expcol');dnn.dom.collapseElement(ctr,this.animf);expandCol.src=this.collapseImg;tNode.expanded=null;tNode.update();this.update();return true;},selectNode:function(tNode) +{var arg=new dnn.controls.DNNNodeEventArgs(tNode);this.invoke_handler('click',arg);if(arg.get_cancel()) +return;if(this.selTreeNode!=null&&this.checkBoxes==false) +{this.selTreeNode.selected=null;this.assignCss(this.selTreeNode);this.selTreeNode.update('selected');} +if(tNode.selected) +{tNode.selected=null;this.assignCss(tNode);} +else +{tNode.selected=true;this.hoverTreeNode=tNode;this.assignCss(tNode);} +tNode.update('selected');this.selTreeNode=tNode;this.update();var chk=this.getChildControl(tNode.id,'chk');if(chk!=null) +chk.checked=tNode.selected;if(tNode.selected) +{var js='';if(this.defaultJS.length>0) +js=this.defaultJS;if(tNode.js.length>0) +js=tNode.js;if(js.length>0) +{if(eval(js)==false) +return;} +if(tNode.clickAction==null||tNode.clickAction==dnn.controls.action.postback) +eval(this.postBack.replace('[NODEID]',tNode.id));else if(tNode.clickAction==dnn.controls.action.nav) +dnn.dom.navigate(tNode.url,tNode.target.length>0?tNode.target:this.target);else if(tNode.clickAction==dnn.controls.action.expand) +{if(tNode.hasNodes||tNode.hasPendingNodes) +{if(tNode.expanded) +this.collapseNode(tNode);else +this.expandNode(tNode);}}} +return true;},selectAllChildren:function(tNode) +{var childTNode;for(var i=0;i0&&this.cssChild.length>0) +sNodeCss=this.cssChild;if(tNode.css.length>0) +sNodeCss=tNode.css;if(tNode.hover) +sNodeCss+=' '+(tNode.cssHover.length>0?tNode.cssHover:this.cssHover);if(tNode.selected) +sNodeCss+=' '+(tNode.cssSel.length>0?tNode.cssSel:this.cssSel);oText.className=sNodeCss;},update:function(force) +{if(force) +{if(this.selTreeNode) +dnn.setVar(this.ns + ':selected', this.selTreeNode.id); dnn.setVar(this.ns + '_json', dnn.decodeHTML(this.rootNode.getJSON())); +} +return true;},_onsubmit:function() +{this.update(true);},callBackStatus:function(result,ctx,req) +{var tNode=ctx;var tree=tNode.tree;tree.invoke_compatHandler('callBackStatus',result,ctx,req);},callBackSuccess:function(result,ctx,req) +{var tNode=ctx;var tree=tNode.tree;var parent=tNode.node;;var json=dnn.evalJSON("{"+result+"}");parent.nodes=json.nodes;parent.setupJSONNodes(parent.rootNode(),parent,parent.nodes);if(tree.workImg!=null) +{var icon=tree.getChildControl(tNode.id,'icn');if(tNode.image!='') +icon.src=tNode.image;else if(tNode.imageIndex>-1) +icon.src=tree.imageList[tNode.imageIndex];} +var ctr=tree.getChildControl(tNode.id,'pctr');tree.renderNode(tNode.node,ctr,true);tree.update();tree.expandNode(new dnn.controls.DNNTreeNode(tNode.node));tree.invoke_compatHandler('callBackStatus',result,ctx,req);tree.invoke_handler('callBackSuccess',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));},callBackFail:function(result,ctx,req) +{var tNode=ctx;var tree=tNode.tree;tree.invoke_handler('callBackFail',new dnn.controls.DNNCallbackEventArgs(result,ctx,req));},nodeExpColClick:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{var tNode=new dnn.controls.DNNTreeNode(node);var ctr=this.getChildControl(tNode.id,'pctr');if(tNode.expanded) +this.collapseNode(tNode);else +this.expandNode(tNode);}},nodeCheck:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{var tNode=new dnn.controls.DNNTreeNode(node);if(this.checkBoxMode==2&&this.selTreeNode!=null) +this.selectNode(this.selTreeNode);this.selectNode(tNode);if(this.checkBoxMode==1) +this.selectAllChildren(tNode);}},nodeTextClick:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +{this.selectNode(new dnn.controls.DNNTreeNode(node));}},nodeTextMOver:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +this.hoverNode(new dnn.controls.DNNTreeNode(node));},nodeTextMOut:function(evt) +{var node=this._findEventNode(evt);if(node!=null) +this.assignCss(new dnn.controls.DNNTreeNode(node));},dispose:function() +{this._onsubmitDelegate=null;dnn.controls.DNNTree.callBaseMethod(this,'dispose');},generateTreeHTML:function() +{this.renderNode(null,this.container);},renderNode:function(node,oCont,bExists) +{var oChildCont=oCont;var tNode;if(bExists!=true) +{if(node!=null) +{tNode=new dnn.controls.DNNTreeNode(node);var oNewContainer;oNewContainer=this.createChildControl('DIV',tNode.id,'ctr');if(document.getElementById(oNewContainer.id)==null){oNewContainer.appendChild(this.renderSpacer((this.indentWidth*tNode.level)+((tNode.hasNodes||tNode.hasPendingNodes)?0:this.expImgWidth)));if(tNode.hasNodes||tNode.hasPendingNodes) +oNewContainer.appendChild(this.renderExpCol(tNode));if(this.checkBoxes) +oNewContainer.appendChild(this.renderCheckbox(tNode));var oIconCont=this.renderIconCont(tNode);oNewContainer.appendChild(oIconCont);if(tNode.imageIndex>-1||tNode.image!='') +{oIconCont.appendChild(this.renderIcon(tNode));} +oNewContainer.appendChild(this.renderText(tNode));oCont.appendChild(oNewContainer);this.assignCss(tNode);}} +else +node=this.rootNode;if(tNode!=null&&(tNode.hasNodes||tNode.hasPendingNodes)) +{oChildCont=this.createChildControl('DIV',tNode.id,'pctr');if(tNode.expanded!=true) +oChildCont.style.display='none';oCont.appendChild(oChildCont);}} +for(var i=0;i0) +span.className=tNode.cssIcon;else if(this.cssIcon.length>0) +span.className=this.cssIcon;return span;},renderIcon:function(tNode) +{var img=this.createChildControl('IMG',tNode.id,'icn');if(tNode.image!='') +img.src=tNode.image;else if(tNode.imageIndex>-1) +img.src=this.imageList[tNode.imageIndex];return img;},renderCheckbox:function(tNode) +{var chk=this.createChildControl('INPUT',tNode.id,'chk');chk.type='checkbox';chk.defaultChecked=tNode.selected;chk.checked=tNode.selected;this.addHandlers(chk,{"click":this.nodeCheck},this);return chk;},renderSpacer:function(width) +{var img=document.createElement('IMG');img.src=this.sysImgPath+'spacer.gif';img.width=width;img.height=1;img.style.width=width+'px';img.style.height='1px';return img;},renderText:function(tNode) +{var span=this.createChildControl('SPAN',tNode.id,'t');span.innerHTML=tNode.text;span.style.cursor='pointer';if(tNode.toolTip.length>0) +span.title=tNode.toolTip;if(tNode.enabled||tNode.clickAction==dnn.controls.action.expand) +{if(this.checkBoxes) +this.addHandlers(span,{"click":this.nodeCheck},this);else +this.addHandlers(span,{"click":this.nodeTextClick},this);if(this.cssHover.length>0) +{this.addHandlers(span,{"mouseover":this.nodeTextMOver,"mouseout":this.nodeTextMOut},this);}} +if(tNode.selected) +{this.selTreeNode=tNode;this.hoverTreeNode=tNode;} +return span;},_findEventNode:function(evt) +{return this.rootNode.findNode(this.getChildControlBaseId(evt.target));},_loadNodes:function() +{var json=dnn.evalJSON(dnn.getVar(this.ns+'_json'));if(json) +{this.nodes=json.nodes;this.rootNode={};this.rootNode.nodes=this.nodes;this.rootNode.id=this.ns;this.rootNode=new dnn.controls.JSONNode(this.rootNode,'root',0);}}} +dnn.controls.DNNTree.registerClass('dnn.controls.DNNTree',dnn.controls.control);dnn.controls.DNNTreeNode=function(node) +{dnn.controls.DNNTreeNode.initializeBase(this,[node]);this.hover=false;this.expanded=node.getAttribute('expanded','0')=='1'?true:null;this.selected=node.getAttribute('selected','0')=='1'?true:null;this.clickAction=node.getAttribute('ca',dnn.controls.action.postback);this.imageIndex=new Number(node.getAttribute('imgIdx','-1'));} +dnn.controls.DNNTreeNode.prototype={childNodes:function(iIndex) +{if(this.node.childNodes(iIndex)!=null) +return new dnn.controls.DNNTreeNode(this.node.childNodes(iIndex));}} +dnn.controls.DNNTreeNode.registerClass('dnn.controls.DNNTreeNode',dnn.controls.DNNNode);var DT_ACTION_POSTBACK=0;var DT_ACTION_EXPAND=1;var DT_ACTION_NONE=2;var DT_ACTION_NAV=3;function __dt_DNNTreeNode(ctl) +{var node=dnn.controls.controls[ctl.ns].rootNode.findNode(ctl.nodeid);if(node!=null) +{var tNode=new dnn.controls.DNNTreeNode(node);this.ctl=ctl;this.id=ctl.id;this.key=tNode.key;this.nodeID=ctl.nodeid;this.text=tNode.text;this.serverName=ctl.name;}} \ No newline at end of file diff --git a/Website/js/dnn.controls.js b/Website/js/dnn.controls.js new file mode 100644 index 00000000000..0426c7faecb --- /dev/null +++ b/Website/js/dnn.controls.js @@ -0,0 +1,137 @@ + +Type.registerNamespace('dnn.controls');dnn.controls.orient=function(){};dnn.controls.orient.prototype={horizontal:0,vertical:1} +dnn.controls.orient.registerEnum("dnn.controls.orient");dnn.controls.action=function(){};dnn.controls.action.prototype={postback:0,expand:1,none:2,nav:3} +dnn.controls.action.registerEnum("dnn.controls.action");dnn.extend(dnn.controls,{version:new Number('02.03'),pns:'dnn',ns:'controls',isLoaded:false,controls:[],toolbars:[],_behaviorIDs:[],find:function(behaviorID) +{return this.controls[this._behaviorIDs[behaviorID]];}});dnn.controls.control=function(ctl) +{dnn.controls.control.initializeBase(this,[ctl]);dnn.controls.controls[ctl.id]=this;this.behaviorID='';this.ns=ctl.id;this.container=ctl;this._props=null;this._childControls=[];this._childControlIDs=[];this._handlerControls=[];} +dnn.controls.control.prototype={initialize:function(behaviorID) +{dnn.controls.control.callBaseMethod(this,'initialize');if(behaviorID) +this.behaviorID=behaviorID;else +this.behaviorID=this.getProp('bid','');if(this.behaviorID.length>0) +dnn.controls._behaviorIDs[this.behaviorID]=this.ns;},getProp:function(name,defVal) +{if(this._props==null) +{this._props={};var p=dnn.getVar(this.ns+'_p');if(p) +{this._props=dnn.evalJSON(p);if(dnn.dom.browser.isType(dnn.dom.browser.Mozilla)==false) +dnn.setVar(this.ns+'_p','');}} +var val=this._props[name];if(val==undefined||val=='') +return defVal;else +return val;},addHandlers:function(element,events,handlerOwner) +{this._handlerControls.push(element);$addHandlers(element,events,handlerOwner);},getChildControlId:function(id,prefix) +{return this.ns+prefix+id;},createChildControl:function(tag,id,prefix) +{var ctl=dnn.dom.createElement(tag);ctl.ns=this.ns;ctl.id=this.getChildControlId(id,prefix);this.registerChildControl(ctl,id);return ctl;},registerChildControl:function(ctl,id) +{this._childControlIDs[ctl.id]=id;this._childControls[ctl.id]=ctl;},getChildControl:function(id,prefix) +{var newId=this.ns+prefix+id;if(this._childControls[newId]!=null) +return this._childControls[newId];else +return $get(newId);},getChildControlBaseId:function(ctl) +{while(ctl.id.length==0&&ctl.parentNode) +{ctl=ctl.parentNode;} +return this._childControlIDs[ctl.id];},add_handler:function(name,handler) +{this.get_events().addHandler(name,handler);},remove_handler:function(name,handler) +{this.get_events().removeHandler(name,handler);},invoke_handler:function(name,args) +{var h=this.get_events().getHandler(name);if(args==null) +args=Sys.EventArgs.Empty;if(h) +h(this,args);},invoke_compatHandler:function(name) +{var ret=true;var h;var evts=this.get_events()._getEvent(name);if(evts) +{var argString='';for(var i=1;i1) +argString+=',';argString+='arguments['+i+']';} +for(var i=0;i0;this.hasPendingNodes=(node.getAttribute('hasNodes','0')=='1'&&this.hasNodes==false);this.imageIndex=new Number(node.getAttribute('imgIdx','-1'));this.image=node.getAttribute('img','');this.level=this.getNodeLevel();this.isBreak=node.getAttribute('isBreak','0')=='1'?true:false;}} +dnn.controls.DNNNode.prototype={_getAbbr:function(name) +{if(this._abbr[name]) +return this._abbr[name];return name;},_addAbbr:function(dict) +{for(var prop in dict) +this._abbr[prop]=dict[prop];},childNodeCount:function() +{return this.node.childNodeCount();},getNodeLevel:function() +{return this.getParentNodes().length;},getParentNodes:function() +{var nodes=[];var node=this.node;while(node!=null) +{node=node.parentNode();if(node==null||node.nodeName()=='root') +break;nodes.push(node);} +return nodes;},update:function(prop) +{if(prop!=null) +{var type=typeof(this[prop]);var key=prop;if(this._abbr[prop]) +key=this._abbr[prop];if(type=='string'||type=='number'||this[prop]==null) +this.node.setAttribute(prop,this[prop]);else if(type=='boolean') +this.node.setAttribute(prop,new Number(this[prop]));} +else +{for(prop in this) +this.update(prop);}}} +dnn.controls.DNNNode.registerClass('dnn.controls.DNNNode');dnn.controls.JSONNode=function(node,nodeName,nodeIndex,path) +{dnn.extend(this,node);this._nodeName=nodeName;this._nodeDictionary=null;this._nodeIndex=nodeIndex;this._nodePath=nodeIndex.toString();if(path==null) +this._nodePath='';else if(path.length>0) +this._nodePath=path+'-'+nodeIndex;if(nodeName=='root') +{this._nodeDictionary=[];this.setupJSONNodes(this,this,node.nodes);}} +dnn.controls.JSONNode.prototype={getAttribute:function(name,def) +{def=(def)?def:'';return this[name]==null?def:this[name];},setAttribute:function(name,val) +{this[name]=val;},parentNode:function() +{return this._parentNode;},hasChildNodes:function() +{return this.nodes.length>0;},getNodeIndex:function() +{return this._nodeIndex;},getNodePath:function() +{return this._nodePath;},childNodeCount:function() +{return this.nodes.length;},childNodes:function(idx) +{return this.nodes[idx];},nodeName:function() +{return this._nodeName;},rootNode:function() +{return this._parentNode==null?this:this._parentNode.rootNode();},findNode:function(id) +{if(arguments.length==3) +id=arguments[2];return this.rootNode()._nodeDictionary[id];},getJSON:function(node) +{if(node==null) +node=this;var json='{';json+=this.getJSONAttributes(node,':',',')+',nodes:[';for(var i=0;i0) +json+=',';json+=this.getJSON(node.childNodes(i));} +json+=']}';return json;},getXml:function(node) +{if(node==null) +node=this;var xml='';xml='<'+node.nodeName()+this.getXmlAttributes(node)+'>';for(var i=0;i';return xml;},getJSONAttributes:function(node) +{var ret='';for(var attr in node) +{if(typeof(node[attr])!='function'&&attr.substring(0,1)!='_'&&attr!='nodes') +{if(ret.length>0) +ret+=',';ret+=' '+attr+':"'+dnn.encodeJSON(node.getAttribute(attr).toString())+'"';}} +return ret;},getXmlAttributes:function(node) +{var ret='';for(var attr in node) +{if(typeof(node[attr])!='function'&&attr.substring(0,1)!='_'&&attr!='nodes') +{if(ret.length>0) +ret+=' ';ret+=' '+attr+'="'+dnn.encodeHTML(node.getAttribute(attr))+'"';}} +return ret;},setupJSONNodes:function(root,parent,nodes) +{var jnode;for(var i=0;i0),'Testing for string length: '+this._safeString(sVal1)+' ('+((sVal1==null)?'null':sVal1.length)+')');},assertNaN:function(sCom,sVal1) +{this.assertCheck(sCom,isNaN(sVal1),'Testing for NaN: '+this._safeString(sVal1)+' ('+typeof(sVal1)+') is a number');},assertNotNaN:function(sCom,sVal1) +{this.assertCheck(sCom,isNaN(sVal1)==false,'Testing for NotNaN: '+this._safeString(sVal1)+' ('+typeof(sVal1)+') is NOT a number');},_safeString:function(s) +{if(typeof(s)=='string'||typeof(s)=='number') +return s;else +return typeof(s);}});var __dnn_m_aryHandled=new Array();function dnn_diagnosticTests(oParent) +{if(oParent.ns=='dnn') +dnn.diagnostics.clearDebug();if(typeof(oParent.UnitTests)=='function') +{dnn.diagnostics.displayDebug('------- Starting '+oParent.pns+'.'+oParent.ns+' tests (v.'+(oParent.apiversion?oParent.apiversion:dnn.apiversion)+') '+new Date().toString()+' -------');oParent.UnitTests();} +for(var obj in oParent) +{if(oParent[obj]!=null&&typeof(oParent[obj])=='object'&&__dnn_m_aryHandled[obj]==null) +{if(oParent[obj].pns!=null) +dnn_diagnosticTests(oParent[obj]);}}} +function __dnn_documentLoaded() +{dnn.diagnostics.debugWait=false;dnn.diagnostics.displayDebug('document loaded... avoiding Operation Aborted IE bug');dnn.diagnostics.displayDebug(dnn.diagnostics.debugArray.join('\n'));} diff --git a/Website/js/dnn.dom.positioning.js b/Website/js/dnn.dom.positioning.js new file mode 100644 index 00000000000..108754c932c --- /dev/null +++ b/Website/js/dnn.dom.positioning.js @@ -0,0 +1,89 @@ + +Type.registerNamespace('dnn.dom.positioning');dnn.extend(dnn.dom.positioning,{pns:'dnn.dom',ns:'positioning',dragCtr:null,dragCtrDims:null,bodyScrollLeft:function() +{if(window.pageYOffset) +return window.pageYOffset;var oBody=(document.compatMode&&document.compatMode!="BackCompat")?document.documentElement:document.body;return oBody.scrollLeft;},bodyScrollTop:function() +{if(window.pageXOffset) +return window.pageXOffset;var oBody=(document.compatMode&&document.compatMode!="BackCompat")?document.documentElement:document.body;return oBody.scrollTop;},viewPortHeight:function() +{if(window.innerHeight) +return window.innerHeight;var oBody=(document.compatMode&&document.compatMode!="BackCompat")?document.documentElement:document.body;return oBody.clientHeight;},viewPortWidth:function() +{if(window.innerWidth) +return window.innerWidth;var oBody=(document.compatMode&&document.compatMode!="BackCompat")?document.documentElement:document.body;return oBody.clientWidth;},dragContainer:function(oCtl,e) +{var iNewLeft=0;var iNewTop=0;var oCont=dnn.dom.getById(oCtl.contID);var oTitle=dnn.dom.positioning.dragCtr;var iScrollTop=this.bodyScrollTop();var iScrollLeft=this.bodyScrollLeft();if(oCtl.startLeft==null) +oCtl.startLeft=e.clientX-this.elementLeft(oCont)+iScrollLeft;if(oCtl.startTop==null) +oCtl.startTop=e.clientY-this.elementTop(oCont)+iScrollTop;if(oCont.style.position=='relative') +oCont.style.position='absolute';iNewLeft=e.clientX-oCtl.startLeft+iScrollLeft;iNewTop=e.clientY-oCtl.startTop+iScrollTop;if(iNewLeft>this.elementWidth(document.forms[0])) +iNewLeft=this.elementWidth(document.forms[0]);if(iNewTop>this.elementHeight(document.forms[0])) +iNewTop=this.elementHeight(document.forms[0]);oCont.style.left=iNewLeft+'px';oCont.style.top=iNewTop+'px';if(oTitle!=null&&oTitle.dragOver!=null) +eval(oCtl.dragOver);},elementHeight:function(eSrc) +{if(eSrc.offsetHeight==null||eSrc.offsetHeight==0) +{if(eSrc.offsetParent==null) +return 0;if(eSrc.offsetParent.offsetHeight==null||eSrc.offsetParent.offsetHeight==0) +{if(eSrc.offsetParent.offsetParent!=null) +return eSrc.offsetParent.offsetParent.offsetHeight;else +return 0;} +else +return eSrc.offsetParent.offsetHeight;} +else +return eSrc.offsetHeight;},elementLeft:function(eSrc) +{return this.elementPos(eSrc).l;},elementOverlapScore:function(oDims1,oDims2) +{var iLeftScore=0;var iTopScore=0;if(oDims1.l<=oDims2.l&&oDims2.l<=oDims1.r) +iLeftScore+=(oDims1.r=7)) +return;var oIFR=dnn.dom.getById('ifr'+oCont.id);if(oIFR==null) +{var oIFR=document.createElement('iframe');oIFR.id='ifr'+oCont.id;if(sSrc!=null) +oIFR.src=sSrc;oIFR.style.top='0px';oIFR.style.left='0px';oIFR.style.filter="progid:DXImageTransform.Microsoft.Alpha(opacity=0)";oIFR.scrolling='no';oIFR.frameBorder='no';oIFR.style.display='none';oIFR.style.position='absolute';oCont.parentNode.appendChild(oIFR);} +var oDims=new dnn.dom.positioning.dims(oCont);oIFR.style.width=oDims.w;oIFR.style.height=oDims.h;oIFR.style.top=oDims.t+'px';oIFR.style.left=oDims.l+'px';var iIndex=dnn.dom.getCurrentStyle(oCont,'zIndex');if(iIndex==null||iIndex==0||isNaN(iIndex)) +iIndex=1;oCont.style.zIndex=iIndex;oIFR.style.zIndex=iIndex-1;if(bShow) +oIFR.style.display="block";else if(oIFR!=null) +oIFR.style.display='none';},__dnn_containerMouseDown:function(oCtl) +{while(oCtl.contID==null) +{oCtl=oCtl.parentNode;if(oCtl.tagName.toUpperCase()=='BODY') +return;} +dnn.dom.positioning.dragCtr=oCtl;oCtl.startTop=null;oCtl.startLeft=null;var oCont=dnn.dom.getById(oCtl.contID);if(oCont.style.position==null||oCont.style.position.length==0) +oCont.style.position='relative';dnn.dom.positioning.dragCtrDims=new dnn.dom.positioning.dims(oCont);if(oCont.getAttribute('_b')==null) +{oCont.setAttribute('_b',oCont.style.backgroundColor);oCont.setAttribute('_z',oCont.style.zIndex);oCont.setAttribute('_w',oCont.style.width);oCont.setAttribute('_d',oCont.style.border);oCont.style.zIndex=9999;oCont.style.backgroundColor=DNN_HIGHLIGHT_COLOR;oCont.style.border='4px outset '+DNN_HIGHLIGHT_COLOR;oCont.style.width=dnn.dom.positioning.elementWidth(oCont);if(dnn.dom.browser.type==dnn.dom.browser.InternetExplorer) +oCont.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity=80)';}},__dnn_containerMouseDownDelay:function(e) +{var oTitle=e.srcElement;if(oTitle==null) +oTitle=e.target;dnn.doDelay('__dnn_dragdrop',500,this.__dnn_containerMouseDown,oTitle);},__dnn_bodyMouseUp:function() +{dnn.cancelDelay('__dnn_dragdrop');var oCtl=dnn.dom.positioning.dragCtr;if(oCtl!=null&&oCtl.dragComplete!=null) +{eval(oCtl.dragComplete);var oCont=dnn.dom.getById(oCtl.contID);oCont.style.backgroundColor=oCont.getAttribute('_b');oCont.style.zIndex=oCont.getAttribute('_z');oCont.style.width=oCont.getAttribute('_w');oCont.style.border=oCont.getAttribute('_d');oCont.setAttribute('_b',null);oCont.setAttribute('_z',null);if(dnn.dom.browser.type==dnn.dom.browser.InternetExplorer) +oCont.style.filter=null;} +dnn.dom.positioning.dragCtr=null;},__dnn_bodyMouseMove:function(e) +{if(this.dragCtr!=null) +this.dragContainer(this.dragCtr,e);}});dnn.dom.positioning.dims=function(eSrc) +{var bHidden=(eSrc.style.display=='none');if(bHidden) +eSrc.style.display="";this.w=dnn.dom.positioning.elementWidth(eSrc);this.h=dnn.dom.positioning.elementHeight(eSrc);var oPos=dnn.dom.positioning.elementPos(eSrc);this.t=oPos.t;this.l=oPos.l;this.at=oPos.at;this.al=oPos.al;this.rot=this.at-this.t;this.rol=this.al-this.l;this.r=this.l+this.w;this.b=this.t+this.h;if(bHidden) +eSrc.style.display="none";} +dnn.dom.positioning.dims.registerClass('dnn.dom.positioning.dims'); diff --git a/Website/js/dnn.gettingstarted.js b/Website/js/dnn.gettingstarted.js new file mode 100644 index 00000000000..4b1d05eab23 --- /dev/null +++ b/Website/js/dnn.gettingstarted.js @@ -0,0 +1 @@ +var GettingStartedNS = {}; GettingStartedNS.markAsShown = function (b, a) { var c = pageCurrentDomainUrl + "/Default.aspx/SetGettingStartedPageAsShown"; $.ajax({ type: "POST", url: c, data: "{ portailId: " + pageCurrentPortalId + "}", async: false, contentType: "application/json; charset=utf-8", dataType: "json", success: function (d) { if (d.d) { if (b == "goto" && window.location.href.indexOf("popUp") > -1) { window.location.href = a } else { if (b == "show" && window.location.href.indexOf("popUp") == -1) { dnnModal.show(a + "?popUp=true", false, 550, 950, true, "") } else { window.location.href = a } } } }, error: function () { } }); return false }; GettingStartedNS.deleteBeforeCloseEvent = function () { var a = parent.$(".ui-dialog:visible"); if (a != null) { a.unbind("dialogbeforeclose") } }; GettingStartedNS.showModal = function (a) { GettingStartedNS.markAsShown("show", a); GettingStartedNS.deleteBeforeCloseEvent() }; GettingStartedNS.goTo = function (a) { GettingStartedNS.markAsShown("goto", a); GettingStartedNS.deleteBeforeCloseEvent() }; GettingStartedNS.addBeforeCloseEvent = function (a) { var b = parent.$(".ui-dialog:visible"); if (b != null) { b.bind("dialogbeforeclose", function (c, d) { GettingStartedNS.goTo(a) }) } }; GettingStartedNS.setDialogTitle = function (a) { parent.$("#iPopUp").dialog({ title: a }) }; $(document).ready(function () { GettingStartedNS.addBeforeCloseEvent(pageCurrentPortalAliasUrl); GettingStartedNS.setDialogTitle(gettingStartedPageTitle) }); \ No newline at end of file diff --git a/Website/js/dnn.js b/Website/js/dnn.js new file mode 100644 index 00000000000..2309af902ea --- /dev/null +++ b/Website/js/dnn.js @@ -0,0 +1 @@ +var dnnJscriptVersion = "6.0.0"; if (typeof (Sys.Browser.Chrome) == "undefined") { Sys.Browser.Chrome = {}; if (navigator.userAgent.indexOf(" Chrome/") > -1) { Sys.Browser.agent = Sys.Browser.Chrome; Sys.Browser.version = parseFloat(navigator.userAgent.match(/Chrome\/(\d+\.\d+)/)[1]); Sys.Browser.name = "Chrome"; Sys.Browser.hasDebuggerStatement = true } } var DNN_HIGHLIGHT_COLOR = "#9999FF"; var COL_DELIMITER = String.fromCharCode(18); var ROW_DELIMITER = String.fromCharCode(17); var QUOTE_REPLACEMENT = String.fromCharCode(19); var KEY_LEFT_ARROW = 37; var KEY_UP_ARROW = 38; var KEY_RIGHT_ARROW = 39; var KEY_DOWN_ARROW = 40; var KEY_RETURN = 13; var KEY_ESCAPE = 27; Type.registerNamespace("dnn"); dnn.extend = function (a, b) { for (s in b) { a[s] = b[s] } return a };dnn.extend(dnn, { apiversion: new Number("04.02"), pns: "", ns: "dnn", diagnostics: null, vars: null, dependencies: new Array(), isLoaded: false, delay: [], _delayedSet: null, getVars: function () { if (this.vars == null) { var a = dnn.dom.getById("__dnnVariable"); if (a != null) { if (a.value.indexOf("`") == 0) { a.value = a.value.substring(1).replace(/`/g, '"') } if (a.value.indexOf("__scdoff") != -1) { COL_DELIMITER = "~|~"; ROW_DELIMITER = "~`~"; QUOTE_REPLACEMENT = "~!~" } } if (a != null && a.value.length > 0) { this.vars = Sys.Serialization.JavaScriptSerializer.deserialize(a.value) } else { this.vars = [] } } return this.vars }, getVar: function (key, def) { if (this.getVars()[key] != null) { var re = eval("/" + QUOTE_REPLACEMENT + "/g"); return this.getVars()[key].replace(re, '"') } return def }, setVar: function (b, c) { if (this.vars == null) { this.getVars() } this.vars[b] = c; var a = dnn.dom.getById("__dnnVariable"); if (a == null) { a = dnn.dom.createElement("INPUT"); a.type = "hidden"; a.id = "__dnnVariable"; dnn.dom.appendChild(dnn.dom.getByTagName("body")[0], a) } if (dnn.isLoaded) { a.value = Sys.Serialization.JavaScriptSerializer.serialize(this.vars) } else { dnn._delayedSet = { key: b, val: c} } return true }, callPostBack: function (action) { var postBack = dnn.getVar("__dnn_postBack"); var data = ""; if (postBack.length > 0) { data += action; for (var i = 1; i < arguments.length; i++) { var aryParam = arguments[i].split("="); data += COL_DELIMITER + aryParam[0] + COL_DELIMITER + aryParam[1] } eval(postBack.replace("[DATA]", data)); return true } return false }, createDelegate: function (a, b) { return Function.createDelegate(a, b) }, doDelay: function (b, c, d, a) { if (this.delay[b] == null) { this.delay[b] = new dnn.delayObject(d, a, b); this.delay[b].num = window.setTimeout(dnn.createDelegate(this.delay[b], this.delay[b].complete), c) } }, cancelDelay: function (a) { if (this.delay[a] != null) { window.clearTimeout(this.delay[a].num); this.delay[a] = null } }, decodeHTML: function (a) { return a.toString().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"') }, encode: function (a, c) { var b = a; if (encodeURIComponent) { b = encodeURIComponent(b) } else { b = escape(b) } if (c == false) { return b } return b.replace(/%/g, "%25") }, encodeHTML: function (a) { return a.toString().replace(/&/g, "&").replace(//g, ">").replace(/'/g, "'").replace(/\"/g, """) }, encodeJSON: function (a) { return a.toString().replace(/&/g, "&").replace(//g, ">").replace(/'/g, "\u0027").replace(/\"/g, """).replace(/\\/g, "\\\\") }, evalJSON: function (a) { return Sys.Serialization.JavaScriptSerializer.deserialize(a) }, escapeForEval: function (a) { return a.replace(/\\/g, "\\\\").replace(/\'/g, "\\'").replace(/\r/g, "").replace(/\n/g, "\\n").replace(/\./, "\\.") }, getEnumByValue: function (a, b) { for (var c in a) { if (typeof (a[c]) == "number" && a[c] == b) { return c } } }, _onload: function () { dnn.isLoaded = true; if (dnn._delayedSet) { dnn.setVar(dnn._delayedSet.key, dnn._delayedSet.val) } } }); dnn.delayObject = function (c, a, b) { this.num = null; this.pfunc = c; this.context = a; this.type = b }; dnn.delayObject.prototype = { complete: function () { dnn.delay[this.type] = null; this.pfunc(this.context) } }; dnn.delayObject.registerClass("dnn.delayObject"); dnn.ScriptRequest = function (e, d, c) { this.ctl = null; this.xmlhttp = null; this.src = null; this.text = null; if (e != null && e.length > 0) { var b = dnn.dom.scriptFile(e); var a = dnn.getVar(b + ".resx", ""); if (a.length > 0) { this.src = a } else { this.src = e } } if (d != null && d.length > 0) { this.text = d } this.callBack = c; this.status = "init"; this.timeOut = 5000; this._xmlhttpStatusChangeDelegate = dnn.createDelegate(this, this.xmlhttpStatusChange); this._statusChangeDelegate = dnn.createDelegate(this, this.statusChange); this._completeDelegate = dnn.createDelegate(this, this.complete); this._reloadDelegate = dnn.createDelegate(this, this.reload) }; dnn.ScriptRequest.prototype = { load: function () { this.status = "loading"; this.ctl = document.createElement("script"); this.ctl.type = "text/javascript"; if (this.src != null) { if (dnn.dom.browser.isType(dnn.dom.browser.Safari)) { this.xmlhttp = new XMLHttpRequest(); this.xmlhttp.open("GET", this.src, true); this.xmlhttp.onreadystatechange = this._xmlhttpStatusChangeDelegate; this.xmlhttp.send(null); return } else { if (dnn.dom.browser.isType(dnn.dom.browser.InternetExplorer)) { this.ctl.onreadystatechange = this._statusChangeDelegate } else { if (dnn.dom.browser.isType(dnn.dom.browser.Opera) == false) { this.ctl.onload = this._completeDelegate } } this.ctl.src = this.src } dnn.dom.scriptElements[this.src] = this.ctl } else { if (dnn.dom.browser.isType(dnn.dom.browser.Safari)) { this.ctl.innerHTML = dnn.encodeHTML(this.text) } else { this.ctl.text = this.text } } var a = dnn.dom.getByTagName("HEAD"); if (a) { if (dnn.dom.browser.isType(dnn.dom.browser.Opera) == false || this.src != null) { a[0].appendChild(this.ctl) } } else { alert("Cannot load dynamic script, no HEAD tag present.") } if (this.src == null || dnn.dom.browser.isType(dnn.dom.browser.Opera)) { this.complete() } else { if (this.timeOut) { dnn.doDelay("loadScript_" + this.src, this.timeOut, this._reloadDelegate, null) } } }, xmlhttpStatusChange: function () { if (this.xmlhttp.readyState != 4) { return } this.src = null; this.text = this.xmlhttp.responseText; this.load() }, statusChange: function () { if ((this.ctl.readyState == "loaded" || this.ctl.readyState == "complete") && this.status != "complete") { this.complete() } }, reload: function () { if (dnn.dom.scriptStatus(this.src) == "complete") { this.complete() } else { this.load() } }, complete: function () { dnn.cancelDelay("loadScript_" + this.src); this.status = "complete"; if (typeof (this.callBack) != "undefined") { this.callBack(this) } this.dispose() }, dispose: function () { this.callBack = null; if (this.ctl) { if (this.ctl.onreadystatechange) { this.ctl.onreadystatechange = new function () { } } else { if (this.ctl.onload) { this.ctl.onload = null } } this.ctl = null } this.xmlhttp = null; this._xmlhttpStatusChangeDelegate = null; this._statusChangeDelegate = null; this._completeDelegate = null; this._reloadDelegate = null } }; dnn.ScriptRequest.registerClass("dnn.ScriptRequest"); Type.registerNamespace("dnn.dom"); dnn.extend(dnn.dom, { pns: "dnn", ns: "dom", browser: null, __leakEvts: [], scripts: [], scriptElements: [], tweens: [], attachEvent: function (a, c, d) { if (dnn.dom.browser.isType(dnn.dom.browser.InternetExplorer) == false) { var b = c.substring(2); a.addEventListener(b, function (e) { dnn.dom.event = new dnn.dom.eventObject(e, e.target); return d() }, false) } else { a.attachEvent(c, function () { dnn.dom.event = new dnn.dom.eventObject(window.event, window.event.srcElement); return d() }) } return true }, cursorPos: function (b) { if (b.value.length == 0) { return 0 } var h = -1; if (b.selectionStart) { h = b.selectionStart } else { if (b.createTextRange) { var f = window.document.selection.createRange(); var a = b.createTextRange(); if (a == null || f == null || ((f.text != "") && a.inRange(f) == false)) { return -1 } if (f.text == "") { if (a.boundingLeft == f.boundingLeft) { h = 0 } else { var d = b.tagName.toLowerCase(); if (d == "input") { var g = a.text; var c = 1; while (c < g.length) { a.findText(g.substring(c)); if (a.boundingLeft == f.boundingLeft) { break } c++ } } else { if (d == "textarea") { var c = b.value.length + 1; var e = document.selection.createRange().duplicate(); while (e.parentElement() == b && e.move("character", 1) == 1) { --c } if (c == b.value.length + 1) { c = -1 } } } h = c } } else { h = a.text.indexOf(f.text) } } } return h }, cancelCollapseElement: function (a) { dnn.cancelDelay(a.id + "col"); a.style.display = "none" }, collapseElement: function (b, c, d) { if (c == null) { c = 10 } b.style.overflow = "hidden"; var a = new Object(); a.num = c; a.ctl = b; a.pfunc = d; b.origHeight = b.offsetHeight; dnn.dom.__collapseElement(a) }, __collapseElement: function (a) { var c = a.num; var b = a.ctl; var d = b.origHeight / c; if (b.offsetHeight - (d * 2) > 0) { b.style.height = (b.offsetHeight - d).toString() + "px"; dnn.doDelay(b.id + "col", 10, dnn.dom.__collapseElement, a) } else { b.style.display = "none"; if (a.pfunc != null) { a.pfunc() } } }, cancelExpandElement: function (a) { dnn.cancelDelay(a.id + "exp"); a.style.overflow = ""; a.style.height = "" }, disableTextSelect: function (a) { if (typeof a.onselectstart != "undefined") { a.onselectstart = function () { return false } } else { if (typeof a.style.MozUserSelect != "undefined") { a.style.MozUserSelect = "none" } else { a.onmousedown = function () { return false } } } }, expandElement: function (b, c, d) { if (c == null) { c = 10 } if (b.style.display == "none" && b.origHeight == null) { b.style.display = ""; b.style.overflow = ""; b.origHeight = b.offsetHeight; b.style.overflow = "hidden"; b.style.height = "1px" } b.style.display = ""; var a = new Object(); a.num = c; a.ctl = b; a.pfunc = d; dnn.dom.__expandElement(a) }, __expandElement: function (a) { var c = a.num; var b = a.ctl; var d = b.origHeight / c; if (b.offsetHeight + d < b.origHeight) { b.style.height = (b.offsetHeight + d).toString() + "px"; dnn.doDelay(b.id + "exp", 10, dnn.dom.__expandElement, a) } else { b.style.overflow = ""; b.style.height = ""; if (a.pfunc != null) { a.pfunc() } } }, deleteCookie: function (a, c, b) { if (this.getCookie(a)) { this.setCookie(a, "", -1, c, b); return true } return false }, getAttr: function (b, a, c) { if (b.getAttribute == null) { return c } var d = b.getAttribute(a); if (d == null || d == "") { return c } else { return d } }, getById: function (b, a) { return $get(b, a) }, getByTagName: function (a, b) { if (b == null) { b = document } if (b.getElementsByTagName) { return b.getElementsByTagName(a) } else { if (b.all && b.all.tags) { return b.all.tags(a) } else { return null } } }, getParentByTagName: function (b, a) { var c = b.parentNode; a = a.toLowerCase(); while (c != null) { if (c.tagName && c.tagName.toLowerCase() == a) { return c } c = c.parentNode } return null }, getCookie: function (c) { var e = " " + document.cookie; var d = " " + c + "="; var b = null; var f = 0; var a = 0; if (e.length > 0) { f = e.indexOf(d); if (f != -1) { f += d.length; a = e.indexOf(";", f); if (a == -1) { a = e.length } b = unescape(e.substring(f, a)) } } return (b) }, getNonTextNode: function (a) { if (this.isNonTextNode(a)) { return a } while (a != null && this.isNonTextNode(a)) { a = this.getSibling(a, 1) } return a }, addSafeHandler: function (b, a, c, d) { b[a] = this.getObjMethRef(c, d); if (dnn.dom.browser.isType(dnn.dom.browser.InternetExplorer)) { if (this.__leakEvts.length == 0) { dnn.dom.attachEvent(window, "onunload", dnn.dom.destroyHandlers) } this.__leakEvts[this.__leakEvts.length] = new dnn.dom.leakEvt(a, b, b[a]) } }, destroyHandlers: function () { var c = dnn.dom.__leakEvts.length - 1; for (var a = c; a >= 0; a--) { var b = dnn.dom.__leakEvts[a]; b.ctl.detachEvent(b.name, b.ptr); b.ctl[b.name] = null; dnn.dom.__leakEvts.length = dnn.dom.__leakEvts.length - 1 } }, getObjMethRef: function (b, a) { return (function (c) { c = c || window.event; return b[a](c, this) }) }, getSibling: function (a, c) { if (a != null && a.parentNode != null) { for (var b = 0; b < a.parentNode.childNodes.length; b++) { if (a.parentNode.childNodes[b].id == a.id) { if (a.parentNode.childNodes[b + c] != null) { return a.parentNode.childNodes[b + c] } } } } return null }, isNonTextNode: function (a) { return (a.nodeType != 3 && a.nodeType != 8) }, getScript: function (c) { if (this.scriptElements[c]) { return this.scriptElements[c] } var a = dnn.dom.getByTagName("SCRIPT"); for (var b = 0; b < a.length; b++) { if (a[b].src != null && a[b].src.indexOf(c) > -1) { this.scriptElements[c] = a[b]; return a[b] } } }, getScriptSrc: function (b) { var a = dnn.getVar(b + ".resx", ""); if (a.length > 0) { return a } return b }, getScriptPath: function () { var a = dnn.dom.getScript("dnn.js"); if (a) { return a.src.replace("dnn.js", "") } var b = dnn.getVar("__sp"); if (b) { return b } return "" }, scriptFile: function (b) { var a = b.split("/"); return a[a.length - 1] }, loadScript: function (e, d, b) { var c; if (e != null && e.length > 0) { c = this.scriptFile(e); if (this.scripts[c] != null) { return } } var a = new dnn.ScriptRequest(e, d, b); if (c) { this.scripts[c] = a } a.load(); return a }, loadScripts: function (a, b, c) { if (dnn.scripts == null) { var e = function (f, g, h) { return (function () { dnn.dom.loadScripts(f, g, h) }) }; dnn.dom.loadScript(dnn.dom.getScriptPath() + "dnn.scripts.js", null, e(a, b, c)); return } var d = new dnn.scripts.ScriptBatchRequest(a, b, c); d.load() }, scriptStatus: function (c) { var b = this.scriptFile(c); if (this.scripts[b]) { return this.scripts[b].status } var a = this.getScript(c); if (a != null) { return "complete" } else { return "" } }, setScriptLoaded: function (b) { var a = this.scriptFile(b); if (this.scripts[a] && dnn.dom.scripts[a].status != "complete") { dnn.dom.scripts[a].complete() } }, navigate: function (b, a) { if (a != null && a.length > 0) { if (a == "_blank" || a == "_new") { window.open(b) } else { document.frames[a].location.href = b } } else { if (Sys.Browser.agent === Sys.Browser.InternetExplorer) { window.navigate(b) } else { window.location.href = b } } return false }, setCookie: function (a, e, g, d, c, b) { var f; if (g) { f = new Date(); f.setTime(f.getTime() + (g * 24 * 60 * 60 * 1000)) } document.cookie = a + "=" + escape(e) + ((f) ? "; expires=" + f.toGMTString() : "") + ((d) ? "; path=" + d : "") + ((c) ? "; domain=" + c : "") + ((b) ? "; secure" : ""); if (document.cookie.length > 0) { return true } }, getCurrentStyle: function (b, c) { var a = Sys.UI.DomElement._getCurrentStyle(b); if (a) { return a[c] } return "" }, getFormPostString: function (a) { var c = ""; if (a != null) { if (a.tagName && a.tagName.toLowerCase() == "form") { for (var b = 0; b < a.elements.length; b++) { c += this.getElementPostString(a.elements[b]) } } else { c = this.getElementPostString(a); for (var b = 0; b < a.childNodes.length; b++) { c += this.getFormPostString(a.childNodes[b]) } } } return c }, getElementPostString: function (a) { var c; if (a.tagName) { c = a.tagName.toLowerCase() } if (c == "input") { var d = a.type.toLowerCase(); if (d == "text" || d == "password" || d == "hidden" || ((d == "checkbox" || d == "radio") && a.checked)) { return a.name + "=" + dnn.encode(a.value, false) + "&" } } else { if (c == "select") { for (var b = 0; b < a.options.length; b++) { if (a.options[b].selected) { return a.name + "=" + dnn.encode(a.options[b].value, false) + "&" } } } else { if (c == "textarea") { return a.name + "=" + dnn.encode(a.value, false) + "&" } } } return "" }, appendChild: function (b, a) { return b.appendChild(a) }, removeChild: function (a) { return a.parentNode.removeChild(a) }, createElement: function (a) { return document.createElement(a.toLowerCase()) } }); dnn.dom.leakEvt = function (c, a, b) { this.name = c; this.ctl = a; this.ptr = b }; dnn.dom.leakEvt.registerClass("dnn.dom.leakEvt"); dnn.dom.eventObject = function (b, a) { this.object = b; this.srcElement = a }; dnn.dom.eventObject.registerClass("dnn.dom.eventObject"); dnn.dom.browserObject = function () { this.InternetExplorer = "ie"; this.Netscape = "ns"; this.Mozilla = "mo"; this.Opera = "op"; this.Safari = "safari"; this.Konqueror = "kq"; this.MacIE = "macie"; var b; var d = navigator.userAgent.toLowerCase(); if (d.indexOf("konqueror") != -1) { b = this.Konqueror } else { if (d.indexOf("msie") != -1 && d.indexOf("mac") != -1) { b = this.MacIE } else { if (Sys.Browser.agent === Sys.Browser.InternetExplorer) { b = this.InternetExplorer } else { if (Sys.Browser.agent === Sys.Browser.FireFox) { b = this.Mozilla } else { if (Sys.Browser.agent === Sys.Browser.Safari) { b = this.Safari } else { if (Sys.Browser.agent === Sys.Browser.Opera) { b = this.Opera } else { b = this.Mozilla } } } } } } this.type = b; this.version = Sys.Browser.version; var c = navigator.userAgent.toLowerCase(); if (this.type == this.InternetExplorer) { var a = navigator.appVersion.split("MSIE"); this.version = parseFloat(a[1]) } if (this.type == this.Netscape) { var a = c.split("netscape"); this.version = parseFloat(a[1].split("/")[1]) } }; dnn.dom.browserObject.prototype = { toString: function () { return this.type + " " + this.version }, isType: function () { for (var a = 0; a < arguments.length; a++) { if (dnn.dom.browser.type == arguments[a]) { return true } } return false } }; dnn.dom.browserObject.registerClass("dnn.dom.browserObject"); dnn.dom.browser = new dnn.dom.browserObject(); if (typeof ($) == "undefined") { eval("function $() {var ary = new Array(); for (var i=0; i'),e(document.body).append(b)):b.attr("src","about:blank");e(document).find("html").css("overflow","hidden");b.dialog({modal:!0,autoOpen:!0,dialogClass:"dnnFormPopup",position:"center",minWidth:f,minHeight:d, +maxWidth:1920,maxHeight:1080,resizable:!0,closeOnEscape:!0,refresh:g,showReturn:c,closingUrl:h,close:function(b,a){dnnModal.closePopUp(g,h)}}).width(f-11).height(d-11);0===b.parent().find(".ui-dialog-title").next("a.dnnModalCtrl").length&&(d=e(''),b.parent().find(".ui-dialog-titlebar-close").wrap(d),d=e('Max'),b.parent().find(".ui-dialog-titlebar-close").before(d),d.click(function(a){a.preventDefault();var c=e(k);b.data("isMaximized")? +(a=b.data("height"),c=b.data("width"),b.data("isMaximized",!1)):(b.data("height",b.dialog("option","minHeight")).data("width",b.dialog("option","minWidth")).data("position",b.dialog("option","position")),a=c.height()-46,c=c.width()-40,b.data("isMaximized",!0));b.dialog({height:a,width:c});b.dialog({position:"center"})}));(function(){var a=e('
    ');a.css({width:b.width(),height:b.height()});b.before(a)})();b[0].src=a;b.bind("load",function(){b.prev(".dnnLoading").remove()}); +if("true"==c.toString())return!1},closePopUp:function(a,c){var d=parent,f=d.jQuery("#iPopUp");if("undefined"===typeof a||null==a)a=!0;if("true"==a.toString()){if("undefined"===typeof c||""==c)c=d.location.href;d.location.href=c;f.hide()}else f.dialog("option","close",null).dialog("close");e(d.document).find("html").css("overflow","")},refreshPopup:function(a){var c=parent,d=c.parent;c.location.href!==d.location.href&&c.location.href!==a.url?d.dnnModal.show(a.url,a.showReturn,a.height,a.width,a.refresh, +a.closingUrl):dnnModal.closePopUp(a.refresh,a.url)}};k.dnnModal.load()})(window,jQuery); diff --git a/Website/js/dnn.motion.js b/Website/js/dnn.motion.js new file mode 100644 index 00000000000..3b5f91c20d7 --- /dev/null +++ b/Website/js/dnn.motion.js @@ -0,0 +1,77 @@ + +dnn.extend(dnn.dom,{tweens:[],animate:function(ctl,type,dir,easingType,easingDir,length,interval,onStartFunc,onFinishFunc) +{var dims=new dnn.dom.positioning.dims(ctl);var anims=[];var vertical=(dir==dnn.motion.animationDir.Down||dir==dnn.motion.animationDir.Up);var expand=(dir==dnn.motion.animationDir.Down||dir==dnn.motion.animationDir.Right);var coord=vertical?'t':'l';var size=coord=='t'?'h':'w';var prop=coord=='t'?'top':'left';var easingFunc=dnn.getEnumByValue(dnn.motion.easingDir,easingDir)+dnn.getEnumByValue(dnn.motion.easingType,easingType);if(type==dnn.motion.animationType.Slide) +{anims.push({prop:'clip'+prop,begin:dims[size],finish:0});anims.push({prop:prop,begin:dims[coord]-dims[size],finish:dims[coord]});} +else if(type==dnn.motion.animationType.Expand) +{var newDir=vertical?'bottom':'right';anims.push({prop:'clip'+newDir,begin:0,finish:dims[size]});} +else if(type==dnn.motion.animationType.Diagonal) +{size=dims.h>dims.w?'h':'w';anims.push({prop:'clipbottomright',begin:0,finish:dims[size]});} +else if(type==dnn.motion.animationType.ReverseDiagonal) +{size=dims.h>dims.w?'h':'w';anims.push({prop:'cliptopleft',begin:dims[size],finish:0});} +for(var i=0;ithis._duration) +{if(this._looping) +{this.rewind(val-this._duration);this._update();this.raiseEvent('onMotionLooped');} +else +{this._time=this._duration;this._update();this.stop();this.raiseEvent('onMotionFinished');}} +else if(val<0) +{this.rewind();this._update();} +else +{this._time=val;this._update();}},get_Time:function(){return this._time;},set_Begin:function(val){this._begin=val;},get_Begin:function(){return this._begin;},set_Duration:function(val){this._duration=val;},get_Duration:function(){return this._duration;},set_Interval:function(val){this._interval=val;},get_Interval:function(){return this._interval;},set_Looping:function(val){this._looping=val;},get_Looping:function(){return this._looping;},set_Object:function(val){this._obj=val;},get_Object:function(){return this._obj;},set_Property:function(val){this._prop=val;},get_Property:function(){return this._prop;},set_Suffix:function(val){this._suffix=val;},get_Suffix:function(){return this._suffix;},get_Timer:function() +{return new Date().getTime()-this._time;},start:function() +{this._fixTime();this.isPlaying=true;this._onEnterFrame();this.raiseEvent('onMotionStarted');},stop:function() +{dnn.cancelDelay(this.id);this.isPlaying=false;this.raiseEvent('onMotionStopped');},resume:function() +{this._fixTime();this.start();},rewind:function(time) +{this._time=(time==null?1:time);this._fixTime();},fforward:function() +{this.set_Time(this._duration);this._fixTime();},nextFrame:function() +{this.set_Time((this.get_Timer()-this._startTime)/1000);},prevFrame:function() +{this.set_Time(this._time-1);},dispose:function() +{this._obj=null;this._listeners=null;this._events=null;},toString:function() +{return'[Motion prop='+this._prop+' t='+this._time+' pos='+this._pos+']';},addEventHandler:function(name,handler) +{this._events.addHandler(name,handler);},removeEventHandler:function(name,handler) +{this._events.removeHandler(name,handler);},raiseEvent:function(eventName) +{if(!this._events)return;var handler=this._events.getHandler(eventName);if(handler){handler(this,Sys.EventArgs.Empty);}},_onEnterFrame:function() +{if(this.isPlaying) +{this.nextFrame();dnn.doDelay(this.id,this._interval,dnn.createDelegate(this,this._onEnterFrame));}},_update:function() +{this.set_Position(this.get_Position(this._time));},_fixTime:function() +{this._startTime=this.get_Timer()-this._time;},_getClipObject:function() +{var o={};o.cliptop='auto';o.clipright='auto';o.clipbottom='auto';o.clipleft='auto';return o;},_getClips:function(prop) +{var o=[];if(prop.indexOf('top')>-1) +o.push('cliptop');if(prop.indexOf('left')>-1) +o.push('clipleft');if(prop.indexOf('bottom')>-1) +o.push('clipbottom');if(prop.indexOf('right')>-1) +o.push('clipright');return o;}} +dnn.motion.registerClass('dnn.motion',null,Sys.IDisposable);dnn.motion.animationType=function(){};dnn.motion.animationType.prototype={None:0,Slide:1,Expand:2,Diagonal:3,ReverseDiagonal:4} +dnn.motion.animationType.registerEnum("dnn.motion.animationType");dnn.motion.animationDir=function(){};dnn.motion.animationDir.prototype={Up:0,Down:1,Left:2,Right:3} +dnn.motion.animationDir.registerEnum("dnn.motion.animationDir");dnn.motion.easingType=function(){};dnn.motion.easingType.prototype={Bounce:0,Circ:1,Cubic:2,Expo:3,Quad:4,Quint:5,Quart:6,Sine:7} +dnn.motion.easingType.registerEnum("dnn.motion.easingType");dnn.motion.easingDir=function(){};dnn.motion.easingDir.prototype={easeIn:0,easeOut:1,easeInOut:2} +dnn.motion.easingDir.registerEnum("dnn.motion.easingDir");dnn.tween=function(id,obj,prop,func,begin,finish,duration) +{dnn.tween.initializeBase(this,[id,obj,prop,begin,duration]);this._func=func;this._change=0;this.set_Finish(finish);} +dnn.tween.prototype={set_Function:function(val){this._func=val;},get_Function:function(){return this._func;},set_Change:function(val){this._change=val;},get_Change:function(){return this._change;},set_Finish:function(val) +{this._change=val-this._begin;},get_Finish:function() +{return this._begin+this._change;},get_Position:function() +{return this._func(this._time,this._begin,this._change,this._duration);},continueTo:function(finish,duration) +{this.set_Begin(this.get_Position());this.set_Finish(finish);this.set_Duration(duration);this.start();},dispose:function() +{dnn.tween.callBaseMethod(this,'dispose');this._func=null;}} +dnn.tween.registerClass('dnn.tween',dnn.motion);Type.registerNamespace('dnn.easing');dnn.extend(dnn.easing,{linearTween:function(t,b,c,d){return c*t/d+b;},easeInQuad:function(t,b,c,d){return c*(t/=d)*t+b;},easeOutQuad:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOutQuad:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},easeInCubic:function(t,b,c,d){return c*(t/=d)*t*t+b;},easeOutCubic:function(t,b,c,d){return c*((t=t/d-1)*t*t+1)+b;},easeInOutCubic:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t+b;return c/2*((t-=2)*t*t+2)+b;},easeInQuart:function(t,b,c,d){return c*(t/=d)*t*t*t+b;},easeOutQuart:function(t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;},easeInOutQuart:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t+b;return-c/2*((t-=2)*t*t*t-2)+b;},easeInQuint:function(t,b,c,d){return c*(t/=d)*t*t*t*t+b;},easeOutQuint:function(t,b,c,d){return c*((t=t/d-1)*t*t*t*t+1)+b;},easeInOutQuint:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t*t+b;return c/2*((t-=2)*t*t*t*t+2)+b;},easeInSine:function(t,b,c,d){return-c*Math.cos(t/d*(3.14/2))+c+b;},easeOutSine:function(t,b,c,d){return c*Math.sin(t/d*(3.14/2))+b;},easeInOutSine:function(t,b,c,d){return-c/2*(Math.cos(3.14*t/d)-1)+b;},easeInExpo:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOutExpo:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOutExpo:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},easeInCirc:function(t,b,c,d){return-c*(Math.sqrt(1-(t/=d)*t)-1)+b;},easeOutCirc:function(t,b,c,d){return c*Math.sqrt(1-(t=t/d-1)*t)+b;},easeInOutCirc:function(t,b,c,d){if((t/=d/2)<1)return-c/2*(Math.sqrt(1-t*t)-1)+b;return c/2*(Math.sqrt(1-(t-=2)*t)+1)+b;},easeInBounce:function(t,b,c,d){return c-dnn.easing.easeOutBounce(d-t,0,c,d)+b;},easeOutBounce:function(t,b,c,d){if((t/=d)<(1/2.75)){return c*(7.5625*t*t)+b;}else if(t<(2/2.75)){return c*(7.5625*(t-=(1.5/2.75))*t+.75)+b;}else if(t<(2.5/2.75)){return c*(7.5625*(t-=(2.25/2.75))*t+.9375)+b;}else{return c*(7.5625*(t-=(2.625/2.75))*t+.984375)+b;}},easeInOutBounce:function(t,b,c,d){if(t + +Type.registerNamespace('dnn.controls'); + +dnn.controls.triStateManager = function (images, toolTips) { + var that; + + that = { + initControl: function (hidden) { + var hdn = jQuery(hidden); + if (!hdn.hasClass('lockedPerm')) { + if (hdn.hasClass('noDenyPerm')) { + + hdn.siblings('img').click(function () { + if (hidden.value === 'True') { + hidden.value = 'Null'; + } else { + hidden.value = 'True'; + } + + this.src = images[hidden.value]; + this.alt = toolTips[hidden.value]; + }); + + } else { + + hdn.siblings('img').click(function () { + if (hidden.value === 'True') { + hidden.value = 'False'; + } else if (hidden.value === 'False') { + hidden.value = 'Null'; + } else { + hidden.value = 'True'; + } + + this.src = images[hidden.value]; + this.alt = toolTips[hidden.value]; + }); + + } + } + } + }; + + return that; +} \ No newline at end of file diff --git a/Website/js/dnn.postbackconfirm.js b/Website/js/dnn.postbackconfirm.js new file mode 100644 index 00000000000..b9e2fd5c342 --- /dev/null +++ b/Website/js/dnn.postbackconfirm.js @@ -0,0 +1,51 @@ +window.postBackConfirm = function(text, mozEvent, oWidth, oHeight, callerObj, oTitle) +{ + try + { + var ev = mozEvent ? mozEvent : window.event; //Moz support requires passing the event argument manually + //Cancel the event + ev.cancelBubble = true; + ev.returnValue = false; + if (ev.stopPropagation) ev.stopPropagation(); + if (ev.preventDefault) ev.preventDefault(); + + //Determine who is the caller + var callerObj = ev.srcElement ? ev.srcElement : ev.target; + + //Call the original radconfirm and pass it all necessary parameters + if (callerObj) + { + //Show the confirm, then when it is closing, if returned value was true, automatically call the caller's click method again. + var callBackFn = function (arg) + { + if (arg) + { + callerObj["onclick"] = ""; + if (callerObj.click) callerObj.click(); //Works fine every time in IE, but does not work for links in Moz + else if (callerObj.tagName == "A") //We assume it is a link button! + { + try + { + eval(callerObj.href) + } + catch(e){} + } + } + } + + if (oWidth == null || oWidth == "") + oWidth = 350 + if (oHeight == null || oHeight == "") + oHeight = 175 + if (oTitle == null || oTitle == "") + oTitle = 'Confirm' + + radconfirm(text + "

    ", callBackFn, oWidth, oHeight, callerObj, oTitle); + } + return false; + } + catch (ex) + { + return true; + } +}; diff --git a/Website/js/dnn.scripts.js b/Website/js/dnn.scripts.js new file mode 100644 index 00000000000..5cc0e6b0792 --- /dev/null +++ b/Website/js/dnn.scripts.js @@ -0,0 +1,19 @@ + +Type.registerNamespace('dnn.scripts');dnn.extend(dnn.scripts,{pns:'dnn',ns:'scripts'});dnn.scripts.ScriptBatchRequest=function(aSrc,aText,callBack) +{this.ref=aSrc;this.inline=aText;this.requests=[];this.callBack=callBack;this.numComplete=0;this.numToComplete=0;} +dnn.scripts.ScriptBatchRequest.prototype={load:function() +{var ary=[];for(var i=0;i -1) { xhr.setRequestHeader("ModuleId", base.getModuleId()); xhr.setRequestHeader("TabId", tabId); } var afValue = base.getAntiForgeryValue(); if (afValue) { xhr.setRequestHeader("RequestVerificationToken", afValue); } }; base.getAntiForgeryKey = function () { return "__RequestVerificationToken"; }; base.getAntiForgeryValue = function () { return $('[name="__RequestVerificationToken"]').val(); }; return base; }; $.ServicesFramework = function (moduleId) { return new $.dnnSF(moduleId); }; })(jQuery); \ No newline at end of file diff --git a/Website/js/dnn.util.tablereorder.js b/Website/js/dnn.util.tablereorder.js new file mode 100644 index 00000000000..73217b91268 --- /dev/null +++ b/Website/js/dnn.util.tablereorder.js @@ -0,0 +1,64 @@ + +Type.registerNamespace('dnn.util');dnn.extend(dnn.util, { tableReorderMove: function (ctl, bUp, sKey) { + var oTR = dnn.dom.getParentByTagName(ctl, 'tr'); if (oTR != null) { + var oCtr = oTR.parentNode; if (oCtr.childNodes[oCtr.childNodes.length - 1].nodeName == "#text") { dnn.dom.removeChild(oCtr.childNodes[oCtr.childNodes.length - 1]); }; var iIdx = oTR.rowIndex; if (dnn.dom.getAttr(oTR, 'origidx', '') == '-1') + this.tableReorderSetOriginalIndexes(oCtr); var iNextIdx = (bUp ? this.tableReorderGetPrev(oCtr, iIdx - 1) : this.tableReorderGetNext(oCtr, iIdx + 1)); if (iNextIdx > -1) { + var aryValues = this.getInputValues(oTR); var aryValues2; var oSwapNode; dnn.dom.removeChild(oTR); if (oCtr.childNodes.length > iNextIdx) + { oSwapNode = oCtr.childNodes[iNextIdx]; aryValues2 = this.getInputValues(oSwapNode); oCtr.insertBefore(oTR, oSwapNode); } + else + oCtr.appendChild(oTR); this.setInputValues(oTR, aryValues); if (oSwapNode) + this.setInputValues(oSwapNode, aryValues2); dnn.setVar(sKey, this.tableReorderGetNewRowOrder(oCtr)); + } + return true; + } + return false; +}, getInputValues: function (oCtl) { + var aryInputs = dnn.dom.getByTagName('input', oCtl); var aryValues = new Array(); for (var i = 0; i < aryInputs.length; i++) { + if (aryInputs[i].type == 'checkbox') + aryValues[i] = aryInputs[i].checked; + } + return aryValues; +}, setInputValues: function (oCtl, aryValues) { + var aryInputs = dnn.dom.getByTagName('input', oCtl); for (var i = 0; i < aryInputs.length; i++) { + if (aryInputs[i].type == 'checkbox') + aryInputs[i].checked = aryValues[i]; + } +}, tableReorderGetNext: function (oParent, iStartIdx) { + for (var i = iStartIdx; i < oParent.childNodes.length; i++) { + var oCtl = oParent.childNodes[i]; if (dnn.dom.getAttr(oCtl, 'origidx', '') != '') + return i; + } + return -1; +}, tableReorderGetPrev: function (oParent, iStartIdx) { + for (var i = iStartIdx; i >= 0; i--) { + var oCtl = oParent.childNodes[i]; if (dnn.dom.getAttr(oCtl, 'origidx', '') != '') + return i; + } + return -1; +}, tableReorderSetOriginalIndexes: function (oParent) { + var iIdx = 0; for (var i = 0; i < oParent.childNodes.length; i++) { + var oCtl = oParent.childNodes[i]; if (dnn.dom.getAttr(oCtl, 'origidx', '') != '') + { oCtl.setAttribute('origidx', iIdx.toString()); iIdx++; } + } +}, tableReorderGetNewRowOrder: function (oParent) { + var sIdx; var sRet = ''; for (var i = 0; i < oParent.childNodes.length; i++) { + var oCtl = oParent.childNodes[i]; sIdx = dnn.dom.getAttr(oCtl, 'origidx', ''); if (sIdx != '') + sRet += (sRet.length > 0 ? ',' : '') + sIdx; + } + return sRet; +}, checkallChecked: function (oCtl, iCellIndex) { + setTimeout(function () { + var bChecked = oCtl.checked; var oTD = dnn.dom.getParentByTagName(oCtl, 'td'); var oTR = oTD.parentNode; var oCtr = oTR.parentNode; var iOffset = 0; var oTemp; + for (var i = 0; i < iCellIndex; i++) { + if (oTR.childNodes[i].tagName == null) + iOffset++; + } + var oChk; for (var i = 0; i < oCtr.childNodes.length; i++) { + oTR = oCtr.childNodes[i]; oTD = oTR.childNodes[iCellIndex + iOffset]; if (oTD != null) { + oChk = dnn.dom.getByTagName('input', oTD); if (oChk.length > 0) + oChk[0].checked = bChecked; + } + } + }, 10); +} +}); diff --git a/Website/js/dnn.xml.js b/Website/js/dnn.xml.js new file mode 100644 index 00000000000..bc7d2a990ff --- /dev/null +++ b/Website/js/dnn.xml.js @@ -0,0 +1,76 @@ + +Type.registerNamespace('dnn.xml');dnn.extend(dnn.xml,{pns:'dnn',ns:'xml',parserName:null,get_parserName:function() +{if(this.parserName==null) +this.parserName=this._getParser();return this.parserName;},createDocument:function() +{if(dnn.xml.get_parserName()=='MSXML') +{var o=new ActiveXObject('MSXML.DOMDocument');o.async=false;return new dnn.xml.documentObject(o);} +else if(dnn.xml.get_parserName()=='DOMParser') +{return new dnn.xml.documentObject(document.implementation.createDocument("","",null));} +else +return new dnn.xml.documentObject(new dnn.xml.JsDocument());},init:function() +{if(this.get_parserName()=='DOMParser') +{function __dnn_getNodeXml() +{var oXmlSerializer=new XMLSerializer;var sXml=oXmlSerializer.serializeToString(this);return sXml;} +Node.prototype.__defineGetter__("xml",__dnn_getNodeXml);}},_getParser:function() +{if(dnn.dom.browser.isType(dnn.dom.browser.InternetExplorer)) +return'MSXML';else if(dnn.dom.browser.isType(dnn.dom.browser.Netscape,dnn.dom.browser.Mozilla)) +return'DOMParser';else +return'JS';}});dnn.xml.documentObject=function(oDoc) +{this._doc=oDoc;} +dnn.xml.documentObject.prototype={getXml:function() +{if(dnn.xml.get_parserName()=='MSXML') +return this._doc.xml;else if(dnn.xml.get_parserName()=='DOMParser') +return this._doc.xml;else +return this._doc.getXml();},loadXml:function(sXml) +{if(dnn.xml.get_parserName()=='MSXML') +return this._doc.loadXML(sXml);else if(dnn.xml.get_parserName()=='DOMParser') +{var oDoc=(new DOMParser()).parseFromString(sXml,"text/xml");while(this._doc.hasChildNodes()) +this._doc.removeChild(this._doc.lastChild);for(var i=0;i'+sXml+'');var aNodes=new Array();for(var i=0;i0;},loadXml:function(sXml) +{var oParser=new dnn.xml.JsParser();oParser.parse(sXml,this.root);return true;},getXml:function() +{return this.root.getXml();},findNode:function(oParent,sNodeName,sAttr,sValue) +{for(var i=0;i0) +{var o=this.findNode(oNode,sNodeName,sAttr,sValue);if(o!=null) +return o;}}},getNextHashCode:function() +{this.currentHashCode++;return this.currentHashCode;}} +dnn.xml.JsDocument.registerClass('dnn.xml.JsDocument');dnn.xml.JsXmlNode=function(ownerDocument,name) +{this.ownerDocument=ownerDocument;this.nodeName=name;this.text='';this.childNodes=new Array();this.attributes=new Array();this.parentNode=null;this.hashCode=this.ownerDocument.getNextHashCode();this.nodeType=0;} +dnn.xml.JsXmlNode.prototype={appendChild:function(oNode) +{this.childNodes[this.childNodes.length]=oNode;oNode.parentNode=this;},removeChild:function(oNode) +{var oParent=this;var iHash=oNode.hashCode;var bFound=false;for(var i=0;i0;},getXml:function(oNode) +{if(oNode==null) +oNode=this;var sXml='';if(oNode.nodeName!='__root') +sXml='<'+oNode.nodeName+this.getAttributes(oNode)+'>';for(var i=0;i';return sXml;},getAttributes:function(oNode) +{var sRet='';for(var sAttr in oNode.attributes) +sRet+=' '+sAttr+'="'+dnn.encodeHTML(oNode.attributes[sAttr])+'"';return sRet;},getAttribute:function(sAttr) +{return this.attributes[sAttr];},setAttribute:function(sAttr,sVal) +{this.attributes[sAttr]=sVal;},removeAttribute:function(sAttr) +{delete this.attributes[sAttr];}} +dnn.xml.JsXmlNode.registerClass('dnn.xml.JsXmlNode');dnn.xml.JsParser=function() +{this.pos=null;this.xmlArray=null;this.root=null;} +dnn.xml.JsParser.prototype={parse:function(sXml,oRoot) +{this.pos=0;this.xmlArray=sXml.split('>');this.processXml(oRoot);},getProcessString:function() +{var s=this.xmlArray[this.pos];if(s==null) +s='';return s.replace(/^\s*/,"").replace(/\s*$/,"");},processXml:function(oParent) +{var oNewParent=oParent;var bClose=this.isCloseTag();var bOpen=this.isOpenTag();while((bClose==false||(bClose&&bOpen))&&this.getProcessString().length>0) +{if(bClose) +{this.processOpenTag(oParent);this.pos+=1;} +else +{oNewParent=this.processOpenTag(oParent);this.pos+=1;this.processXml(oNewParent);} +bClose=this.isCloseTag();bOpen=this.isOpenTag();} +var s=this.getProcessString();if(bClose&&s.substr(0,1)!='<') +oParent.text=s.substr(0,s.indexOf('<'));this.pos+=1;},isCloseTag:function() +{var s=this.getProcessString();if(s.substr(0,1)=='/'||s.indexOf('-1||s.substr(s.length-1)=='/') +return true;else +return false;},isOpenTag:function() +{var s=this.getProcessString();if(s.substr(0,1)=='<'&&s.substr(0,2)!='-1) +s=s.substr(s.indexOf(' ')+1);if(s.indexOf('=')>-1) +{var bValue=false;var sName='';var sValue='';var sChar;for(var i=0;i0) +{pair=methods[i].split('=');this.callBackMethods[pair[0]]=pair[1];}}}},_cleanupxmlhttp:function() +{for(var i=0;i');this.doc.write('
    -1) +sSep='&';this.doc.write(' action="'+this.url+sSep+'__U='+this.getUnique()+'">');this.doc.write('');if(postData&&postData.length>0) +{var aryData=postData.split('&');for(var i=0;i');} +this.doc.write('');this.doc.close();this.assignIFrameDoc();this.doc.forms[0].submit();},assignIFrameDoc:function() +{if(this.iframe.contentDocument) +this.doc=this.iframe.contentDocument;else if(this.iframe.contentWindow) +this.doc=this.iframe.contentWindow.document;else if(window.frames[this.iframe.name]) +this.doc=window.frames[this.iframe.name].document;},getResponseHeader:function(sKey) +{this.assignIFrameDoc();var oCtl=dnn.dom.getById(sKey,this.doc);if(oCtl!=null) +return oCtl.value;else +return'WARNING: response header not found';},getUnique:function() +{return new Date().getTime();}} +dnn.xmlhttp.JsXmlHttpRequest.registerClass('dnn.xmlhttp.JsXmlHttpRequest'); diff --git a/Website/js/dnncore.js b/Website/js/dnncore.js new file mode 100644 index 00000000000..513a3c5b342 --- /dev/null +++ b/Website/js/dnncore.js @@ -0,0 +1 @@ +var DNN_COL_DELIMITER=String.fromCharCode(16);var DNN_ROW_DELIMITER=String.fromCharCode(15);var __dnn_m_bPageLoaded=false;if(window.addEventListener){window.addEventListener("load",__dnn_Page_OnLoad,false)}else{window.attachEvent("onload",__dnn_Page_OnLoad)}function __dnn_ClientAPIEnabled(){return typeof(dnn)!="undefined"}function __dnn_Page_OnLoad(){if(__dnn_ClientAPIEnabled()){dnn.dom.attachEvent(window,"onscroll",__dnn_bodyscroll)}__dnn_m_bPageLoaded=true}function __dnn_KeyDown(iKeyCode,sFunc,e){if(e==null){e=window.event}if(e.keyCode==iKeyCode){eval(unescape(sFunc));return false}}function __dnn_bodyscroll(){var a=document.forms[0];if(__dnn_ClientAPIEnabled()&&__dnn_m_bPageLoaded&&typeof(a.ScrollTop)!="undefined"){a.ScrollTop.value=document.documentElement.scrollTop?document.documentElement.scrollTop:dnn.dom.getByTagName("body")[0].scrollTop}}function __dnn_setScrollTop(c){if(__dnn_ClientAPIEnabled()){if(c==null){c=document.forms[0].ScrollTop.value}var a=dnn.getVar("ScrollToControl");if(a!=null&&a.length>0){var b=dnn.dom.getById(a);if(b!=null){c=dnn.dom.positioning.elementTop(b);dnn.setVar("ScrollToControl","")}}if(document.getElementsByTagName("html")[0].style.overflow!="hidden"){window.scrollTo(0,c)}}}function __dnn_SetInitialFocus(a){var b=dnn.dom.getById(a);if(b!=null&&__dnn_CanReceiveFocus(b)){b.focus()}}function __dnn_CanReceiveFocus(b){if(b.style.display!="none"&&b.tabIndex>-1&&b.disabled==false&&b.style.visible!="hidden"){var a=b.parentElement;while(a!=null&&a.tagName!="BODY"){if(a.style.display=="none"||a.disabled||a.style.visible=="hidden"){return false}a=a.parentElement}return true}else{return false}}function __dnn_ContainerMaxMin_OnClick(i,b){var g=dnn.dom.getById(b);if(g!=null){var e=i.childNodes[0];var l=dnn.getVar("containerid_"+b);var j=dnn.getVar("cookieid_"+b);var d=e.src.toLowerCase().substr(e.src.lastIndexOf("/"));var a;var h;var k;if(dnn.getVar("min_icon_"+l)){k=dnn.getVar("min_icon_"+l)}else{k=dnn.getVar("min_icon")}if(dnn.getVar("max_icon_"+l)){h=dnn.getVar("max_icon_"+l)}else{h=dnn.getVar("max_icon")}a=h.toLowerCase().substr(h.lastIndexOf("/"));var c=5;var f=dnn.getVar("animf_"+b);if(f!=null){c=new Number(f)}if(d==a){e.src=k;dnn.dom.expandElement(g,c);e.title=dnn.getVar("min_text");if(j!=null){if(dnn.getVar("__dnn_"+l+":defminimized")=="true"){dnn.dom.setCookie(j,"true",365)}else{dnn.dom.deleteCookie(j)}}else{dnn.setVar("__dnn_"+l+"_Visible","true")}}else{e.src=h;dnn.dom.collapseElement(g,c);e.title=dnn.getVar("max_text");if(j!=null){if(dnn.getVar("__dnn_"+l+":defminimized")=="true"){dnn.dom.deleteCookie(j)}else{dnn.dom.setCookie(j,"false",365)}}else{dnn.setVar("__dnn_"+l+"_Visible","false")}}return true}return false}function __dnn_Help_OnClick(a){var b=dnn.dom.getById(a);if(b!=null){if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}return true}return false}function __dnn_SectionMaxMin(f,c){var d=dnn.dom.getById(c);if(d!=null){var g=f.getAttribute("max_icon");var e=f.getAttribute("min_icon");var a=f.getAttribute("userctr")!=null;var b;if(d.style.display=="none"){f.src=e;d.style.display="";if(a){b="True"}else{dnn.setVar(f.id+":exp",1)}}else{f.src=g;d.style.display="none";if(a){b="False"}else{dnn.setVar(f.id+":exp",0)}}if(a){dnncore.setUserProp(f.getAttribute("userctr"),f.getAttribute("userkey"),b,null)}return true}return false}function __dnn_enableDragDrop(){var b=dnn.getVar("__dnn_dragDrop").split(";");var e;for(var c=0;c0){var a=dnn.dom.getById(e[0]);var d=dnn.dom.getById(e[1]);if(a!=null&&d!=null){a.setAttribute("moduleid",e[2]);dnn.dom.positioning.enableDragAndDrop(a,d,"__dnn_dragComplete()","__dnn_dragOver()")}}}}var __dnn_oPrevSelPane;var __dnn_oPrevSelModule;var __dnn_dragEventCount=0;function __dnn_dragOver(){__dnn_dragEventCount++;if(__dnn_dragEventCount%75!=0){return}var c=dnn.dom.getById(dnn.dom.positioning.dragCtr.contID);var a=__dnn_getMostSelectedPane(dnn.dom.positioning.dragCtr);if(__dnn_oPrevSelPane!=null){__dnn_oPrevSelPane.pane.style.border=__dnn_oPrevSelPane.origBorder}if(a!=null){__dnn_oPrevSelPane=a;a.pane.style.border="4px double "+DNN_HIGHLIGHT_COLOR;var e=__dnn_getPaneControlIndex(c,a);var b;var f;for(var d=0;dd&&a.controls[d].id!=c.id){b=a.controls[d]}if(e<=d&&a.controls[d].id!=c.id){f=a.controls[d];break}}if(__dnn_oPrevSelModule!=null){dnn.dom.getNonTextNode(__dnn_oPrevSelModule.control).style.border=__dnn_oPrevSelModule.origBorder}if(f!=null){__dnn_oPrevSelModule=f;dnn.dom.getNonTextNode(f.control).style.borderTop="5px groove "+DNN_HIGHLIGHT_COLOR}else{if(b!=null){__dnn_oPrevSelModule=b;dnn.dom.getNonTextNode(b.control).style.borderBottom="5px groove "+DNN_HIGHLIGHT_COLOR}}}}function __dnn_dragComplete(){var f=dnn.dom.getById(dnn.dom.positioning.dragCtr.contID);var d=f.getAttribute("moduleid");if(__dnn_oPrevSelPane!=null){__dnn_oPrevSelPane.pane.style.border=__dnn_oPrevSelPane.origBorder}if(__dnn_oPrevSelModule!=null){dnn.dom.getNonTextNode(__dnn_oPrevSelModule.control).style.border=__dnn_oPrevSelModule.origBorder}var b=__dnn_getMostSelectedPane(dnn.dom.positioning.dragCtr);var e;if(b==null){var a=__dnn_Panes();for(var c=0;c0){__dnn_m_aryPanes[__dnn_m_aryPanes.length]=new __dnn_Pane(dnn.dom.getById(b[c]),a[c])}}}var __dnn_m_aryPanes;var __dnn_m_aryModules;function __dnn_Panes(){if(__dnn_m_aryPanes==null){__dnn_m_aryPanes=new Array();__dnn_RefreshPanes()}return __dnn_m_aryPanes}function __dnn_Modules(a){if(__dnn_m_aryModules==null){__dnn_RefreshPanes()}return __dnn_m_aryModules[a]}function __dnn_getMostSelectedPane(g){var c=new dnn.dom.positioning.dims(g);var f=0;var a;var h;for(var e=0;e<__dnn_Panes().length;e++){var b=__dnn_Panes()[e];var d=new dnn.dom.positioning.dims(b.pane);a=dnn.dom.positioning.elementOverlapScore(d,c);if(a>f){f=a;h=b}}return h}function __dnn_getPaneControlIndex(f,b){if(b==null){return}var a=new dnn.dom.positioning.dims(f);var e;if(b.controls.length==0){return 0}for(var c=0;c0){e+=c+"~";this.controls[this.controls.length]=new __dnn_PaneControl(g,f);__dnn_m_aryModules[c]=g.id;f+=1}}}this.moduleOrder=e}function __dnn_PaneControl(a,b){this.control=a;this.id=a.id;this.index=b;this.origBorder=a.style.border}function __dnn_ShowModalPage(a){dnnModal.show(a,true,550,950,true,"")}function __dnncore(){this.GetUserVal=0;this.SetUserVal=1}__dnncore.prototype={getUserProp:function(b,c,a){this._doUserCallBack(dnncore.GetUserVal,b,c,null,new dnncore.UserPropArgs(b,c,a))},setUserProp:function(c,d,a,b){this._doUserCallBack(dnncore.SetUserVal,c,d,a,new dnncore.UserPropArgs(c,d,b))},_doUserCallBack:function(c,d,e,a,b){if(dnn&&dnn.xmlhttp){var f=c+COL_DELIMITER+d+COL_DELIMITER+e+COL_DELIMITER+a;dnn.xmlhttp.doCallBack("__Page",f,dnncore._callBackSuccess,b,dnncore._callBackFail,null,true,null,0)}else{alert("Client Personalization not enabled")}},_callBackSuccess:function(a,b,c){if(b.pFunc){b.pFunc(b.namingCtr,b.key,a)}},_callBackFail:function(a,b){window.status=a}};__dnncore.prototype.UserPropArgs=function(b,c,a){this.namingCtr=b;this.key=c;this.pFunc=a};var dnncore=new __dnncore(); \ No newline at end of file diff --git a/Website/release.config b/Website/release.config new file mode 100644 index 00000000000..c747f20c108 --- /dev/null +++ b/Website/release.config @@ -0,0 +1,352 @@ + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Website/web.config b/Website/web.config new file mode 100644 index 00000000000..b6dd00dab74 --- /dev/null +++ b/Website/web.config @@ -0,0 +1,351 @@ + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +